with PragmARC.Rem_Nn_Wrapper;
use PragmARC.Rem_Nn_Wrapper;
with Text_Io;
use Text_Io;
package body Libsens.Neural_Generator is                        
   
   
   generic
      Size : natural;
      type Item_Type is(<>);
   package Generic_Extended_Binary_Code is
      subtype Code_Type is Node_Set(1..Size);
      Code_Init : Code_Type := (others => 0.0);
      
      function Code_of(Item : in Item_Type) return Code_Type;
      function Item_Of(Code : in Code_Type) return Item_Type;
      
   end Generic_Extended_Binary_Code;
   package body Generic_Extended_Binary_Code is
   


   
   function Code_of(Item : in Item_Type) return Code_Type is
      Code : Code_Type := Code_Init;
      Pos : Natural := Item_Type'Pos(Item);
   begin
      if Pos = 0 then
   	 return Code_Init;
      else
   	 for Index in reverse Code_Type'Range loop
   	    if Real(Pos rem 2) /= 1.0 then
   	       Code(index) := 0.0;
   	    else
   	       Code(index) := 1.0;
   	    end if;
   	    Pos := Pos/2;
   	 end loop;
   	 return Code;
      end if;
   end Code_of;

   function Item_Of(Code : in Code_Type) return Item_Type is
      Pos : Natural := 0;
   begin
      for I in reverse Code_Type'Range loop
   	 if Code(I) = 1.0 then
   	    Pos := Pos + 2**(Code_Type'Length-I);
   	 else
   	    null;
   	 end if;
      end loop;
      return Item_Type'Val(Pos);
   end Item_Of;
   end Generic_Extended_Binary_Code;

   subtype Gm_Range is Natural range 0..127;
   
   package Note_Code is new Generic_Extended_Binary_Code(7, Gm_Range);
   use Note_Code;
   
   type Chord_array is array (1..6) of Gm_Range;
   type Chords_Set_array is array (1..12) of Chord_Array;
   
   Chords_Set : Chords_Set_Array :=
     (
      (64, 68, 73, 0, 0, 0),
      (66, 71, 75, 0, 0, 0),
      (66, 71, 75, 80, 0, 0),
      (68, 75, 80, 83, 0, 0),
      (68, 75, 80, 83, 85, 0),
      (75, 80, 83, 86, 90, 0),
      (75, 80, 83, 86, 90, 92),
      (80, 83, 86, 90, 92, 95),
      (80, 83, 86, 90, 92, 95),
      (68, 75, 80, 83, 0, 0),
      (75, 80, 83, 86, 90, 0),
      (64, 68, 73, 0, 0, 0));

   procedure Rand_Init(Samples : in out Samples_Type) is
      Polyphony : Natural := 0;
      Float_Gen : Generator;
      Code : Code_Type := (others => 0.0);
      Item : Gm_Range := 0;
   begin
      Samples := (others => (others => 0.0));
      for I in Chords_set'Range loop
	 Put_Line("line " & Integer'Image(I));
	 for J in Chord_Array'range loop	   
	    Code := (others => 0.0);
	    Code := Code_Of(Chords_Set(I)(J));
	    for K in Code'range loop
	       
	       Samples(I)((J-1)*7+K) := Code(K);
	    end loop;
	    Code := (others => 0.0);
	    Code := Code_Of(100);
	    for K in Code'range loop
	       
	       Samples(I)((J-1)*7+7+K) := Code(K);
	    end loop;
	    Code := (others => 0.0);
	    Code := Code_Of(8);
	    for K in Code'range loop
	       
	       Samples(I)((J-1)*7+14+K) := Code(K);
	    end loop;
	 end loop;
      end loop;
   end Rand_Init;
   
   --  procedure Rand_Init(Samples : in out Samples_Type) is
   --     Polyphony : Natural := 0;
   --     Float_Gen : Generator;
   --  begin
   --     Reset(Float_Gen);
   --     for I in Samples'Range loop
   --  	 for J in reverse 1..Network_Size loop	   
   --  	    if Real(Random(Float_Gen)) >= 0.5 then
   --  	       Samples(I)(J) := 1.0;
	       
   --  	    else
   --  	       Samples(I)(J) := 0.0;
   --  	    end if;	    
   --  	 end loop;
	 
   --     end loop;
   --  end Rand_Init;
   
   Chord : Chord_Array := (66, 71, 75, 80, 0, 0);
   
   function Problem_Rand return Node_Set is
      Set : Node_Set(1..Network_Size) := (others => 0.0);      
      Code : Code_Type := (others => 0.0);
   begin      
      for I in chord'Range loop
	 Put_Line("TOTO 0");
	 Code := (others => 0.0);
	 Code := Code_Of(Chord(I));
	 for J in Code'Range loop
	    Set((I-1)*7+J) := Code(J);
	    
	 end loop;
	 Put_Line("TOTO 1");
	 Code := (others => 0.0);
	 Code := Code_Of(100);
	 for K in Code'range loop
	    
	    Set((I-1)*7+7+K) := Code(K);
	 end loop;
	 Put_Line("TOTO 2");
	 Code := (others => 0.0);
	 Code := Code_Of(8);
	 for K in Code'range loop
	    
	    Set((I-1)*7+14+K) := Code(K);
	 end loop;
	 Put_Line("TOTO 3");
      end loop;
      return Set;
   end Problem_Rand;
   
   
end Libsens.Neural_Generator;