with Ada.Strings, Ada.Strings.Fixed;
use Ada.Strings, Ada.Strings.Fixed;
with Pragmarc.Ansi_Tty_Control;
use Pragmarc.Ansi_Tty_Control;

with PragmARC.Math.Functions;
with Ada.Text_Io;
use Ada;
package body Libsens.Neural_Network is
   
   
   package Real_Io is new Ada.Text_Io.Float_Io(Real);
   package Real_Math is new PragmARC.Math.Functions (Supplied_Real => Real);
   
   
   procedure Train(Filename   : in String;
		   Samples    : in Samples_Type;
		   Reuse      : in Boolean;
		   Converged  : in Real;
		   Max_Epochs : in Positive) is
      
      procedure Get_Input (Pattern : in Positive;
                           Input : out Node_Set;
                           Desired : out Node_Set) is
	 
      begin

         Input := Samples(Pattern*2-1);
         Desired := Samples(Pattern*2);
      end Get_Input;
      
      
      package Rem_NN_Train is new REM_NN(Num_Input_Nodes => Width,
					 Num_Hidden_Nodes => hidden,
					 Num_Output_Nodes => Width,
					 New_Random_Weights => not reuse,
					 Weight_File_Name => Filename,
					 Input_To_Output_Connections => False,
					 Num_Patterns => Samples'Length/2,
					 Get_Input => Get_Input);
      
      
      Response : Rem_NN_Train.Output_Set := (others => 0.0);      
      
      Banner : String(1..80) := (others => Character'Val(32));
      RMS_Error : Real := 10.0;

      Error     : Real := 0.0;
      Epoch : Natural := 0;
      
      begin         
         loop
            --Text_Io.Put_Line("passe par ici");
            Text_Io.Put (Clear_Screen);
            Move("Welcome to " & Filename & " Network Generator." , Banner, Ada.Strings.Error, Center);
            Text_Io.Put_Line(Bold_mode & Banner & Normal_mode);
            
            Text_Io.New_Line;

		 Text_Io.Put_Line("Training artificial neural network " & " length=" & Integer'Image(Samples'Length/2));
            Text_Io.Put ("Epoch");
            Text_Io.put (Integer'Image (Epoch) );
            Text_Io.Put(" => RMS_Error: ");

            Real_Io.Put(RMS_Error);
            Text_Io.Put_line(Integer'Image(Integer(((converged)/RMS_Error)*100.0)) &
			       '%');
	    --Text_Io.Put_Line("passe par là");
            
            if integer((((80.0/RMS_Error)/80.0)/(0.1/converged))*8.0) > 0 then
               Text_Io.Put(Reverse_Video &
                   Integer((((80.0/RMS_Error)/80.0)/(0.1/converged))*8.0) * ' ' &
			     Normal_Mode);
            end if;

            RMS_Error := 0.0;
        All_Patterns :
            for Pattern in 1..Samples'Length/2 Loop
               REM_NN_Train.Train;
               REM_NN_Train.Respond (Pattern, Response);
               for I in Response'Range loop
                  Error := Error + (samples((Pattern*2)-1)(i) -   Response(i) );
               end loop;
               RMS_Error := RMS_Error + ((Error/Real(Response'Length)) ** 2);
               Error := 0.0;
            end loop All_Patterns;
            RMS_Error := Real_Math.Sqrt(RMS_Error / Real (Samples'Length/2)) ;
            if (RMS_Error <= Converged) or
              (Epoch >= Max_Epochs) then
               exit;
            end if;
	    --Text_Io.Put_Line("passe enfin par là");
            Epoch := Epoch + 1;
         end loop;
         REM_NN_train.Save_Weights;

      
      
      
      
      
   end Train;
   
   function Respond(Filename   : in String;
		    Problem : in Node_Set) return Node_Set is
      
      
      procedure Get_Input (Pattern : in Positive;
                           Input : out Node_Set;
                           Desired : out Node_Set) is
	 
      begin
	 
         Input := Problem;
         Desired := (others => 0.0);
      end Get_Input;
      
      
      package Rem_NN_Expl is new REM_NN(Num_Input_Nodes => Width,
					Num_Hidden_Nodes => hidden,
					Num_Output_Nodes => Width,
					New_Random_Weights => false,
					Weight_File_Name => Filename,
					Input_To_Output_Connections => False,
					Num_Patterns => 1,
					Get_Input => Get_Input);
      
            
      Response : Rem_NN_Expl.Output_Set := (others => 0.0);      
      
      
   begin
      Rem_Nn_Expl.Respond(1, Response);
      return Response;
   end Respond;
   
   
   
   
end Libsens.Neural_Network;