--  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.Focus.Directories.Initialization;

with Nomo.Interpreter.Premises_Index.Arrays.Initialization;

with Nomo.Interpreter.Premises_Index.Arrays.Setting;

with Nomo.Numerics.Accurately.Constants;

package body Nomo.Interpreter.Conditions_Base.Initialization is

   function Get_Information (This       : in Condition_Base;
                             Prediction : in Premise_Index) return Positive_Integer is
      use Premises_Index.Arrays.Initialization;
   begin
      return Get_Information (This.Premises, Prediction);
   end Get_Information;

   function Get_First_Landmark_Index (This : in Condition_Base) return Premise_Index is
      use Premises_Index.Focus.Directories.Initialization;
   begin
      return Get_First_Landmark_Index (This.Directory);
   end Get_First_Landmark_Index;

   function Get_Second_Landmark_Index (This : in Condition_Base) return Premise_Index is
      use Premises_Index.Focus.Directories.Initialization;
   begin
      return Get_Second_Landmark_Index (This.Directory);
   end Get_Second_Landmark_Index;

   function Get_Prediction_Index (This        : in Condition_Base;
                                  Linked_Type : in Prediction_Type_Index) return Premise_Index is
      use Premises_Index.Focus.Directories.Initialization;
   begin
      return Get_Prediction_Index (This.Directory, Linked_Type);
   end Get_Prediction_Index;

   procedure Initialize (This                       : in out Condition_Base;
                         Premises                   : in Internal_Premises;
                         Premises_Types             : in Internal_Premises_Types;
                         Properties                 : in Internal_Premises_Properties;
                         Premises_Number            : in Premise_Index;
                         Fitting_Nbr                : in Count;
                         Matchmaker_Ptr             : not null access Internal_Events_Index.Matchmakers.Matchmaker;
                         Excitatory_Specificity_Log : out Real_Accurately;
                         Inhibitory_Specificity_Log : out Real_Accurately) is
      use Focus.Directories.Initialization;
      use Premises_Index.Arrays.Setting;
      use Premises_Index.Arrays.Initialization;
      use Numerics.Accurately.Constants;
      Maximum_Of_Premises : constant Positive := Beginning.Parameters.Get_Maximum_Of_Premises;
      Excitator_Last      : Premise_Index;
      pragma Suppress (Accessibility_Check, Matchmaker_Ptr);
   begin
      This.Fitting_Nbr := Fitting_Nbr;
      This.Optimizable := Fitting_Nbr < Maximum_Of_Maximizations;
      Set (This.Premises, Premises, Premises_Number);
      Initialize (This.Directory, Premises_Types, Properties, Premises_Number);
      Excitator_Last := This.Directory.Get_Excitator_Last;
      This.Matchmaker_Ptr := Matchmaker_Ptr;
      if Excitator_Last < Premises_Number then
         Inhibitory_Specificity_Log := Sum_Specificity_Log (This.Premises, Excitator_Last + 1, Premises_Number)
           + Positive (Premises_Number - Excitator_Last) * Zero_Plus_Log + (Maximum_Of_Premises - Positive (Premises_Number - Excitator_Last)) * 4.0 * Positive_Infinity_Log;
      else
         Inhibitory_Specificity_Log := Maximum_Of_Premises * 4.0 * Positive_Infinity_Log;
      end if;
      Inhibitory_Specificity_Log := (Inhibitory_Specificity_Log) / 2.0;
      Excitatory_Specificity_Log := Sum_Specificity_Log (This.Premises, First_Excitator, Excitator_Last);
      This.Specificity_Log_Min := Natural (Excitator_Last) * Zero_Plus_Log + (Maximum_Of_Premises - Natural (Excitator_Last)) * 4.0 * Positive_Infinity_Log;
      Excitatory_Specificity_Log := (Excitatory_Specificity_Log + This.Specificity_Log_Min) / 2.0;
      This.Specificity_Log := Excitatory_Specificity_Log;
   end Initialize;

end Nomo.Interpreter.Conditions_Base.Initialization;
