-- 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
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 := 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 =>

   	    Words_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 := 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;
      
   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(Item_Of(Code), Words));
   	    exception
   	       when others =>
   		  null;
   	    end;
   	    Line := new Wide_String ' (Buffer.all);
   	 end;
      end loop;
      
      
      return Line.all;
   exception
      when others =>
   	 return Line.all;
   end Output2string;
   --                     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
	    
   	    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;

      Wide_Text_Io.Close(File);
      Text_Io.Put_Line("Done.");
      
   end Init_Samples;


end El.Hander ;