-- elhoim is full object organizer with editor and command interpreter.
-- Elhoim is Copyright (C) 2023 Manuel De Girardi ; 
--
--   <one line to give the program's name and a brief idea of what it does.>
--   Copyright (C) 19yy  <name of author>
--
--   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;  

with El.Shared ; 
with El.Errors ; 
with El.Outils ; 
with El.Operat ; 
with El.Result ; 
with El.Classe ; 
with El.Params ; 
with El.Applic ;
with El.Interf ;
with El.Center ; 
with El.Enumes ;
with El.Window ; 
with El.Styles ; 
with El.Compil ;
with El.Strings;

with Windows_Console;
with PragmARC.Menu_Handler;

with Ada.Text_Io;
with Ada.Wide_Text_Io;
with Ada.Characters.Handling;
use Ada.Characters;
with Ada.Strings.Wide_Fixed;
use Ada.Strings.Wide_Fixed;
use Ada.Strings;
with Ada.Strings.Fixed;
with Ada.Calendar ;
use Ada.Calendar ;



with Gnat.Os_Lib;

with Ansi_Console;
procedure Elhoim is
use Gnat;
   use Os_Lib;   
   Color     : constant String := Character'Val(27) & "[01;36m";
   Normal    : constant String := Character'Val(27) & "[00m";
   
   The_World : constant String := "world";
   User_Val  : constant String := "LOGNAME";
   Lang_Val  : constant String := "LANG";
   
   
   The_Lang  : constant String_Access := Getenv(Lang_Val);
   The_User  : constant String_access := Gnat.Os_Lib.Getenv(User_val);
   
   type Lang_Enum is (En, Fr, C);
   Lang      : Lang_Enum := En;      
   
   En_Msg : constant String := "Hello";
   Fr_Msg : constant String := "Salut";
   C_Msg  : constant String := "Error";
   
   
   C_Text  : constant String := "I come from a standard C";	    
   En_Text : constant String := "I come from the France !";
   Fr_Text : constant String := "je suis venu de France !";
   package T_Io renames Ada.Text_Io;
   package W_Io renames Ada.Wide_Text_Io;
   

   use Ada;
   --use Strings;
   use Ada.Strings.Fixed;
   --use Ada.Characters;
   use Ansi_Console;
   use El.Styles ;
   use El.Errors ;
   use El.Enumes ;
   use El.Errors ;
   use El.Shared ; 
   use El.Operat ;
   use El.Result ;
   use El.Params ;
   use El.Interf ;
   use El.Compil ;
   use El.Strings;
   
   
   
   

   use El.Outils ;
   procedure Clear is
   begin
      Clear_Screen;
      W_Io.Put(Handling.To_Wide_String
	    (Ascii.Esc & "[" & 
	       Handling.To_String
	       (Trim(Handling.To_Wide_String(Integer'Image(1)), 
		     left)) & ";"                         
	       & Handling.To_String(Trim(Handling.To_Wide_String(Integer'Image(1)), 
				left)) & "H"));               
   end Clear;
   
   function To_Version (From : String) return El.Version_Record is

      New_Release : El.Release_Enum := El.Release_Enum ' First;
      New_Revision : El.Revision_Range := El.Revision_Range'First;
      New_Minor : El.Minor_Range := El.Minor_Range'First;
      
      First_Dot : Natural := 0;
      Second_Dot : Natural := 0;      
      
      New_Version : El.Version_Record;
      
   begin
      Second_Dot := Fixed.Index(From, ".", Strings.Backward);
      First_Dot :=  Fixed.Index(From, ".");
      if (First_Dot = 0) or (Second_Dot = 0) then
	 raise Program_Error;
      end if;
      
      New_Release := El.Release_Enum'Value(Character'Image(From(From'Last)));            
      New_Revision := El.Revision_Range'Value(From(Second_Dot+1..From ' Last-1));
      New_Minor := El.Minor_Range'Value(From(First_Dot+1..Second_Dot-1));            
      
      New_Version.Revision := New_Revision;      
      New_Version.Minor := New_Minor;
      New_Version.Release := New_Release;
      return New_Version;
   exception
      when others =>
	 T_Io.Put_Line("Exception in To_Version when updating version.");
	 raise;
   end To_Version;

   New_Version : El.Version_Record;
   Is_New_Version : Boolean := False;
   
   Elhoim_Applic : El.Applic.Applic_Record;
   
   
   Lines : El.Line_Range := 67;
   Cols  : El.Column_Range := 240;
   
   All_Result : Spawn_Result_Record;
   Clean_Result : Spawn_Result_Record;
   Mrproper_Result : Spawn_Result_Record;
   enlight_Result : Spawn_Result_Record;
   Arch_Result : Spawn_Result_Record;
   Update_Result : Spawn_Result_Record;
   
   Ptr_Max : Positive := 6536;
   
   The_Style, An_Style : Style_Enum := Color_And_Color;
   User_Text           : Wide_String_Access := new Wide_String ' ("");
   
   Exit_Result : Spawn_Result_Record;
   Errno : Integer := 0;
begin   
   
   Elhoim_Applic.Initialize;
   
   declare
	 
      Help_Parameter : constant Parameter_Tagged_Record_Type :=
	El.Applic.Get_Parameter(Elhoim_Applic, Help);
      Version_Parameter : constant Parameter_Tagged_Record_Type :=
	El.Applic.Get_Parameter(Elhoim_Applic, El.Params.Version);
      quiet_Parameter : constant Parameter_Tagged_Record_Type :=
	El.Applic.Get_Parameter(Elhoim_Applic, quiet);
      update_Parameter : constant Parameter_Tagged_Record_Type :=
      	El.Applic.Get_Parameter(Elhoim_Applic, Update);
      Geometry_Parameter : constant Parameter_Tagged_Record_Type :=
      	El.Applic.Get_Parameter(Elhoim_Applic, Geometry);
      Style_Parameter : constant Parameter_Tagged_Record_Type :=
      	El.Applic.Get_Parameter(Elhoim_Applic, Style);
      Input_Text_Parameter : constant Parameter_Tagged_Record_Type :=
      	El.Applic.Get_Parameter(Elhoim_Applic, Input_Text);
      
      
      
      
      
      
   begin
      
      if Help_Parameter.Is_Setted then
	 El.Applic.Parameters_Descriptions(Elhoim_Applic);	 
	 return;
      else
	 if Version_Parameter.Is_Setted then
	    T_Io.Put_Line(El.To_String(El.Shared.Version));	    
	    return;	    
	 elsif Update_Parameter.Is_Setted then	    
	    if Update_Parameter.Value'Length /= 0 then
	       New_Version := To_Version
		 (Handling.To_String(Update_Parameter.Value.all));
	       if not (El."="(New_Version, El.Shared.Version)) then
	 	  Is_New_Version := False;
	       end if;
	    end if;
	 elsif not Quiet_Parameter.Is_Setted then
	    El.Applic.Print_Parameters(Elhoim_Applic);	    
	 end if;
	 
      end if;
      
      
      if not Quiet_Parameter.Is_Setted then	 
	 
	 if The_Lang /= null then
	    begin
	       Lang := Lang_Enum'Value(The_Lang.all(1..2));
	    exception
	       when Constraint_Error =>
		  T_Io.Put_Line("Uncknow language ; ");
	    end;
	 end if;	       
	 
	 
	 delay 0.1;
	T_Io. New_Line;
	 delay 0.2;
	 
	 T_Io.Put_Line(Handling.To_String(((The_User'Length+En_Msg'Length+10) *  '-')));
	 case Lang is	 
	    when En =>
	       T_Io.Put_Line("-- " & En_Msg & ' ' & Color & 
			       The_User.all & Normal & " ! " & " --");
	    when Fr =>
	       T_Io.Put_Line("-- " & Fr_Msg & ' ' & Color & 
			       The_User.all & Normal & " ! " & " --");	   
	    when C =>
	       T_Io.Put_Line("-- " & C_Msg & ' ' & Color & 
			       The_User.all & Normal & " ! " & " --");
	 end case;      
	 T_Io.New_Line;
	 delay 0.5;
	 case Lang is
	    when En =>		  		  
	       for Wchar in En_Text'Range loop
		  T_Io.Put(En_Text(Wchar));
		  delay 0.025;
	       end loop;
	    when Fr =>
	       T_Io.New_Line;
	       for Wchar in Fr_Text'Range loop
		  T_Io.Put(En_Text(Wchar));
		  delay 0.025;
	       end loop;
	    when C =>
	       T_Io.New_Line;
	       for Wchar in C_Text'Range loop
		  T_Io.Put(En_Text(Wchar));
		  delay 0.025;
	       end loop;
	 end case;
	 T_Io.New_Line;
	 delay 1.0;
      end if;

      if Geometry_Parameter.Is_Setted then
	 Lines := Lines_Number(Geometry_Parameter.Value.all);
	 Cols := Columns_Number(Geometry_Parameter.Value.all);
      end if;
      
      if Style_Parameter.Is_Setted then
	 begin
	    The_style := Style_Enum'value(Handling.To_String(Style_Parameter.Value.all));
	    An_Style := The_Style;
	 exception
	    when others =>
	       W_Io.Put_Line("Style error : not an style");
	       raise;
	 end;
      end if;
      
      if Input_Text_Parameter.Is_Setted then
	 User_Text := new Wide_String ' (Input_Text_Parameter.value.all);
      end if;
	 
   
      
   
      declare
	 package Windows is new Windows_Console
	   (Elhoim_Applic.Get_lines, Elhoim_Applic.Get_cols);      
	 package The_Window is new El.Window
	   (Elhoim_Applic.Get_Lines, Elhoim_Applic.Get_Cols, Windows, An_Style);
	 
	 use The_Window;	 
	 
	 Glossary_Filename : Os_Lib.String_Access := new String '("glossary.txt");
	 Width_Line : El.Word_Range := 80;
	 Max_Words : El.Lexical_Range := 1023;
	 Samples_Max : Positive := 112;
	 Network_Filename : Os_Lib.String_Access := new String ' ("elhoim");
	 
	 package Classes is new El.Classe (Lines_Max-21, 24, Windows);
	 use Classes;
	 
	 
	 
	 
	 
	 package This_Center is new El.Center 
	   (Ptr_Max, Elhoim_Applic, The_Window, 
	    Glossary_Filename.all, Width_Line, Max_Words, Samples_Max, Network_Filename.all,
	    Classes, 
	    --Heuristic, Uniform, Equal, "<", E_Array, Successors, 
	    Lines, cols);
	 
	 use This_Center;
	 
	 Elhoim_Center : Center_Record;
	 
	 --Pid : Os_Lib.Process_Id;
	 Args : Os_Lib.Argument_List_Access := Os_Lib.Argument_String_To_List(Cmd_Line);
	 
	 
	 Update : Boolean := False;
	 
      begin
	 --Clear;
	 Os_Lib.Normalize_Arguments(Args.all);
	 Elhoim_Center.Initialize(10000, "data/Lexique383.tsv");
	 
	 
	 El.Class_Ranking_Init(El.Top_Classes);
	 
	 El.Sort_Init(El.Top_classes);
	 
	 Elhoim_Center.Classes_Ranking := new El.Rank_Array ' (El.Top_Classes.all);
	 
	 
	 
	 Elhoim_Center.Main_Win.Initialize
	   (1, 1, Elhoim_Center.Get_Lines,
	    Elhoim_Center.Get_Cols, Cyan, white);
	 
	 
	 
	 
	 Elhoim_Center.Msg_Win.Initialize
	   (Elhoim_Center.Get_Lines/2-1,
	    Elhoim_Center.Get_Cols/2-20, 3, 40, Cyan, white);
	 
	 
	 
	 
	 The_Window.Draw_Window(Elhoim_Center.Main_Win);
	 

	 
	 
	 
	 The_Window.Draw_Window(Elhoim_Center.Msg_Win);
	 
	 
	 Elhoim_Center.Msg_Win.Draw_Text
	   (1, (20-The_User'Length/2-6), white, 
	    Handling.To_Wide_String
	      ("Hello" & 
		 ' ' & Color & The_User.all & Normal & ' ' & '!')
	   );      
	 
	 delay 2.0;
	 
	 Elhoim_Center.Center_Proc.Initialize(Auth_Mode, User_Text.all);
	 
	 
     Main_Loop :
	 loop
	    
	    Elhoim_Center.Work_Proc.Wait;
	    
	    declare
	       package Main_Menu is new PragmARC.Menu_Handler(80, 25);
	       use Main_Menu.V_String;

	       Menu : constant Main_Menu.Menu_Info := (5, True, To_Bounded_String("Main menu"),
						       (
							To_Bounded_String("Realy Quit"),
							To_Bounded_String("Choose new mode"),
							To_Bounded_String("Do nothing"),							
							To_Bounded_String("hello !"),
							To_Bounded_String("Compile and Restart")
						       ),
						      5);
	       
	       Main_Choice : Natural := 0;
	       
	       Mode_Menu : constant Main_Menu.Menu_Info := (4, False, To_Bounded_String("Mode menu"),
							    (
							     To_Bounded_String("Dialog mode"),
							     To_Bounded_String("Devel mode"),
							     To_Bounded_String("Organizer mode"),
							     To_Bounded_String("Multi mode")
							    )
							   );
	       
	       Mode_Choice : Natural := 0;
	       New_Mode    : Mode_Enum := Null_Mode;
	    begin
	       
	       
	       Main_Choice := Main_Menu.Process(Menu);
	       case Main_Choice is
		  when 1 =>
		     Elhoim_Center.Center_Proc.Restart;
		     Elhoim_Center.Center_Proc.Halt;
		     exit;
		  when 2 =>
		     
		     Mode_Choice := Main_Menu.Process(Mode_Menu);
		     
		     case Mode_Choice is
			when 1 | 3 | 4 =>
			   New_Mode := Mode_Enum'Val(Mode_Choice+2);
			   Elhoim_Center.Center_Proc.Restart;
			   Elhoim_Center.Console_Proc.Switch(New_Mode);
			   
			when 2 =>
			   
		       Upgrade :
			   loop
			      begin
				 W_Io.New_Line;
				 W_Io.Put("Would you like upgrade this project ? (y/o or n) : ");
				 declare
				    Response : constant Wide_String := W_Io.Get_Line;
				 begin
				    if (Response(1) = 'o') or (Response(1) = 'y') then
				       W_Io.Put("Enter the new version : ");
				       declare
					  Version_String : constant String := T_Io.Get_Line;
				       begin					  
					  loop
					     T_Io.Put_Line("The new version is " & Version_String);
					     W_Io.Put("This informations are exect (y/o or n) or Ctrl+D to abort : ");
					     declare
						Is_exact : constant Wide_String := W_Io.Get_Line;
					     begin
						if (Is_Exact(1) = 'o') or (Is_Exact(1) = 'y') then
						   
						   W_Io.Put_Line("please, wait...");
						   El.Compil.Initialize;   
						   W_Io.Put_Line("Done.");
						   
						   Set_Start_Time;
						   W_Io.Put_Line("TOTO 7");
						   To_Update(To_Version(Version_String));
						   W_Io.Put_Line("TOTO 8");
						   Update := True;
						   exit Upgrade;
						end if;
						exit;
					     exception
						when W_Io.End_Error =>
						   exit Upgrade;
					     end;					     
					  end loop;					  
				       end;
				    else
				       exit;
				    end if;
				 end;
			      exception
				 when W_Io.End_Error =>
				    null;
			      end;
			   end loop Upgrade;
			   New_Mode := Mode_Enum'Val(Mode_Choice+2);
			   W_Io.Put_Line("TOTO 4");
			   Elhoim_Center.Center_Proc.Restart;
			   W_Io.Put_Line("TOTO 5");
			   Elhoim_Center.Console_Proc.Switch(New_Mode);
			   
			when 5 =>
			   Elhoim_Center.Center_Proc.Restart;
			when others =>
			   raise Program_Error;
		     end case;
		  when 3 =>
		     Elhoim_Center.Center_Proc.Restart;		     
		     Elhoim_Center.Console_Proc.Switch(Dialog_Mode);		     
		  when 4 =>
		     
		     T_Io.Put_Line(((The_User'Length+En_Msg'Length+10) *  '-'));
		     case Lang is	 
			when En =>
			   T_Io.Put_Line("-- " & En_Msg & ' ' & Color & The_User.all & Normal & " ! " & " --");
			when Fr =>
			   T_Io.Put_Line("-- " & Fr_Msg & ' ' & Color & The_User.all & Normal & " ! " & " --");	   
			when C =>
			   T_Io.Put_Line("-- " & C_Msg & ' ' & Color & The_User.all & Normal & " ! " & " --");
		     end case;      
		     T_Io.New_Line;
		     case Lang is
			when En =>		  		  
			   for Wchar in En_Text'Range loop
			      T_Io.Put(En_Text(Wchar));
			      delay 0.025;
			   end loop;
			when Fr =>
			   T_Io.New_Line;
			   for Wchar in Fr_Text'Range loop
			      T_Io.Put(En_Text(Wchar));
			      delay 0.025;
			   end loop;
			when C =>
			   T_Io.New_Line;
			   for Wchar in C_Text'Range loop
			      T_Io.Put(En_Text(Wchar));
			      delay 0.025;
			   end loop;			    
		     end case;
		     T_Io.New_Line;
		     Elhoim_Center.Center_Proc.Restart;		     
		     Elhoim_Center.Console_Proc.Switch(Dialog_Mode);		     
		     
		  when 5 =>
		     if Update then
			
			--  --Text_Io.Put_Line("-- check for New Specifications...");
			New_Description := Check_Modification_To_New_Description;
			--  --Text_Io.Put_Line("-- check for New Implementation...");
			New_Action := Check_Modification_To_New_Action;
			
			
			if New_Description then
			   --Text_Io.Put_Line("-- Edditting minor version...");
			   To_Minor;
			   
			end if;
			
			if New_Action then
			   --Text_Io.Put_Line("-- Edditting revision version...");
			   To_Revision;
			   
			end if;
			
			if New_Action and New_Description then
			   
			   
			   --Text_Io.Put_Line("-- Edditting major version...");
			   
			   To_Major;
			else
			   
			   --Text_Io.Put_Line("-- Edditting release version...");
			   
			   To_Release;
			   
			end if;
			
			
			Exit_Result := Spawn("make all", "Err.txt");
			
			-- Make update.
			--Text_Io.Put_Line("-- Making update...");
			Exit_Result := Spawn("make update", "Out_File.txt");
			
			--Text_Io.Put_Line("-- Version Update...");
			-- update Version !
			Version_Update(El.Shared.Version, Errno);
			
			if Errno /= 0 then
			   raise Program_Error;
			end if;
		     end if;
		     Elhoim_Center.Center_Proc.Restart;
		     Elhoim_Center.Center_Proc.Halt;
		     ---------------------------------------------------------------------
		     --                                Restart                          --
		     ---------------------------------------------------------------------
		     Errno := Os_Lib.Spawn("elhoim/bin/elhoim", Args.all);
		     --Pid := Os_Lib.Non_Blocking_Spawn("elhoim/bin/elhoim", Args.all);
		     --Exit_Result := Spawn(Normalize_Quoted_Argument("sh -c ""elhoim/bin/elhoim " & Cmd_Line & " &""") , "Out_File.txt");
		     
		     ---------------------------------------------------------------------
		     --                                                                 --
		     ---------------------------------------------------------------------
		     delay 1.0;
		     exit;
		     
		  when others =>
		     raise Program_Error;
	       end case;
	    exception
	       when Spec_error =>
		  null;
	    end;	    
	 end loop Main_Loop;

	 
	 --  Clear;
	 --  Elhoim_Center.Main_Win.Initialize
	 --    (1, 1, Elhoim_Center.Get_Lines-1,
	 --     Elhoim_Center.Get_Cols, Cyan, white);
	 --  The_Window.Draw_Window(Elhoim_Center.Main_Win);
	 
	 
	 --  The_Window.Draw_Window(Elhoim_Center.Msg_Win);
	 
	 
	 --  for Line in Elhoim_Applic.Get_Lines/2..Elhoim_Applic.Get_Lines-3 loop
	 --     The_Window.Draw_Window(Elhoim_Center.Main_Win);
	 --     Elhoim_Center.Main_Win.Draw_Text
	 --       (Line, 1, white, Handling.To_Wide_String
	 --  	 ("Good by" & ' ' & Color & The_User.all & Normal & ' ' & '!')
	 --       );
	 --     delay 0.05;
	 --  end loop;
	 --  delay 0.2;
	 --  T_Io.New_Line; 
	 --  delay 0.1;
	 
      exception
	 when T_Io.End_Error =>
	    T_Io.Put_Line("End error : Program aborted by user");
	    Elhoim_Center.Center_Proc.Restart;
	    Elhoim_Center.Center_Proc.Halt;	    
	    
	 when Spec_Error =>
	    T_Io.Put_Line("Specification error");
	    Elhoim_Center.Center_Proc.Restart;
	    Elhoim_Center.Center_Proc.Halt;	    
	    
	    raise;
	    
	 when Impl_Limit =>
	    T_Io.Put_Line("Implementation limit");
	    Elhoim_Center.Center_Proc.Restart;
	    Elhoim_Center.Center_Proc.Halt;
	    
	    raise;
      end;
      
   end;

exception
   when T_Io.End_Error =>            
      T_Io.Put_Line("Program aborted by user");
   when Spec_Error =>      
      T_Io.Put_Line("Specification Error");
      raise;
   when Impl_Limit =>      
      T_Io.Put_Line("Implementation Error");
      raise;

end Elhoim ;