--  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/>

package body Nomo.Interpreter.Gen_Rules_Directories.Checking is

   procedure Forget (This             : in out Checking_Directory;
                     Number_Of_Forget : in out Reference_Index_Minus;
                     Updatable        : in Reference_Index;
                     Reference        : in Reference_Index);

   procedure Forget (This             : in out Checking_Directory;
                     Number_Of_Forget : in out Reference_Index_Minus;
                     Updatable        : in Reference_Index;
                     Reference        : in Reference_Index) is
   begin
      if Is_Forget (This.References (Updatable).Reference.all) then
         Number_Of_Forget := Number_Of_Forget + 1;
         This.Last_Space := This.Last_Space + 1;
         This.Spaces (This.Last_Space) := Updatable;
         This.Trash (This.Last_Space) := This.References (Updatable);
      elsif Number_Of_Forget /= Reference_Index_Minus'First then
         This.Updatables (Reference - Number_Of_Forget):= Updatable;
      end if;
   end Forget;

   procedure Update_Relevance (This : in out Checking_Directory) is
      Number_Of_Forget : Reference_Index_Minus := Reference_Index_Minus'First;
      Updatables       : Index_Tab renames This.Updatables;
      References       : Rule_References renames This.References;
   begin
      for I in Reference_Index'First .. This.Last_Updatable loop
         Update_Relevance (References (Updatables (I)).Reference.all);
      end loop;
      if This.Tested_Reference_Index /= Reference_Index_Minus'First and then Is_Updatable (References (This.Tested_Reference_Index).Reference.all) then
         for I in Reference_Index'First .. This.Last_Updatable loop
            if Updatables (I) /= This.Tested_Reference_Index then
               Forget (This, Number_Of_Forget, Updatables (I), I);
            end if;
         end loop;
      else
         for I in Reference_Index'First .. This.Last_Updatable loop
            Forget (This, Number_Of_Forget, Updatables (I), I);
         end loop;
      end if;
      This.Last_Updatable := This.Last_Updatable - Number_Of_Forget;
   end Update_Relevance;

   procedure Select_And_Update (This        : in out Checking_Directory;
                                Rule_Tested : out Rule_Ptr) is
      References : Rule_References renames This.References;
   begin
      Rule_Tested := null;
      for I in Reference_Index'First .. This.Last_Reference loop
         Evaluate (References (I).Reference.all);
         if Is_Ongoing (References (I).Reference.all) then
            This.Tested_Reference_Index := I;
            Rule_Tested := References (I).Reference;
            exit;
         end if;
      end loop;
      if This.Last_Updatable /= Reference_Index_Minus'First then
         Update_Relevance (This);
      end if;
   end Select_And_Update;

   procedure Reset_Tested_Reference (This : in out Checking_Directory) is
   begin
      This.Tested_Reference_Index := Reference_Index_Minus'First;
   end Reset_Tested_Reference;

end Nomo.Interpreter.Gen_Rules_Directories.Checking;
