--  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 Nomo.Interpreter.External_Messages.Setting;

package body Nomo.Interpreter.External_Events_Index.Registers.Plant is

   procedure Get_Current_Event (This         : in External_Register;
                                Arrival_Time : out Positive_Time;
                                Position     : out External_Event_Index) is
   begin
      Arrival_Time :=  This.Arrival_Times (This.Current_Evidence);
      Position := This.Current_Evidence;
   end Get_Current_Event;

   procedure Get_Event (This           : in External_Register;
                        Arrival_Time   : in out Positive_Time;
                        Sensitive_Data : out External_Message;
                        Size           : in Component_Index) is
      Low_Index     : Integer := Integer (External_Events'First) + Integer (This.Current_Evidence) + 1;
      High_Index    : Integer := Integer (External_Events'Last) + Integer (This.Current_Evidence) + 1;
      Median_Index  : Integer;
      Final_Index   : External_Event_Index;
      Value         : Positive_Time;
      Arrival_Times : Times renames This.Arrival_Times;
   begin
      while Low_Index <= High_Index loop
         Median_Index := (Low_Index + High_Index) / 2;
         Value := Arrival_Times (External_Event_Index (Median_Index mod Integer (Index_Modulo)));
         if Arrival_Time < Value then
            High_Index := Median_Index - 1;
         elsif Arrival_Time > Value then
           Low_Index := Median_Index + 1;
         else
            exit;
         end if;
      end loop;
      Final_Index := External_Event_Index ( (Median_Index mod Integer (Index_Modulo)));
      if Arrival_Times (Final_Index) > Arrival_Time then
         Final_Index := External_Event_Index ( ( (Median_Index - 1) mod Integer (Index_Modulo)));
      end if;
      Arrival_Time := Arrival_Times (Final_Index);
      External_Messages.Setting.Set (Sensitive_Data, This.Trace (Final_Index), Size);
   end Get_Event;

   procedure Get_Event (This           : in External_Register;
                        Position       : in External_Event_Index;
                        Sensitive_Data : out External_Message;
                        Size           : in Component_Index) is
   begin
      External_Messages.Setting.Set (Sensitive_Data, This.Trace (Position), Size);
   end Get_Event;

end Nomo.Interpreter.External_Events_Index.Registers.Plant;
