with Pipe;
package body Batch_Commands is
    Pipe_Name : constant String := "!machine.batch_streams.batch_pipe";

    package Command_Io is new Pipe.Type_Specific_Operations (Command);

    function Make (Stream_Number : Natural;
                   Inst : Instruction;
                   Job_Description : Batch_Stream.Job_Descriptor)
                  return Command is
    begin
        return Command'(Stream_Number => Stream_Number,
                        Instr => Inst,
                        The_Job => Job_Description);
    end Make;

    function Stream_Number (In_Command : Command) return Natural is
    begin
        return In_Command.Stream_Number;
    end Stream_Number;

    function The_Instruction (In_Command : Command) return Instruction is
    begin
        return In_Command.Instr;
    end The_Instruction;

    function Job_Description (In_Command : Command)
                             return Batch_Stream.Job_Descriptor is
    begin
        return In_Command.The_Job;
    end Job_Description;

    procedure Initialize is
        The_Channel : Channel;
    begin
        Open (Pipe => The_Channel, Mode => Pipe.Shared_Read, Name => Pipe_Name);
        Close (The_Channel);
    exception
        when Pipe.Name_Error =>
            Create (Pipe => The_Channel,
                    Mode => Pipe.Exclusive,
                    Name => Pipe_Name);
            Close (The_Channel);
    end Initialize;

    procedure Open_Read_Channel (The_Channel : in out Channel) is
    begin
        Open (Pipe => The_Channel, Mode => Pipe.Shared_Read, Name => Pipe_Name);
    end Open_Read_Channel;

    procedure Close_Read_Channel (The_Channel : in out Channel) is
    begin
        Close (The_Channel);
    end Close_Read_Channel;

    procedure Put (The_Command : Command) is
        The_Channel : Channel;
    begin
        Open (Pipe => The_Channel,
              Mode => Pipe.Shared_Write,
              Name => Pipe_Name);
        Command_Io.Write (Pipe.Handle (The_Channel), The_Command);
        Close (The_Channel);
    end Put;

    function Get (From_Channel : Channel) return Command is
        Result : Command;
    begin
        while End_Of_File (From_Channel) loop
            begin
                Result := Command_Io.Read (Pipe.Handle (From_Channel));
            exception
                when Pipe.End_Error =>
                    null;
            end;
        end loop;
        Result := Command_Io.Read (Pipe.Handle (From_Channel));
        return Result;
    end Get;
end Batch_Commands;