-- This program is the last attempt of artificial intelligency with Ada.
-- Elhoim is Copyright (C) 2023 Manuel ; 
--
--   This program is free software; you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation; either version 2 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 General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program; if not, write to the Free Software
--   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
--
-- Date := "2023-05-05 17:40:18"
-- Version := "0.1.4b"

with Ada.Wide_Text_Io;
use Ada;

with Gnat.OS_Lib;
use Gnat.Os_Lib;

with Gnat.Directory_Operations;
use Gnat.Directory_Operations;
With Gnat.Directory_Operations.Iteration;
use Gnat.Directory_Operations.Iteration;
with Ada.Strings.Fixed;
use Ada.Strings.Fixed;
use Ada.Strings;
with Ada.Text_Io;
use Ada.Text_Io;
with Ada.Containers.Vectors;
package body Lib.Projec is
   
   function Egual_String(Left, Right : in Name_type) return Boolean is
   begin
      
      return Left = Right;
   end Egual_String;
   
   package Filename_Vectors is new Ada.Containers.Vectors(Positive, Name_type, Egual_string);
   use Filename_Vectors;
   
   function Compare_String(Left, Right : in Name_type) return Boolean is
   begin
      
      return Left < Right;
   end Compare_String;
   
   package Sorting is new Generic_Sorting(Compare_String);
   
   procedure Load_Project_Src(Project : in out Project_Record_Type'Class;Path_Name : in String) is
      
      Project_Vector : Vector;
      
      procedure Dir_Action(Item  :        String;
			   Index :        Positive;
			   Quit  : in out Boolean) is
	 pragma Unreferenced (Index);
	 Filename : Name_type;
      begin
	 
	 if Item /= ".\." and Item /= ".\.." then
	    --Put_line(Item);
	    Move(Item, Filename, Error, Left, ' ');
	    append(Project_Vector, Filename);
	    Quit := False;
	 end if;
      end Dir_Action;
      
      procedure Iterate is new Wildcard_Iterator(Dir_Action);
      
      
   begin
      
      --Put_Line("Project iterate : " & Path_Name);
      Iterate(Path_Name & "\src\*.adb");
      Sorting.Sort(Project_Vector);
      --Put_Line("Reading filename...");
      for I in 1..Length(Project_Vector) loop
         text_io.put_line("Intex : " & integer'image(integer(I)));
	 declare
	    Filename : constant Name_type := Element(Project_Vector, Integer(I));
	 begin
            --Put_Line("Move filename...");	    
	    Move(Filename, Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_Index + 1).File_Name, Error, Left, ' ');
            --Put_Line("Reading base name of filename...");
	    Move(Base_Name(Filename), Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_Index + 1).Unit_Name, Error, Left, ' ');
            --Put_Line("Library unit_Index + 1...");
            Project.Proj_Library.Unit_Index := Project.Proj_Library.Unit_Index + 1;
            --Put_Line("1 added.");
	 end;
      end loop;
   end Load_Project_Src;
   
   procedure Load_Library(Project : in out Project_Record_Type'Class;Path_Name : in String) is
      
      Project_Vector : Vector;
      
      procedure Dir_Action(Item  :        String;
			   Index :        Positive;
			   Quit  : in out Boolean) is
	 
	 pragma Unreferenced (Index);
	 
	 Filename : Name_type;	 	 
      begin
	 
	 if Item /= ".\." and Item /= ".\.." then
	    --Put_line(Item);
	    Move(Item, Filename, Error, Left, ' ');
	    append(Project_Vector, Filename);
	    Quit := False;
	 end if;
      end Dir_Action;
      
      procedure Iterate is new Wildcard_Iterator(Dir_Action);
      
      
   begin
      
      --Put_Line("Library iterate : " & Path_Name);
      Iterate(Path_Name  & "*.ad?");
      --Put_Line("Iterate : done.");
      if (Project_Vector /= Empty_Vector) then
	 --Put_Line("Library full");
	 Sorting.Sort(Project_Vector);
	 --Put_Line("Library sorted");
	 for I in 1..Length(Project_Vector) loop
	    declare
	       Filename : constant Name_type := Element(Project_Vector, Integer(I));
	    begin
	       
	       Move(filename, Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_Index + 1).File_Name, Error, Left, ' ');
      
	       Move(Base_Name(Filename), Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_Index + 1).Unit_Name, Error, Left, ' ');
	       
	       Project.Proj_Library.Unit_Index := Project.Proj_Library.Unit_Index + 1;
	    end;
	 end loop;
      end if;
   end Load_Library;
   
   procedure Load_Ada(Project : in out Project_Record_Type'Class;Path_Name : in String) is
      
      Project_Vector : Vector;
      
      procedure Dir_Action(Item  :        String;
			   Index :        Positive;
			   Quit  : in out Boolean) is
	 
	 pragma Unreferenced (Index);
	 
	 Filename : Name_type;
      begin
	 
	 if Item /= ".\." and Item /= ".\.." then
	    --Put_line(Item);
	    Move(Item, Filename, Error, Left, ' ');
	    append(Project_Vector, Filename);
	    Quit := False;
	 end if;
      end Dir_Action;
      
      procedure Iterate is new Wildcard_Iterator(Dir_Action);
      
      
   begin
      
      --Put_Line("Library iterate : " & Path_Name);
      Iterate(Path_Name  & "*.ads");      
      Sorting.Sort(Project_Vector);
      Project.Ada_Library.Unit_Index := 0;
      for I in 1..Length(Project_Vector) loop
	 declare
	    Filename : constant Name_type := Element(Project_Vector, Integer(I));
	 begin

	    Move(Filename, Project.Ada_Library.Library_Unit(Project.Ada_Library.Unit_Index + 1).File_Name, Error, Left, ' ');
	    
	    Move(Base_Name(Filename), Project.Ada_Library.Library_Unit(Project.Ada_Library.Unit_Index + 1).Unit_Name, Error, Left, ' ');
	    
	    Project.Ada_Library.Unit_Index := Project.Ada_Library.Unit_Index + 1;
	 end;
      end loop;
   end Load_Ada;
   
   
   
   procedure Load_GtkAda(Project : in out Project_Record_Type'Class;Path_Name : in String) is
      
      Project_Vector : Vector;
      
      procedure Dir_Action(Item  :        String;
			   Index :        Positive;
			   Quit  : in out Boolean) is
	 
	 pragma Unreferenced (Index);
	 
	 Filename : Name_type;
      begin
	 
	 if Item /= ".\." and Item /= ".\.." then
	    --Put_line(Item);
	    Move(Item, Filename, Error, Left, ' ');
	    append(Project_Vector, Filename);
	    Quit := False;
	 end if;
      end Dir_Action;
      
      procedure Iterate is new Wildcard_Iterator(Dir_Action);
      
      
   begin
      
      --Put_Line("Library iterate : " & Path_Name);
      Iterate(Path_Name  & "*.ads");
      Sorting.Sort(Project_Vector);
      Project.Gtk_Library.Unit_Index := 0;
      for I in 1..Length(Project_Vector) loop
	 declare
	    Filename : constant Name_type := Element(Project_Vector, Integer(I));
	 begin
      
	    Move(Filename, Project.Gtk_Library.Library_Unit(Project.Gtk_Library.Unit_Index + 1).File_Name, Error, Left, ' ');
	    
	    Move(Base_Name(Filename), Project.Gtk_Library.Library_Unit(Project.Gtk_Library.Unit_Index + 1).Unit_Name, Error, Left, ' ');
	    
	    Project.Gtk_Library.Unit_Index := Project.Gtk_Library.Unit_Index + 1;
	 end;
      end loop;
   end Load_GtkAda;
   
   
   procedure Load_Aws(Project : in out Project_Record_Type'Class;Path_Name : in String) is
      
      Project_Vector : Vector;
      
      procedure Dir_Action(Item  :        String;
			   Index :        Positive;
			   Quit  : in out Boolean) is
	 
	 pragma Unreferenced (Index);
	 
	 Filename : Name_type;
      begin
	 
	 if Item /= ".\." and Item /= ".\.." then
	    --Put_line(Item);
	    Move(Item, Filename, Error, Left, ' ');
	    append(Project_Vector, Filename);
	    Quit := False;
	 end if;
      end Dir_Action;
      
      procedure Iterate is new Wildcard_Iterator(Dir_Action);
      
      
   begin
      
      --Put_Line("Library iterate : " & Path_Name);
      Iterate(Path_Name  & "*.ads");
      Sorting.Sort(Project_Vector);
      Project.Aws_Library.Unit_Index := 0;
      for I in 1..Length(Project_Vector) loop
	 declare
	    Filename : constant Name_type := Element(Project_Vector, Integer(I));
	 begin
      
	    Move(Filename, Project.Aws_Library.Library_Unit(Project.Aws_Library.Unit_Index + 1).File_Name, Error, Left, ' ');
	    
	    Move(Base_Name(Filename), Project.Aws_Library.Library_Unit(Project.Aws_Library.Unit_Index + 1).Unit_Name, Error, Left, ' ');
	    
	    Project.Aws_Library.Unit_Index := Project.Aws_Library.Unit_Index + 1;
	 end;
      end loop;
   end Load_Aws;
      
   
   procedure Load_Project(Project : out Project_Record_Type'Class;
			  Path_Name : in String) is
      Project_File : constant String := Path_Name & '/' & Project_Default;
      The_Project : Gnose_Project_type;
      File : File_Type;
   begin                  
                  
      Gnos.Engineering.initialize(Data_Class(Project), The_Project);
      
      
      Project.Proj_Library.Unit_Index := 0;
      
      if not Is_Regular_File(Project_Default) then
	 
	 return;
	 
      end if;
      
      Put_Line("Open : " & Project_File);
      
      Open(File, In_File, Project_File);      
      
      declare
	 
	 Project_Name : constant String := Get_Line(File);
	 Main_Line : constant String := Get_Line(File);
      begin
	 --Put_Line("Project name : " & Project_Name);
	 Project.Project_Name := new String ' (Base_Name((Project_Name(1..Index_Non_Blank(Project_Name, Backward))), ".adb"));
	 
	 begin
	    
	    Load_Project_Src(Project, Path_Name => (Path_Name & '/' & Project_Name & '/' & Project_Name));
	 exception
	    when others =>
	       null;
	 end;
	 
	 
	 if not End_Of_File(File) then
	    
	    declare
	       
	       
	       Subunit_Name : constant String := Get_Line(File);
	       
	    begin
	       
	       if Subunit_Name'Length /= 0 then
		  --Put_Line("Subunit name : " & Subunit_Name);
		  Load_Library(Project, Path_Name => (Path_Name & '/' & Project_Name & '/' & Subunit_Name & "/src/lib/"));
		  --Put_Line("Subunit name : " & Subunit_Name & " loaded.");
	       end if;
	    exception
	       when others =>
		  raise;
	    end;
	    
	    if Project.Proj_Library.Unit_Index > 1 then
	       declare
		  Prefix : string :=
		    Base_Name(Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_index).Unit_Name(1..Index_Non_Blank(Project.Proj_Library.Library_Unit(Project.Proj_Library.Unit_index).Unit_Name, Backward)), ".ads");
	       begin
		  
		  --Text_Io.Put_Line("Prefix is : " & Prefix);
		  Project.Project_Prefix := new String ' (Prefix);
	       end;
	    end if;
	    
	    while not End_Of_File(File) loop
	       --Put_Line("file found...");
	       declare
		  Subunit_Name : constant String := Get_Line(File);
	       begin	       
		  
		  if Subunit_Name'Length /= 0 then
		     --Put_Line("Subunit name : " & Subunit_Name);
		     Load_Library(Project, Path_Name => (Path_Name & '/' & Project_Name & '/' & Subunit_Name & "/src/lib/"));
		     --Put_Line("Subunit name : " & Subunit_Name & " loaded.");
		  end if;
	       exception
		  when others =>
		     raise;
	       end;
	    end loop;
	 end if;
      end;
      
      Close(File);
      
      
      
   end Load_Project;
   
   
   procedure initialize(Projects_Context : in out Projects_Context_Record'Class;
			Projects_Params  : in Projects_Parameters_Type) is
      
   begin
      Projects_Context.Projects_Params := Projects_Params;
   end Initialize;
   

   function Check_Parameters(Projects_Context : in Projects_Context_Record'Class;
			     Params : in Projects_Parameters_Type'class) return Boolean is
      
      Checked : Boolean := False;
      
   begin            
      Text_Io.Put("Projects Context :");      
      Checked := Projects_Context.Projects_Params = Parameters.Projects_Parameters_Type(Params);
      if not Checked then	 
	 Text_Io.New_Line;
	 if Projects_Context.Projects_Params.Name_Length /= Projects_Parameters_Type(Params).Name_Length then
	    Text_Io.Put_Line("Name_Length : " & 
				    Integer'Image(Projects_Context.Projects_Params.Name_Length) & " /= " &
				    Integer'Image(Projects_Parameters_Type(Params).Name_Length));
	 end if;
	 if Projects_Context.Projects_Params.Unit_Max /= Projects_Parameters_Type(Params).Unit_Max then
	    Text_Io.Put_Line("Unit_Max : " & 
				    Integer'Image(Projects_Context.Projects_Params.Unit_Max) & " /= " &
				    Integer'Image(Projects_Parameters_Type(Params).Unit_Max));	    
	 end if;
	 if Projects_Context.Projects_Params.With_Gtk /= Projects_Parameters_Type(Params).With_Gtk then
	    Text_Io.Put_Line("with Gtk : " & 
			       Boolean'Image(Projects_Context.Projects_Params.With_Gtk) & " /= " &
			       Boolean'Image(Projects_Parameters_Type(Params).With_Gtk));
	 end if;
	 if Projects_Context.Projects_Params.With_Ada /= Projects_Parameters_Type(Params).With_Ada then
	    Text_Io.Put_Line("With_Ada : " & 
			       Boolean'Image(Projects_Context.Projects_Params.With_Ada) & " /= " &
			       Boolean'Image(Projects_Parameters_Type(Params).With_Ada));	    
	 end if;
	 if Projects_Context.Projects_Params.With_Aws /= Projects_Parameters_Type(Params).With_Aws then
	    Text_Io.Put_Line("With_Aws : " & 
			       Boolean'Image(Projects_Context.Projects_Params.With_Aws) & " /= " &
			       Boolean'Image(Projects_Parameters_Type(Params).With_Aws));	    
	 end if;
	 
	 raise Program_Error;
      end if;
      Wide_Text_Io.Put_Line("Ok !");
      return Checked;
   end Check_Parameters;
      
end Lib.Projec ;