--  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.Premises_Index.Arrays.Getting;

package body Nomo.Interpreter.Premises_Index.Focus.Directories.Initialization is

   function Get_Prediction_Index (This            : in Premises_Directory;
                                  Prediction_Type : in Prediction_Type_Index) return Premise_Index is
   begin
      for Property in Excitatory_Property'Range loop
         for I in This.Types_Ranges (Property).First .. This.Types_Ranges (Property).Last loop
            if This.Premises_Ranges (I).Index = Prediction_Type then
               return This.Premises_Ranges (I).First;
            end if;
         end loop;
      end loop;
      raise Constraint_Error;
   end Get_Prediction_Index;

   function Get_First_Landmark_Index (This : in Premises_Directory) return Premise_Index is
   begin
      for Property in Excitatory_Property'Range loop
         for I in This.Types_Ranges (Property).First .. This.Types_Ranges (Property).Last loop
            if This.Premises_Ranges (I).Index in Landmark_Type_Index then
               return This.Premises_Ranges (I).First;
            end if;
         end loop;
      end loop;
      return Premise_Index'First;
   end Get_First_Landmark_Index;

   function Get_Second_Landmark_Index (This : in Premises_Directory) return Premise_Index is
   begin
      for Property in Excitatory_Property'Range loop
         for I in This.Types_Ranges (Property).First .. This.Types_Ranges (Property).Last loop
            if This.Premises_Ranges (I).Index in Landmark_Type_Index then
               if This.Premises_Ranges (I).Size > 1 then
                  return This.Premises_Ranges (I).First + 1;
               end if;
            end if;
         end loop;
      end loop;
      return Premise_Index'First;
   end Get_Second_Landmark_Index;

   procedure Initialize (This            : in out Premises_Directory;
                         Internal_Types  : in Internal_Premises_Types;
                         Last_Premises   : in Internal_Premises_Properties;
                         Premises_Number : in Premise_Index) is
      use Premises_Index.Arrays.Getting;
      Index_Focus    : Premises_Focus_Index := 0;
      First_Premise  : Premise_Index := 0;
   begin
      This.Premises_Last := Premises_Number;
      This.Excitator_Last := Get (Last_Premises, Excitatory_Evidence);
      if This.Excitator_Last = 0 then
         This.Excitator_Last := Get (Last_Premises, Excitatory_Intention);
      end if;
      for P in Premise_Property'Range loop
         if Get (Last_Premises, P) /= 0 then
            Index_Focus := Index_Focus + 1;
            This.Types_Ranges (P).First := Index_Focus;
            First_Premise := First_Premise + 1;
            This.Premises_Ranges (Index_Focus).Index := Get (Internal_Types, First_Premise);
            This.Premises_Ranges (Index_Focus).First := First_Premise;
            This.Premises_Ranges (Index_Focus).Last := First_Premise;
            This.Premises_Ranges (Index_Focus).Size := 1;
            for I in First_Premise + 1 .. Get (Last_Premises, P) loop
               if Get (Internal_Types, I) = This.Premises_Ranges (Index_Focus).Index then
                  This.Premises_Ranges (Index_Focus).Last := I;
                  This.Premises_Ranges (Index_Focus).Size := This.Premises_Ranges (Index_Focus).Size + 1;
               else
                  Index_Focus := Index_Focus + 1;
                  This.Premises_Ranges (Index_Focus).Index := Get(Internal_Types, I);
                  This.Premises_Ranges (Index_Focus).First := I;
                  This.Premises_Ranges (Index_Focus).Last := I;
                  This.Premises_Ranges (Index_Focus).Size := 1;
               end if;
            end loop;
            First_Premise := Get (Last_Premises ,P);
            This.Types_Ranges (P).Last := Index_Focus;
         end if;
      end loop;
   end Initialize;

end Nomo.Interpreter.Premises_Index.Focus.Directories.Initialization;
