--  Copyright (2008-2013) Cédric Coussinet (cedric.coussinet@nomoseed.net)
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU Affero General Public License as published
--  by the Free Software Foundation, either version 3 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
--  GNU Affero General Public License for more details.

--  You should have received a copy of the GNU Affero General Public License
--  along with this program. If not, see <http://www.gnu.org/licenses/>

with Standard_Random;

with Nomo.Interpreter.Plant.Scopes;

with Nomo.Interpreter.External_Events_Index.Registers.Plant;

package body Nomo.Interpreter.Event_Memory.External.Plant is

   procedure Get_Current_Event (Scope_Index  : in Positive;
                                I            : out Input_Type_Index;
                                Arrival_Time : out Positive_Time;
                                Position     : out External_Event_Index) is
      use Interpreter.Plant.Scopes;
      use Standard_Random;

      type Pointed_Event is record
         Index        : Input_Type_Index;
         Arrival_Time : Positive_Time;
         Position     : External_Event_Index;
      end record;

      Selection : array (1 .. External_Scopes (Scope_Index).Last) of Pointed_Event;
      Last      : Positive := 1;
   begin
      Selection (1).Index := External_Scopes (Scope_Index).List (1);
      External_Events_Index.Registers.Plant.Get_Current_Event (This (Selection (1).Index), Arrival_Time, Position);
      Selection (1).Position := Position;
      Selection (1).Arrival_Time := Arrival_Time;
      for I in 2 .. Selection'Last loop
         External_Events_Index.Registers.Plant.Get_Current_Event (This (External_Scopes (Scope_Index).List (I)), Arrival_Time, Position);
         if Arrival_Time = Selection (1).Arrival_Time then
            Last := Last + 1;
            Selection (Last).Index := External_Scopes (Scope_Index).List (I);
            Selection (Last).Position := Position;
            Selection (Last).Arrival_Time := Arrival_Time;
         elsif Arrival_Time > Selection (1).Arrival_Time then
            Last := 1;
            Selection (1).Index := External_Scopes (Scope_Index).List (I);
            Selection (1).Position := Position;
            Selection (1).Arrival_Time := Arrival_Time;
         end if;
      end loop;
      Last := Standard_Random.Random mod Last + 1;
      I := Selection (Last).Index;
      Arrival_Time := Selection (Last).Arrival_Time;
      Position := Selection (Last).Position;
   end Get_Current_Event;

   procedure Get_Event (I              : in Input_Type_Index;
                        Arrival_Time   : in out Positive_Time;
                        Sensitive_Data : out External_Message;
                        Size           : in Component_Index) is
   begin
      External_Events_Index.Registers.Plant.Get_Event (This (I), Arrival_Time, Sensitive_Data, Size);
   end Get_Event;

   procedure Get_Event (I              : in Input_Type_Index;
                        Position       : in External_Event_Index;
                        Sensitive_Data : out External_Message;
                        Size           : in Component_Index) is
   begin
      External_Events_Index.Registers.Plant.Get_Event (This (I), Position, Sensitive_Data, Size);
   end Get_Event;

end Nomo.Interpreter.Event_Memory.External.Plant;
