with Bounded_String;
with List_Generic;
with Time_Utilities;
package Batch_Stream is

    subtype Job_Identifier is Natural range 1 .. 128;

    type Job_Descriptor is private;
    -- A data structure used to describe a batch job

    Nil : constant Job_Descriptor;

    type Job_State is (Waiting, Running, Done, Cancelled);
    -- Waiting means the job has been placed on the queue, but not run yet
    -- Running means that the job is currently running
    -- Done means that the job has terminated, and the entry in the queue
    -- can be deleted or reused
    -- Cancelled means that the job has been cancelled by a user, and the
    -- entry in the queue can be deleted or reused

    function Make (Job_Number : Job_Identifier;
                   Command : String;
                   Context : String;
                   User_Name : String;
                   Error_Filename : String;
                   Input_Filename : String;
                   Output_Filename : String;
                   Start_Time : Time_Utilities.Time;
                   Restartable : Boolean;
                   Response : String := "<PROFILE>") return Job_Descriptor;
    -- Construct a job descriptor, and set the state to waiting

    procedure Set_State (Of_Job : in out Job_Descriptor; To : Job_State);

    procedure Set_Number (Of_Job : in out Job_Descriptor; To : Job_Identifier);
    function Number (Of_Job : Job_Descriptor) return Job_Identifier;
    function Command (Of_Job : Job_Descriptor) return String;
    function Context (Of_Job : Job_Descriptor) return String;
    function Username (Of_Job : Job_Descriptor) return String;
    function Error_Filename (Of_Job : Job_Descriptor) return String;
    function Input_Filename (Of_Job : Job_Descriptor) return String;
    function Output_Filename (Of_Job : Job_Descriptor) return String;
    function Start_Time (Of_Job : Job_Descriptor) return Time_Utilities.Time;
    function Restartable (Of_Job : Job_Descriptor) return Boolean;
    function State (Of_Job : Job_Descriptor) return Job_State;
    function Response (Of_Job : Job_Descriptor) return String;

    -- A batch stream is a permanent representation of the batch queue
    -- stream on the R1000, it exists across machine crashes.

    procedure Initialize_Stream (Stream_Number : Natural);
    procedure Delete_Stream (Stream_Number : Natural);

    generic
        with procedure Visit (Stream_Number : Natural);
    procedure Traverse_Streams;
    procedure Add_To_Stream (Stream_Number : Natural;
                             The_Job : in out Job_Descriptor);
    -- Adds a job to the batch stream.  The job_identifier will be
    -- updated in the job_descriptor

    procedure Change_State (Of_Job_Number : Job_Identifier;
                            To : Job_State;
                            In_Stream : Natural;
                            Successful : out Boolean);

    procedure Get_Next_Job_To_Run (From_Stream : Natural;
                                   The_Job : out Job_Descriptor;
                                   Found_One : out Boolean);

    type Iterator is limited private;

    procedure Initialize (Stream_Number : Natural; The_Iter : in out Iterator);

    function Value (Of_Iter : Iterator) return Job_Descriptor;

    procedure Next (In_Iter : in out Iterator);

    function Done (For_Iter : Iterator) return Boolean;

    File_Access_Error : exception;
    Queue_Is_Full : exception;
private  
    Job_String_Length : constant Natural := 256;
    subtype Job_String is Bounded_String.Variable_String (Job_String_Length);

    type Job_Descriptor is
        record
            Number : Job_Identifier;
            Command : Job_String;
            Context : Job_String;
            Username : Job_String;
            Error_Filename : Job_String;
            Input_Filename : Job_String;
            Output_Filename : Job_String;
            Start_Time : Time_Utilities.Time;
            State : Job_State;  
            Response : Job_String;
            Restartable : Boolean;
        end record;


    Nil : constant Job_Descriptor :=
       Job_Descriptor'(Number => Job_Identifier'First,
                       Command => Bounded_String.Value ("", Job_String_Length),
                       Context => Bounded_String.Value ("", Job_String_Length),
                       Username => Bounded_String.Value ("", Job_String_Length),
                       Error_Filename =>
                          Bounded_String.Value ("", Job_String_Length),
                       Input_Filename =>
                          Bounded_String.Value ("", Job_String_Length),
                       Output_Filename =>
                          Bounded_String.Value ("", Job_String_Length),
                       Response => Bounded_String.Value
                                      ("<PROFILE>", Job_String_Length),
                       Start_Time => Time_Utilities.Get_Time,
                       Restartable => False,
                       State => Waiting);

    package Batch_List is new List_Generic (Job_Descriptor);
    type Iterator is new Batch_List.List;
end Batch_Stream;