--  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 Ada.Strings.Unbounded;

with Basic_Sax.File_Parser;
pragma Elaborate_All (Basic_Sax.File_Parser);

package body Nomo.Compiler is

   type Porportions_Reader is new Basic_Sax.File_Parser.Reader with record
      Number_Of_Types              : Positive;
      Number_Of_Rules              : Positive;
      Number_Of_External_Operators : Natural;
      Number_Of_Internal_Operators : Natural;
      Number_Of_External_Scopes    : Natural;
      Number_Of_Internal_Scopes    : Natural;
      Maximum_Of_Premises          : Natural;
      Maximum_Of_Components        : Natural;
      Number_Of_Input_Types        : Natural := 0;
   end record;

   procedure Start_Element (Handler : in out Porportions_Reader;
                            Name    : in String;
                            A       : in Basic_Sax.Attributes);
   pragma Unreferenced (Start_Element);

   procedure Start_Element (Handler : in out Porportions_Reader;
                            Name    : in String;
                            A       : in Basic_Sax.Attributes) is
      use Ada.Strings.Unbounded;
      Local_Name : constant String := Name (Index(To_Unbounded_String (Name), ":") + 1 .. Name'Last);
   begin
      if Local_Name = "proportions" then
         for I in 1 .. Basic_Sax.Get_Quantity (A) loop
            if Basic_Sax.Get_Name (A, I) = "number_of_types" then
               Handler.Number_Of_Types := Positive'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "number_of_rules" then
               Handler.Number_Of_Rules := Positive'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "number_of_operator_input" then
               Handler.Number_Of_External_Operators := Natural'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "number_of_operator_other" then
               Handler.Number_Of_Internal_Operators := Natural'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "number_of_scope_input" then
               Handler.Number_Of_External_Scopes := Natural'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "number_of_scope_other" then
               Handler.Number_Of_Internal_Scopes := Natural'Value (Basic_Sax.Get_Value (A, I));
            elsif Basic_Sax.Get_Name (A, I) = "maximum_of_components" then
               Handler.Maximum_Of_Components := Natural'Value (Basic_Sax.Get_Value (A, I));
            end if;
         end loop;
      elsif Local_Name = "maximum_of_premises" then
         Handler.Maximum_Of_Premises := Natural'Value (Basic_Sax.Get_Value (A, 1));
      elsif Local_Name = "type" then
         for I in 1 .. Basic_Sax.Get_Quantity (A) loop
            if Basic_Sax.Get_Name (A, I) = "category" then
               if Basic_Sax.Get_Value (A, I) = "input" then
                  for I in 1 .. Basic_Sax.Get_Quantity (A) loop
                     if Basic_Sax.Get_Name (A, I) = "id" then
                        if Handler.Number_Of_Input_Types < Natural'Value (Basic_Sax.Get_Value (A, I)) then
                           Handler.Number_Of_Input_Types := Natural'Value (Basic_Sax.Get_Value (A, I));
                        end if;
                     end if;
                  end loop;
               end if;
            end if;
         end loop;
      end if;
   end Start_Element;

   procedure Compile (Code_File                    : String;
                      Number_Of_Types              : Positive;
                      Number_Of_Rules              : Positive;
                      Number_Of_External_Operators : Natural;
                      Number_Of_Internal_Operators : Natural;
                      Number_Of_External_Scopes    : Natural;
                      Number_Of_Internal_Scopes    : Natural;
                      Maximum_Of_Premises          : Natural;
                      Maximum_Of_Components        : Natural;
                      Number_Of_Input_Types        : Natural);

   procedure Compile (Code_File                    : String;
                      Number_Of_Types              : Positive;
                      Number_Of_Rules              : Positive;
                      Number_Of_External_Operators : Natural;
                      Number_Of_Internal_Operators : Natural;
                      Number_Of_External_Scopes    : Natural;
                      Number_Of_Internal_Scopes    : Natural;
                      Maximum_Of_Premises          : Natural;
                      Maximum_Of_Components        : Natural;
                      Number_Of_Input_Types        : Natural) is separate;

   procedure Compile (Code_Path : in String) is
      Reader  : Porportions_Reader;
   begin
      Basic_Sax.File_Parser.Parse (Reader, Code_Path);
      Compile (Code_Path,
               Reader.Number_Of_Types,
               Reader.Number_Of_Rules,
               Reader.Number_Of_External_Operators,
               Reader.Number_Of_Internal_Operators,
               Reader.Number_Of_External_Scopes,
               Reader.Number_Of_Internal_Scopes,
               Reader.Maximum_Of_Premises,
               Reader.Maximum_Of_Components,
               Reader.Number_Of_Input_Types);
   end Compile;

end Nomo.Compiler;
