// ----
// ---- file   : EditCustomSynthInstrumentDialog.tks
// ---- author : Bastian Spiegel <bs@tkscript.de>
// ---- legal  : (c) 2011 by Bastian Spiegel. 
// ----          Distributed under terms of the GNU LESSER GENERAL PUBLIC LICENSE (LGPL). See 
// ----          http://www.gnu.org/licenses/licenses.html#LGPL or COPYING for further information.
// ----
// ---- info   : This is part of the "syntracker" midi sequencer.
// ----
// ---- created: 06Apr2011
// ----          
// ---- changed: 07Apr2011
// ----          
// ----
// ----

module MEditCustomSynthInstrumentDialog;

use tkcustomsynth;

use namespace ui;

use namespace st2;


class EditCustomSynthInstrumentDialog : CustomInstrumentDialog {

   CustomSynthInstrument *ins; // reference to instrument that is currently being edited

   protected XMLForm *xfm;

   protected Button       *bt_close;
   protected TextField    *tf_name;
   protected RepeatButton *rb_previnstr;
   protected RepeatButton *rb_nextinstr;
   protected CheckBox     *cb_enablemacro;
   protected Button       *bt_editmacro;
   protected Button       *bt_edit_ctl;
   protected Button       *bt_edit_gen;
   protected CheckBox     *cb_resetusrctl;
   protected FloatParam   *fp_pitchbend;


   public method init() : boolean {
      // called when CustomSynthGenerator-type is added

      initDialog();

      xfm <= XMLForm.New_PakFile("EditCustomSynthInstrumentDialog.xfm");
      if(null == xfm)
      {
         return false;
      }

      xfm.autoResolveIds(this);

      initWindow(xfm, "Edit instrument (Custom)", 140, 10, 
                 370+UIConstants.WINDOW_BORDER_SIZE*2, 
                 300+WindowTitleBar.HEIGHT+UIConstants.WINDOW_BORDER_SIZE*2); // xxx hardcoded title height

      setMinimumSize2f(getSizeX(), getSizeY());

      return true;
   }

   public virtual isPopup() : boolean {
      return true;
   }

   public method showInstrument(ST_Instrument _ins, boolean _bOpenWindow) {

      ins <= _ins;

      tf_name        .setText(ins.getName());
      cb_enablemacro .setSelected(ins.b_macro);
      cb_resetusrctl .setSelected(ins.b_select_resetusrctl);
      fp_pitchbend   .setValue(ins.pitchbend_range);

      if(_bOpenWindow)
      {
         resizeToMinimum();
         resizeToMinimum(); // (TODO) for some reason this needs to be called twice ATM
         
         Dialog::showCentered();
         
         UI.SetKeyboardFocus(bt_close);
      }

      updateWindowTitle();
   }

   protected method updateWindowTitle() {
      String t = "Edit instrument #"+ins.instrument_nr+" name=\""+ins.name+"\"";
      ST_Generator g <= ins.getGenerator();
      t.append(" (generator type="+g.getTypeName()+" name=\""+g.getName()+"\")");
      setWindowTitle(t);
   }

   public method selectPreviousInstrument() {
      int instrNr = ins.instrument_nr;

      ST_InstrumentMap imap <= current_song.instrument_map;
      loop(ST_InstrumentMap.MAX_INSTRUMENTS)
      {
         instrNr--;
         if(instrNr < 0)
         {
            instrNr += ST_InstrumentMap.MAX_INSTRUMENTS;
         }
         ST_Instrument *c <= imap.getInstrument(instrNr);
         if(c instanceof ins)
         {
            showInstrument(c, false);
            break;
         }
      }
   }

   public method selectNextInstrument() {
      int instrNr = ins.instrument_nr;

      ST_InstrumentMap imap <= current_song.instrument_map;
      loop(ST_InstrumentMap.MAX_INSTRUMENTS)
      {
         instrNr++;
         if(instrNr >= ST_InstrumentMap.MAX_INSTRUMENTS)
         {
            instrNr -= ST_InstrumentMap.MAX_INSTRUMENTS;
         }
         ST_Instrument *c <= imap.getInstrument(instrNr);
         if(c instanceof ins)
         {
            showInstrument(c, false);
            break;
         }
      }
   }

   protected method editUserCtlMap() {
      _= Global.dlg_edit_controller_mapping.showInstrument(ins);
   }

   protected method editGenerator() {
      // Edit/re-assign generator
      ManageGeneratorsDialog *dlg <= Global.dlg_manage_generators;
      dlg.showSelector(ins.getGenerator(), this); // Sends GENERATOR_SELECTED action
   }

   protected method handleGeneratorSelected() {
      ST_Generator g <= Global.dlg_manage_generators.getSelectedGenerator();

      // Change instrument generator:

      //  Unlink instrument from old generator instruments list
      ST_Instrument ai <= ins.generator.instruments.getDeref(ins.generator.instruments.indexOfPointer(ins, 0));
      ins.generator.instruments.remove(ins);

      //  Add instrument to new generator instruments list
      g.instruments.add(#(deref ai));

      //  Set generator reference in instrument
      ins.setGenerator(g);

      updateWindowTitle();

      Global.RedrawAll();
   }

   protected =replay= method handleEnableMacroChanged() {
      ins.b_macro = cb_enablemacro.isSelected();
   }

   protected method editMacro() {
      EditMacroDialog *macroDlg <= Global.GetEditMacroDialog();

      macroDlg.showMacro(ins.macro);
   }

   protected =replay= method handlePitchbendRangeChanged() {
      ins.setPitchBendRange(fp_pitchbend.getValue());
   }

   protected =replay= method handleResetUsrCtlChanged() {
      ins.b_select_resetusrctl = cb_resetusrctl.isSelected();
   }

   public virtual onTriadKey(Key _k) : boolean {
      switch(_k.pressed)
      {
         case 'c':
            hide();
            return true;
      }
   }

   public virtual onTriadKeyTimeout() {
      Global.ShowTriadKeyHelpDialog("lctrl-x ..", 
"
          c         :   Close dialog
"
                                    ,
                                    this);
      return true;
   }

   public virtual onKey(Key _k) returns boolean {

      switch(_k.pressed)
      {
        case VKEY_ESCAPE:
           hide();
           return true;
      }

      return Dialog::onKey(_k);
   }

   public virtual consumeAction(Action _action) returns boolean {

      String acName <= _action.getActionName();
      ActionProvider ap <= _action.getActionProvider();

      ////trace "xxx EditCustomSynthInstrumentDialog::consumeAction: name=\""+acName+"\".";

      switch(acName)
      {
         case TextField.ACTION_TEXTENTERED:
         {
            UI.SetKeyboardFocus(bt_close);
         }
         break;

         case ManageGeneratorsDialog.ACTION_GENERATOR_SELECTED:
         {
            handleGeneratorSelected();
         }
         break;

      }

      switch(@(ap))
      {
         case @(rb_previnstr):
            selectPreviousInstrument();
            return true;

         case @(rb_nextinstr):
            selectNextInstrument();
            return true;

         case @(bt_close):
            hide();
            return true;

         case @(tf_name):
            ins.setName(tf_name.getText());
            return true;

         case @(bt_edit_ctl):
            editUserCtlMap();
            return true;

         case @(bt_edit_gen):
            if(Global.NotPlaying("edit/re-assign generator"))
            {
               editGenerator();
            }
            return true;

         case @(bt_editmacro):
            editMacro();
            return true;

         case @(cb_enablemacro):
            handleEnableMacroChanged();
            return true;

         case @(fp_pitchbend):
            handlePitchbendRangeChanged();
            return true;

         case @(cb_resetusrctl):
            handleResetUsrCtlChanged();
            return true;
      }
      
      return true;
   }

}
