-- 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 Ada.Strings.Wide_Fixed;
use Ada.Strings.Wide_Fixed;
with Ada.Wide_Characters.Handling;
use Ada.Wide_Characters.Handling;
with Ada.Strings.UTF_Encoding.Wide_Strings;
with Ada.Strings;

with El.Strings;

with Ada.Text_Io;

with Gnat.Os_Lib;
use Gnat;

package body El.Hander is
   
   pragma Ellaborate_All (El.Hander);
   
   use Strings;
   
   function String2input (Line : in Wide_String; Words : in out Glossary_Type) return Input_Type is
      
      
      procedure Add_Word (Word : in Wide_String; Input : in out Input_Type; Pos : in Word_Range) is
   	 Lexique : File_Type;	       	    
   	 Key     : Word_Type;	    	       
   	 Code : Code_Type;	    
      begin

   	 Key := Word_Type'Val(T_Language'pos(Keyword(Word, Words)));

   	 Code := Code_Of(key);

   	 for J in Code'Range loop
   	    Input((Pos-1) * Code_Type'Length+J) := code(J);			
   	 end loop;

      exception
   	 when Specification_Error =>

   	    Glossary.Add(Word, Key_Count(Words)+1, Words);

   	    Wide_Text_Io.Open(Lexique, Wide_Text_Io.Append_File, "data" & Os_Lib.Directory_Separator & Glossary_Filename, "WCEM=8");

   	    Wide_Text_Io.Put_Line(Lexique, Word);
   	    Wide_Text_Io.Close(Lexique);

   	    Key := Word_Type'Val(T_Language'Pos(Keyword(Word, Words)));

   	    Code := Code_Of(Key);

   	    for J in Code'Range loop
   	       Input((Pos-1) * Code_Type'Length+J) := code(J);
   	    end loop;

      end Add_Word;
      
      
      
      
      function Add_Wchar (Wchar : in Wide_Character; To : in out Wide_String_Access) return Wide_String_Access is
   	 Buffer : Wide_String_Access;
      begin
   	 if To /= null then

   	    Buffer := new Wide_String ' (To.all  & Wchar);

   	    Wide_Free(To);	    
   	    return Buffer;
   	 else

   	    Buffer := new Wide_String ' (Wchar & "");
   	    Wide_Free(To);

   	    return Buffer;
   	 end if;
      end Add_wchar;
      
      Input     : Input_Type := (others => 0.0);
      
      Top       : natural := 0;
      Done      : Boolean := False;
      Item      : Word_Range := 1;	    
      Wchar     : Wide_Character := ' ';
      
      Word : Wide_String_Access := new Wide_String ' ("");
      Buffer : Wide_String_Access;
   begin

      if Index_Non_Blank (Line) = 0 then
   	 return Input;
      end if;
      Top := 1;

      for iter in Line'Range loop

   	 Wchar := Line(Iter);
   	 if Is_Letter(Wchar) then

   	    Word := Add_wchar(Wchar, Word);
	    
	 elsif Is_Special(Wchar) then

	    if Iter = Line'Last then

	       if Top < Iter then

		  Add_Word(Word.all, Input, Item);
		  
		  Item := Item + 1;
		  
		  Word := Add_wchar(Wchar, Word);
		  
		  Add_Word(Word.all, Input, Item); 			
		  
		  Item := Item + 1;
		  
   		  Wide_Free(Word);
	       else

		  Word := Add_wchar(Wchar, Word);
		  
		  Add_Word(Word.all, Input, Item);
		  
		  Wide_Free(Word);
	       
		  Item := Item + 1;
	       
		  Top := Iter + 1;
	       end if;
	    elsif Top < Iter then		 

   	       Add_Word(Word.all, Input, Item);

   	       Item := Item + 1;

   	       Wide_Free(Word);

   	       Word := Add_wchar(Wchar, Word);

   	       Add_Word(Word.all, Input, Item);
	       
	       Wide_Free(Word);
	       
	       Item := Item + 1;
	       
   	       Top := Iter + 1;
   	       
   	    else

   	       Word := Add_wchar(Wchar, Word);
	       
	       Add_Word(Word.all, Input, Item);
	       
	       Wide_Free(Word);
	       
	       Item := Item + 1;
	       
   	       Top := Iter + 1;
   	       
   	    end if;	       	    
   	 end if;
      end loop;	 

      return Input;
   end String2input;
   
   

   

   function Output2string(Output : Output_Type; Words : in Glossary_Type) return Wide_String is
      Line: Wide_String_access := new Wide_String ' ("");      
      Buffer : Wide_String_access;
      
      wik_line : constant wide_string := "<a href=""https://fr.wikipedia.org/wiki/";
     top_line : constant wide_string := "<a href=""https://fr.wiktionary.org/wiki/";
     end_line : constant wide_string := "</a>";
      
   begin
      for I in 0..Width_Line-1 loop

   	 declare
   	    Code : Code_Type := (others => 0.0);
   	 begin
   	    for J in Code_Type'Range loop
	       
   	       Code(J) := output(I*Code_Type'Length+J);
   	    end loop;
	    
   	    begin
   	       Wide_Free(buffer);
   	       Buffer := new Wide_String ' (Line.all & image(T_Language'Val(Word_Type'Pos(Item_Of(Code))), Words));
   	    exception
   	       when others =>
   	    	  null;
   	    end;
   	    Line := new Wide_String ' (Buffer.all);
   	 end;
      end loop;
      --  for I in Line'Range loop
      --  	 if Line(I) = Wide_Character'Val(32) then
	    
      --  	    Line(I) := '_';
      --  	 end if;
      --  end loop;
      return Line.all;
   exception
      when others =>
   	 return Line.all;
   end Output2string;
   
   function webOutput2string(Output : Output_Type; Words : in Glossary_Type) return Wide_String is
      Line: Wide_String_access := new Wide_String ' ("");      
      Buffer : Wide_String_access;
      
      wik_line : constant wide_string := "<a href=""https://fr.wikipedia.org/wiki/";
     top_line : constant wide_string := "<a href=""https://fr.wiktionary.org/wiki/";
     end_line : constant wide_string := "</a>";
      
   begin
      for I in 0..Width_Line-1 loop

   	 declare
   	    Code : Code_Type := (others => 0.0);
   	 begin
   	    for J in Code_Type'Range loop
	       
   	       Code(J) := output(I*Code_Type'Length+J);
   	    end loop;
	    declare
	       word : constant wide_string := image(T_Language'Val(Word_Type'Pos(Item_Of(Code))), words);
	    begin
	       if word'length > 1 and then ada.strings.wide_fixed.index_non_blank(word) /= 0 then
		  if is_upper(word(1)) then
		     Buffer := new Wide_String ' (Line.all & wik_line & word & """ class=""nom"">" & word & end_line);
		  else
		     Buffer := new Wide_String ' (Line.all & top_line & word & """>" & word & end_line);
		  end if;
		  wide_free(Line);
		  Line := new Wide_String ' (Buffer.all);
			wide_free(buffer);
	       elsif word'length = 1 then
		  Buffer := new Wide_String ' (Line.all & word);
		  wide_free(Line);
		  Line := new Wide_String ' (Buffer.all);
		  wide_free(buffer);
	       end if;
	    exception
	       when others =>
		  null;
	    end;
	    
   	    --  begin
   	    --     Wide_Free(buffer);
   	    --     Buffer := new Wide_String ' (Line.all & image(T_Language'Val(Word_Type'Pos(Item_Of(Code))), Words));
   	    --  exception
   	    --     when others =>
   	    --  	  null;
   	    --  end;
   	    Line := new Wide_String ' (Buffer.all);
	 exception
	    when others =>
	       null;
   	 end;
      end loop;
      --  for I in Line'Range loop
      --  	 if Line(I) = Wide_Character'Val(32) then
	    
      --  	    Line(I) := '_';
      --  	 end if;
      --  end loop;
      return Line.all;
   exception
      when others =>
   	 return Line.all;
   end webOutput2string;

   
   --                     End From/to string                             --
   ------------------------------------------------------------------------
   
   
   ------------------------------------------------------------------------
   --                     init_samples                                   --
   
   procedure Init_Samples(Samples  : in out Neural_Train.Sample_Set_Type;
   			  Words    : out Glossary_Type;
   			  Filename : in String) is
      File        : Wide_Text_Io.File_Type;
      Buffer      : Neural_Train.Sample_Type;
      Is_Input    : Boolean := True;
      Index       : Positive := 1;
   begin
      Text_Io.Put_Line("Samples set initialization...");
      Wide_Text_Io.Open(File, Wide_Text_Io.In_File, Filename, "WCEM=8");
      Text_Io.Put_Line("Samples set : reading a file : " & Filename);
      
      while not Wide_Text_Io.End_Of_File(File) loop
	 
   	 declare
   	    Line : constant Wide_String := Ada.Strings.UTF_Encoding.Wide_Strings.Encode(Wide_Text_Io.Get_Line(File));
	    
   	 begin
--	    Text_Io.Put_Line(Character'Val(13) & Positive ' Image (Index));
					     
   	    if Is_Input then
	       
   	       Buffer.Input := Neural_Train.Input_Type(String2input(Line, Words));
   	       Is_Input := False;
	       
   	    else
	       
   	       Buffer.output := Neural_Train.Output_Type(String2input(Line, Words));
	       
   	       Samples(Index) := Buffer;
	       
   	       Buffer.Input := (others => 0.0);
   	       Buffer.Output := (others => 0.0);
   	       Index := Index + 1;
   	       Is_Input := True;
	       
   	    end if;
   	 end;
	 
   	 exit when Index > Samples'Length;
	 
      end loop;
      Text_Io.New_Line;
      Wide_Text_Io.Close(File);
      Text_Io.Put_Line("Done.");
      
   end Init_Samples;


end El.Hander ; 
