with Glib;                              use Glib;
with Glib.Object;                       use Glib.Object;

with Gtk.Handlers;                      use Gtk.Handlers;
pragma Elaborate_All (Gtk.Handlers);
with Gtk.Widget;                        use Gtk.Widget;
with Gtk.Enums;                         use Gtk.Enums;
with Gtk.Scrolled_Window;               use Gtk.Scrolled_Window;

with PragmARC.REM_NN_Wrapper;           use PragmARC.REM_NN_Wrapper;

with Text_Io;                           use Text_Io;

package body Libsens.Gtk_Arpegiator is
   
   --------------------
   -- step sequencer --
   --------------------
   
   
   
   
  
   package Plugin_Cb is new Gtk.Handlers.User_Callback 
     (Gtk.Widget.Gtk_Widget_Record, 
      Abstract_Plugin_Access);            


   procedure Set_Last_step(Widget : access Gtk_Widget_Record'class; Plugin : Abstract_Plugin_Access) is
   begin
      Arp_Seq_Plugin_Record(Plugin.all).Last_step := Positive(Get_value(Gtk_Spin_Button(Widget)));
       
    end Set_Last_step;

    procedure Set_Transpose(Widget : access Gtk_Widget_Record'class; Plugin : Abstract_Plugin_Access) is
    begin
       Arp_Seq_Plugin_Record(Plugin.all).Transpose := C.long(Get_value(Gtk_Spin_Button(Widget)));       
    end Set_Transpose;        
    
    procedure Reuse_Mono_Callback
     (Widget  : access Gtk_Widget_Record'Class;      
      Plugin : Abstract_Plugin_Access) is
    begin      
       Arp_Seq_Plugin_Record(Plugin.all).Reuse := Boolean'Val(Gtk.Combo_Box_text.Get_Active(Gtk_Combo_Box_text(Widget)));
   exception
      when others =>
	 null;
   end Reuse_Mono_Callback;

   
      
   procedure Converged_Mono_Callback
     (Widget  : access Gtk_Widget_Record'Class;      
      Plugin : Abstract_Plugin_Access) is
   begin      
      Arp_Seq_Plugin_Record(Plugin.all).Converged := real(Gtk.Spin_Button.Get_Value(Gtk_Spin_Button(Widget)));
   exception
      when others =>
	 null;
   end Converged_Mono_Callback;
   
   procedure Max_Epoch_Mono_Callback
     (Widget  : access Gtk_Widget_Record'Class;      
      Plugin : Abstract_Plugin_Access) is
   begin      
      Arp_Seq_Plugin_Record(Plugin.all).Max_Epoch := Integer(Gtk.Spin_Button.Get_Value(Gtk_Spin_Button(Widget)));
   exception
      when others =>
	 null;
   end Max_Epoch_Mono_Callback;


   
   
   procedure Init_intel
     (Intelligence : out Intelligence_Access;
      Plugin : in Abstract_Plugin_access) is
      
      
      Hbox : Gtk_Hbox;
      Label : Gtk_Label;
      Vbox : Gtk_Vbox;
   begin
      Intelligence := new GTK_Intelligence;
      --Put_Line("intel ::= 0.0.0");
      Gtk_New_Vbox(Intelligence.Main_Vbox);
      Gtk_New_Hbox(Intelligence.Main_Hbox);
      Gtk_New_Vbox(Intelligence.parameters);
      Gtk_New_Hbox(Intelligence.Chord_Hbox);
      --Put_Line("intel ::= 0.0.1");
      for I in Arp_Seq_Plugin_Record(plugin.all).chord'Range loop
	 
	 
	 --Put_Line("intel ::= 0.0.2");
	 Gtk_Arpegiator.Initialize(Intelligence.chord(I), Arp_Seq_Plugin_Record(plugin.all).Start_Chord(I), Plugin);
	 ----Put_Line("intel ::= 0.0.3");
	 Pack_Start(Intelligence.Chord_Hbox, Intelligence.Chord(I).Note_Vbox, False, False, 0);
	 
	 --Put_Line("intel ::= 0.0.4");
         
      end loop;
      
      Gtk_New(Intelligence.Key_Label, "Key");
      Gtk_New(Intelligence.Sens_Label, "Sens");

      Gtk_New_Vbox(Intelligence.Label_Vbox);
      --Put_Line("intel ::= 0.0.5");
      Pack_Start(Intelligence.Label_Vbox, Intelligence.Key_Label, False, False, 5);
      Pack_Start(Intelligence.Label_Vbox, Intelligence.Sens_Label, False, False, 5);

      --Put_Line("intel ::= 0.0.6");
      Pack_Start(Intelligence.Main_Hbox, Intelligence.Label_Vbox, False, False, 0);
      Pack_Start(Intelligence.Main_Hbox, Intelligence.Chord_Hbox, False, False, 0);
      Pack_Start(Intelligence.Main_Hbox, Intelligence.parameters, False, False, 15);

      --Put_Line("intel ::= 0.0.7");
      Gtk_New(Intelligence.Last_Label, "Last step :");
      Gtk_New(Intelligence.Last_Spin_Button, 1.0, 32.0, 1.0);
      Set_Value(Intelligence.Last_Spin_Button, Gdouble(Arp_Seq_Plugin_Record(Plugin.all).Last_Step));
      Gtk_New(Intelligence.Transpose_Label, "Transpose :");
      Gtk_New(Intelligence.Transpose_Spin_Button, 0.0, 24.0, 1.0);
      
      
      
      
      
      
      
      Set_Value(Intelligence.Transpose_Spin_Button, Gdouble(Arp_Seq_Plugin_Record(Plugin.all).transpose));
      Gtk_New_Hbox(Intelligence.Stepseq_Hbox);
      for I in Intelligence.Step_Table'Range loop
	 
	 
	 Gtk_Arpegiator.Init_step(Intelligence.Step_Table(I), Arp_Seq_Plugin_Record(plugin.all).Step_Table(I), Integer'Image(I), plugin);
	 Pack_Start(Intelligence.Stepseq_Hbox, Intelligence.Step_Table(I).Step_Vbox, False, False, 0);

      end loop;
      --Put_Line("intel ::= 0.0.8");
      Gtk_New(Intelligence.Filename_Gentry);
      --Gtk_New_From_stock(Intelligence.File_Selection_button, Stock_open);
      Gtk_New(Intelligence.Filename_Label, "Network filename : " & Arp_Seq_Plugin_Record(Plugin.all).Network.all);
      Gtk_New_Vbox(Intelligence.Step_Parameters);
      Gtk_New_Vbox(Intelligence.Network_Parameters);
      --Put_Line("intel ::= 0.0.9");
      Pack_Start(Intelligence.Step_Parameters, Intelligence.Last_label, False, False, 0);
      Pack_Start(Intelligence.Step_Parameters, Intelligence.Last_Spin_Button, False, False, 0);
      Pack_Start(Intelligence.Step_Parameters, Intelligence.Transpose_Label, False, False, 0);
      Pack_Start(Intelligence.Step_Parameters, Intelligence.Transpose_Spin_Button, False, False, 0);
      --Put_Line("intel ::= 0.0.10");
      Pack_Start(Intelligence.Network_Parameters, Intelligence.Filename_Label, False, False, 0);
      
      
      Gtk_New_Vbox(Vbox);
      
      Gtk_New(Intelligence.Reuse);
      Insert_Text(Intelligence.Reuse, 0, Boolean'Image(False));
      Insert_Text(Intelligence.Reuse, 1, Boolean'Image(True));                  
      Set_Active(Intelligence.Reuse, Boolean'Pos(Arp_seq_Plugin_Record(Plugin.all).Reuse));
      Gtk_New_Hbox(Hbox);
      Gtk_New(Label, "Reuse network   : ");      
      Pack_Start(Hbox, Label, False, False, 2);
      Pack_Start(Hbox, Intelligence.Reuse, False, False, 2);
      Pack_Start(Vbox, Hbox, False, False, 2);
      
      Plugin_Cb.Connect
        (Intelligence.Reuse, "changed", Plugin_Cb.To_Marshaller(Reuse_Mono_Callback'Access),
	 User_Data => Plugin);
      
      
      
      
      
      Gtk_New(Intelligence.Converged, 0.0001, 1.0, 0.0001);
      Set_Value(Intelligence.Converged, Gdouble(Arp_Seq_Plugin_Record(Plugin.all).Converged));
           
      Gtk_New_Hbox(Hbox);
      Gtk_New(Label, "Converged       :");      
      Pack_Start(Hbox, Label, False, False, 2);
      Pack_Start(Hbox, Intelligence.Converged, False, False, 2);
      Pack_Start(Vbox, Hbox, False, False, 2);
      
      
      Plugin_Cb.Connect
        (Intelligence.Converged, "value_changed", Plugin_Cb.To_Marshaller(Converged_Mono_Callback'Access),
	 User_Data => Plugin);
      
      
      
      
      
      Gtk_New(Intelligence.Max_Epoch, 1.0, 65537.0, 128.0);
      Set_Value(Intelligence.Max_Epoch, Gdouble(Arp_Seq_Plugin_Record(Plugin.all).Max_Epoch));

      Gtk_New_Hbox(Hbox);
      Gtk_New(Label, "Max epoch       : ");      
      Pack_Start(Hbox, Label, False, False, 2);
      Pack_Start(Hbox, Intelligence.Max_epoch, False, False, 2);
      Pack_Start(Vbox, Hbox, False, False, 2);
      
      
      Plugin_Cb.Connect
        (Intelligence.Max_Epoch, "value_changed", Plugin_Cb.To_Marshaller(Max_Epoch_Mono_Callback'Access),
	 User_Data => Plugin);
      
      
      
      
      Pack_Start(Intelligence.Network_Parameters, vbox, False, False, 0);
      
      
      --Pack_Start(Intelligence.Network_Parameters, Intelligence.Filename_gentry, False, False, 0);
      --Pack_Start(Intelligence.Network_Parameters, Intelligence.File_Selection_button, False, False, 10);
      --Put_Line("intel ::= 0.0.11");
      Pack_Start(Intelligence.Main_Hbox, Intelligence.Step_Parameters, False, False, 0);
      Pack_Start(Intelligence.Main_Hbox, Intelligence.Network_Parameters, False, False, 15);
      --Put_Line("intel ::= 0.0.12");
      Pack_Start(Intelligence.Main_Vbox, Intelligence.Main_Hbox, False, False, 0);
      Pack_Start(Intelligence.Main_Vbox, Intelligence.Stepseq_Hbox, False, False, 0);
      --Put_Line("intel ::= 0.0.13");
      Plugin_Cb.Connect(Intelligence.Last_Spin_Button,
                                    "value_changed",
                                    Plugin_Cb.To_Marshaller(Set_Last_Step'access),
                                    plugin);

      Plugin_Cb.Connect(Intelligence.Transpose_Spin_Button,
                                    "value_changed",
                                    Plugin_Cb.To_Marshaller(Set_Transpose'access),
                                    plugin);

      --  Plugin_Cb.Connect(Intelligence.File_Selection_Button,
      --                                "clicked",
      --                                Plugin_Cb.To_Marshaller(Set_filename'access),
      --                                Intelligence);



      
   end Init_intel;

   
   procedure Set_To_Active(Widget : access Gtk_Widget_Record'class; step : Virtual.Arp_Sequencer.Step_Access) is
   begin
      step.Set := Get_active(Gtk_Check_Button(Widget));
   end Set_To_Active;
   
   procedure Set_Key(Widget : access Gtk_Widget_Record'class; Step : Common.Note_Access) is
   begin
      Step.key := C.Long(Get_value(Gtk_Spin_Button(widget)));
   end Set_Key;

   procedure Set_Sens(Widget : access Gtk_Widget_Record'class; Step : Common.Note_Access) is
   begin
      Step.vel := C.Long(Get_value(Gtk_Spin_Button(Widget)));
   end Set_Sens;


   package Step_Handlers is new Gtk.Handlers.User_Callback(Gtk_Widget_Record, Virtual.Arp_Sequencer.Step_Access);
   
   package note_Handlers is new Gtk.Handlers.User_Callback(Gtk_Widget_Record, Common.Note_Access);


   procedure Initialize
     (Note : in out Gtk_Note_Access;
      The_note : in Common.Note_Access;
      Plugin : in Abstract_Plugin_Access) is
      begin
	 
         note := new Gtk_Note;
         Gtk_New(Note.Key_Spin_Button, 0.0, 127.0, 1.0);
         Set_Value(Note.Key_Spin_Button, Gdouble(The_Note.key));
         Gtk_New(Note.Sens_Spin_Button, 0.0, 127.0, 1.0);
         Set_Value(Note.sens_Spin_Button, Gdouble(The_Note.Vel));
	 
	 Gtk_New_Vbox(Note.Note_Vbox, False, 0);
	 
         Pack_Start(Note.Note_Vbox, Note.Key_Spin_Button, False, False, 0);
         Pack_Start(Note.Note_Vbox, Note.Sens_Spin_Button, False, False, 0);

         

	 
         note_Handlers.Connect(Note.Key_Spin_Button,
                               "value_changed",
                               note_handlers.To_Marshaller(Set_key'access),
			       The_Note);

         note_Handlers.Connect(Note.sens_Spin_Button,
                               "value_changed",
                               note_handlers.To_Marshaller(Set_sens'access),
                               The_Note);
	 
   end Initialize;


   
    
 
    procedure Init_step
      (Step : in out Gtk_Step_Access;
       The_Step : in Virtual.Arp_Sequencer.Step_Access;
       Label : in String;
       Plugin : in Abstract_Plugin_Access) is
    begin

       Step := new Gtk_Step;
       Gtk_New_Vbox(Step.Step_Vbox);
       Gtk_New(Step.Step_Label, Label);
       Gtk_New(Step.Set_Check_Button);
       Set_Active(Step.Set_Check_Button, The_Step.set);

       Pack_Start(Step.Step_Vbox, Step.Step_label, False, False, 0);

       Pack_Start(Step.Step_Vbox, Step.Set_check_Button, False, False, 0);

       Step_Handlers.Connect(Step.Set_Check_Button,
                             "toggled",
                             Step_handlers.To_Marshaller(Set_To_Active'access),
                             The_Step);

    end Init_step;


   
   
   
    procedure Initialize (Spec : in out Arpegiator_Specifications;
			  Plugin : in Abstract_Plugin_access) is
       
       Scrolled   : Gtk_Scrolled_Window;      
   begin
      
      
      
      Gtk_New(Spec.Specifications_Frame, "Arpegiator : ");
      --Put_Line("initializing intel spec...");
      Init_intel(Spec.Intel, Plugin);
      --Put_Line("Intel spec initialized.");
      Gtk_New(Scrolled);
      --Put_Line("new scroll");
      Add_With_Viewport(Scrolled, Spec.Intel.Main_Vbox);
      --Put_Line("add vbox to scrolled");
      Add(Spec.Specifications_Frame, scrolled);
      --Put_Line("add scrolled to frame");
      
      --Put_Line("Load seq 0.1.8.1");
      
   end Initialize;
   
   
   
   
end Libsens.Gtk_Arpegiator;