-- elhoim is full object organizer with editor and command interpreter.
-- Elhoim is Copyright (C) 2023 Manuel De Girardi ; 
--
--   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-26 17:40:38"
-- Version := "0.6.6b"
with El.Intell;
with El.Classe ;
with El.Player ;
with El.Window ;
with El.Search ;
with El.Enumes ;
with El.Errors ;
with El.Parole ;
with El.Strings ;

with Ansi_Console;

With Ada.Unchecked_Deallocation;
use Ada;
with Gnat.Semaphores;
use Gnat.Semaphores;
with Gnat.Sha1;
use Gnat;
generic
   Glossary_Filename : String;
   Width_Line :Word_Range;
   Max_Words : Lexical_Range;
   Samples_Max : Positive;
   Network_Filename : String;
   Lines : Line_Range;
   Cols  : Column_Range;
   
   with package Classes is new El.Classe (<>);
   with package Window is new El.Window (<>);

package El.Engine is
   use Enumes;   
   use Player ;
   use Strings;
   package Intelligency is new El.Intell (Glossary_Filename, Width_Line, Max_Words, Samples_Max, Network_Filename, Lines, Cols, Classes, window);
   
   type Engine_Record;
   
   use Classes;
   
   
   
   
   
   
   function equal (Left, Right : in Abstracted_Access) return Boolean;
   function "<" (Left, Right : in Abstracted_Access) return Boolean;
   function uniform  (E : in Abstracted_Access) return Float;
   function Heuristic (E : in Abstracted_Access) return Float;
   
   type E_Array is array (Positive range <>) of Abstracted_Access;
   
   function Successors (E : in Abstracted_Access) return E_Array;
   
   
   
   package Path_Finding is new El.Search.Path_Finding
     (Abstracted_Access, Heuristic, Uniform, Equal, "<", E_Array, Successors);
   
   
   procedure Astar (Start : in Abstracted_Access;
		    Goal : in Abstracted_Access;
		    Close  : out Abstracted_Vectors.Vector);
   
   
   task type Astar_Process (Engine : access Engine_Record) is
      entry Init (Start : in Abstracted_Access;
		  Goal : in Abstracted_Access);
      entry Close_Set(Closed_Out : out Abstracted_Vectors.Vector; End_Of_Task : out Boolean);
      entry Halt;
   end Astar_Process;
   
   
   use Ansi_Console;
   
   type Window_Access is access Classes.Windows.Window_Type;
   
   procedure Win_Free is new Unchecked_Deallocation(Classes.Windows.Window_Type, Window_Access);
   
   
   Main_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (1, 1, 
      Lines, Cols,
      Classes.Windows.Single_Line_Frame, Cyan, Red);
   
   
   Input_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (4, 2, 
      3, Cols-2,
      Classes.Windows.Single_Line_Frame, blue, white);
   
   
   Output_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (9, 2,
      4, (Cols-2)/2,
      Classes.Windows.Single_Line_Frame, green, magenta);
   
   Internal_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (15, 2,
      4, (Cols-2)/2,
      Classes.Windows.Single_Line_Frame, white, blue);
                  
   
   
   User_Objects_Tree_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (21, 2, 
      Lines_Left/2, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Blue, white);
   
   
   User_Objects_View_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (21+Lines_Left/2+1, 2, 
      Lines_Left/2-1, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Cyan, yellow);
   
   Ai_Objects_Tree_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (21, (Cols-2)/4+3, 
      Lines_Left/2, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Blue, white);
   
   
   Ai_Objects_View_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (21+Lines_Left/2+1, (Cols-2)/4+3, 
      Lines_Left/2-1, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Cyan, yellow);   
   
   
   Start_State_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (9, (Cols-2)/2+3, 
      10, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Cyan, yellow);
   
   End_State_Win : constant Window_Access := new Classes.Windows.Window_Type '
     (9, (Cols-2)/2+3+(Cols-2)/4, 
      10, (Cols-2)/4,
      Classes.Windows.Single_Line_Frame, Cyan, yellow);
   
   
   use Intelligency.Expr_Vectors;
   use Intelligency.Prompt_Vectors;
   --use Classes;
   use Classes.Abstracted_Vectors;
   
   procedure Accounting_Wins_Draw(Wins : Accounting_Windows_Type);
   
   
   Accounting_Wins : Accounting_Windows_Type(21, (cols-2)/2+3);
   
   
   
   type Main_Windows_Type is tagged
      record
	 
	 Main_Win_Ptr : Window_Access := Main_Win;
	 
	 Input_Win_Ptr : Window_Access := Input_Win;
	 Output_Win_Ptr : Window_Access := Output_Win;
	 Internal_Win_Ptr : Window_Access := Internal_Win;
	 
	 User_Objects_Tree_Win_Ptr : Window_Access := User_Objects_Tree_Win;
	 User_Objects_View_Win_Ptr : Window_Access := User_Objects_View_Win;
	 
	 Ai_Objects_Tree_Win_Ptr : Window_Access := Ai_Objects_Tree_Win;
	 Ai_Objects_View_Win_Ptr : Window_Access := Ai_Objects_View_Win;
	 
	 
	 Start_State_Win_Ptr : Window_Access := Start_State_Win;
	 End_State_Win_Ptr : Window_Access := End_State_Win;	 	 
	 
	 Accounting_Wins : Accounting_Windows_Type(21, (Cols-2)/2+3);
	 
      end record;
   
   
   
   procedure Wins_Draw(Main_Wins : Main_Windows_Type);      
   
   Wins_Main : Main_Windows_Type;
   

   
   type Object_Counter is array (Tag_Name'Range) of Natural;
   
   type Terminal_record is tagged
      record
	 Write_Line_Index : Natural := 1;
	 Wins_Main : Main_Windows_Type;
	 Page_Index : Natural := 0;
	 Line : Intelligency.V_Line_Range := 1;
	 Col  : Column_Range := 1;            
	 V_Win_First : Intelligency.V_Index_Type := 0;
	 V_Win_Last  : Intelligency.V_Index_Type := 0;
	 Expr_List : Intelligency.Expr_Vectors.Vector;	    
	 Expr : Intelligency.Expression_Type := (others => Wide_Character'Val(32));	    
	 Prompt_List : Intelligency.Prompt_Vectors.Vector;
	 Prompt : Name_Type;
	 Obj    : Abstracted_Access;
	 V_Switch : Objects_Vector;
	 Obj_Cur  : Abstracted_Access;
	 Top      : Abstracted_Access;
	 Path_Index : Natural := 0;
      end record;
   procedure Save(T : in Terminal_Record);
   
   procedure Save (Object : in Abstracted_Access;
		   Filename : in String);
   
   
   procedure Restore(T : in out Terminal_Record;
   		     Win : in Classes.Windows.Window_Type;
   		     State : in Classes.Windows.Window_Type;
   		     Filename : in String);
   
   procedure Right_Exec (T : in out Terminal_Record;
   			 Win : in Classes.Windows.Window_Type;
   			 Prompt : out Name_Type);
   
   procedure Update(T : in out Terminal_Record;
   		    Prompt : in Name_Type;
   		    Expr   : in Intelligency.Expression_Type);
   
   
   procedure Switch(T : in out Terminal_Record;
   		    Num : in Abstracted_Index;
   		    Prompt : out Name_Type;
   		    Success : out boolean) ;
   
   
   procedure State_Draw(Where : in Classes.Windows.Window_Type;
			State : in Intelligency.Account.Account_State_Type);
   
   procedure Global_Content_Print (Object : Abstracted_Access;
   				   Win       : in Classes.Windows.Window_Type;
   				   Win_Index : in out Natural);
   
   -- Attribute the tree sum of heuristical and uniform values for all nodes.
   procedure Valuate_Tree (Object  : in Abstracted_Access);
   
   -- Estimate the ucost (unifom) and hcost (heuristic) values of full tree.
   procedure Evaluate_Tree (Object  : in Abstracted_Access;
			    Ucost   : out Float;
			    Hcost   : out float);
   
   
   type Terminal_Access is access all Terminal_Record;
   
   procedure Terminal_Free is new Ada.Unchecked_Deallocation(Terminal_Record, Terminal_Access);
   
   
   type Instruction_Enum is 
     (
      Null_Inst, Open_Output, Open_Input, Close_Output, Close_Intput,
      Learn, Respond, Set_Init, Tree_Loading, Imagine, Run, Set_Sentence, Get_Tree, Get_Env,
      Set_Samples
     );
   
   
   
   
   
   task type Kernel_Process (Engine : access Engine_Record) is
      
      entry Initialize;
      entry Set_Init(Object : in out Abstracted_Access);
      entry Load_Tree;
      entry Imagine(Object : in out Abstracted_Access);
      entry Set_Sentence(Line : in Wide_String);
      entry Engine_Run;
      entry Get_Tree(Object : out Abstracted_Access);
      entry Get_Env (Object : out Abstracted_Access);
      entry Halt;
   end Kernel_Process;
   
   
   
   task type Engine_Process (Engine : access Engine_Record) is
      entry Halt (End_Of_Program : out Boolean);
      entry Initialize;
      entry Receive (Cmd : in Instruction_Enum;
		     Arg : in Wide_String);
      entry Receive (wchar : in Wide_Character);
      entry Dialup (Sentence : in Parole.Word_Array;
		    Terminal : in out Terminal_Record;
		    Response : out Wide_String_Access;
		    Internal : out Wide_String_Access
		   );
      entry Mode(Mode : out Mode_Enum);
      entry Reset;
      entry Switch (Mode : in Mode_Enum);
      entry Lock;
      entry Unlock;
      entry Set_On_Esc(Is_Escape : in Boolean);      
      entry Page_Down;
      entry Page_Up;
      entry Up_Arrow;
      entry Down_Arrow;
      entry Left_Arrow;
      entry Right_Arrow;
      entry Full_Screen;
      entry Del;
      entry Begin_Of;
      entry End_Of;
      entry Overwrite;
      entry Screen_Print;
      entry Shutdown;
      entry Send (Who, Where, How, Why, How_Mutch, How_Many : in Wide_String; Objects : out Intelligency.Object_Set);      
   end Engine_Process;
   
   
   procedure Help(Win       : in Classes.Windows.Window_Type;
		  Win_Index : in out Positive;
		  Name      : out Name_Type);
   
   
   
   
   
   
   
      
   
   
   
   type Identified_Domain_Record is tagged
      record	
	 Id     : Identity_Record;
	 Term   : Terminal_Record;
	 Domain : Intelligency.Ai_Domain_Record(8192);
      end record;
   
   type Identified_Domain_Access is access all Identified_Domain_Record;
   
   type Identified_Domain_Arrays is array (Positive range <>) of Identified_Domain_Record;
   
   type Domain_Set(Max_Users : Positive) is tagged
      record
	 Set : Identified_Domain_Arrays(1..Max_Users);
      end record;
   
   
   
   
   type Engine_Record(Max_Users : Positive) is new Intelligency.Intell_Record with
      record
	 Astar_Proc  : Astar_Process (Engine_Record ' access);
	 Engine_Proc : Engine_Process (Engine_Record ' access);
	 Users       : User_Set(Max_Users);
	 Domains     : Domain_Set(Max_Users);
	 Kernel_Proc : Kernel_Process (Engine_Record ' access);
      end record;
   
   package Users_Manager is
      
      
      
      function Add_User(Logname : in String;
			Passwd : in Sha1.Message_Digest) return Boolean;
      

      
      function Check_passwd(Logname : in String;
			    Passwd : in Sha1.Message_Digest) return Boolean;
      
      
   private
      
      
      -- User define --
      
      subtype Logname_Type is String (1..64);
      
      
      
      type User_Type is tagged
	 record
	    Logname : Logname_Type := (others => Character ' Val (32)) ;
	    Passwd : Sha1.Message_Digest;
	 end record;                  
      
      procedure Initialize(User : out User_Type;
			   Name : in String);
      -- Get player named "Name".
      
      
      
      procedure Set_Pass(User : in out User_Type;
			 Pass : in Sha1.Message_Digest);
      -- Set password for player.
      
      function Check_Pass(User : in User_Type;
			  Pass : in Sha1.Message_Digest) return Boolean;
      -- Return True is getted password is valid. False else.      
      
      
      
      
   end Users_Manager;
   
   use Users_Manager;
end El.Engine ;