// ----
// ---- file   : ColorPickerDialog.tks
// ---- author : Bastian Spiegel <bs@tkscript.de>
// ---- legal  : (c) 2012-2017 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: 19Feb2012
// ---- changed: 20Feb2012, 24Feb2012, 07May2013, 05Jun2013, 23Jan2015, 24Jan2015, 04Mar2017
// ----          10Nov2017
// ----
// ----
// ----


module MColorPickerDialog;

use namespace ui;
use namespace st2;



class ColorPickerDialog extends Dialog, ActionProvider {

   define String ACTION_COLOR_CHANGED;

   protected XMLForm *xfm;

   protected int c32_orig;
   protected int c32_cur;

   protected TextField      *tf_color;
   protected Button         *bt_clear;
   protected ColorButton    *color_button;
   protected HSVColorPicker *hsv_color_picker;

   protected FloatParam *fp_rgb_r;
   protected FloatParam *fp_rgb_g;
   protected FloatParam *fp_rgb_b;
   protected FloatParam *fp_rgb_a;

   protected FloatParam *fp_hsv_h;
   protected FloatParam *fp_hsv_s;
   protected FloatParam *fp_hsv_v;
   protected FloatParam *fp_hsv_a;

   protected Button    *bt_ok;
   protected Button    *bt_revert;

   protected ActionConsumer *consumer;


   public method init() : boolean {

      initDialog();

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

      xfm.autoResolveIds(this);

      initWindow(xfm, "Edit color", 140, 140, 
                 120+UIConstants.WINDOW_BORDER_SIZE*2, 
                 410+WindowTitleBar.HEIGHT+UIConstants.WINDOW_BORDER_SIZE*2); // xxx hardcoded title height

      return true;
   }

   public virtual getProvidedActionNames() : StringArray {
      return [ACTION_COLOR_CHANGED];
   }

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

   public virtual isResizable() : boolean {
      return false;
   }

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

   public method showColor(int _c32, ActionConsumer _consumer) {

      consumer <= _consumer;

      c32_orig = _c32;
      c32_cur = _c32;

      resizeToMinimum();

      updateARGB32();
      updateRGBA();
      updateHSVA();
      updateColorButton();

      showNearMouse(-85, -68);
   }

   public method getColor() : int {
      return c32_cur;
   }

   public method revertColor() {

      c32_cur = c32_orig;

      updateARGB32();
      updateRGBA();
      updateHSVA();
      updateColorButton();

      handleColorChanged();
   }

   public virtual postShow() {
      Dialog::postShow();

      UI.SetKeyboardFocus(tf_color);
   }

   // public virtual hide() {
   //    Dialog::hide();
   // }

   protected method updateARGB32() {
      Integer io = c32_cur;
      tf_color.setText(io.printf("#%08x"));
   }

   protected method updateRGBA() {
      // RGB
      fp_rgb_r.setValue( (c32_cur>>16) & 255 );
      fp_rgb_g.setValue( (c32_cur>> 8) & 255 );
      fp_rgb_b.setValue( (c32_cur    ) & 255 );
      fp_rgb_a.setValue( (c32_cur>>24) & 255 );
   }

   protected method updateHSVA() {
      // HSV
      Float h, s, v;
      UI.RGB32TOHSV(c32_cur, h, s, v);
      float a = ((c32_cur>>24)&255) * (1.0f / 255);
      fp_hsv_h.setValue(h);
      fp_hsv_s.setValue(s);
      fp_hsv_v.setValue(v);
      fp_hsv_a.setValue(a);
   }

   protected method updateColorButton() {
      color_button.setTint(c32_cur);
      byte a8 = (c32_cur>>24) & 255;
      if(0 == c32_cur)
      {
         a8 = 255;
      }
      hsv_color_picker.setAlpha8(a8);
   }

   protected method handleColorChanged() {

      Integer io = c32_cur;
      Global.Debug2("ColorPickerDialog:handleColorChanged: color is now #"+io.printf("%08x"));

      if(null != consumer)
      {
         consumer.consumeAction(IntAction.New(ACTION_COLOR_CHANGED, this, c32_cur));
      }
   }

   protected method handleColorEntered() {

      String text = tf_color.getText();

      if(!text.startsWith("#"))
         text = "#" + text;

      int c32 = text;

      c32_cur = c32;

      updateRGBA();
      updateHSVA();
      updateColorButton();
      handleColorChanged();
   }

   protected method handleClear() {

      c32_cur = 0;

      updateARGB32();
      updateRGBA();
      updateHSVA();
      updateColorButton();
      handleColorChanged();
   }

   protected method handleRGBAChanged() {

      int r = fp_rgb_r.getFloatValue();
      int g = fp_rgb_g.getFloatValue();
      int b = fp_rgb_b.getFloatValue();
      int a = fp_rgb_a.getFloatValue();

      c32_cur = argb(a, r, g, b);
      
      updateARGB32();
      updateHSVA();
      updateColorButton();
      handleColorChanged();
   }

   protected method handleHSVAChanged() {

      int c32 = UI.HSVTOARGB32(fp_hsv_h.getFloatValue(),
                               fp_hsv_s.getFloatValue(),
                               fp_hsv_v.getFloatValue(),
                               (fp_hsv_a.getFloatValue() * 255)
                               );

      c32_cur = c32;

      updateARGB32();
      updateRGBA();
      updateColorButton();
      handleColorChanged();
   }

   protected method handleColorButtonClicked() {
      trace "xxx handleColorButtonClicked";
   }

   protected method handleHSVColorPicked(IntAction _ia) {

      c32_cur = _ia.getIntValue();

      updateARGB32();
      updateRGBA();
      updateHSVA();
      updateColorButton();
      handleColorChanged();
   }

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

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

   public virtual onKey(Key _k) : boolean {
      switch(_k.code)
      {
         case VKEY_ESCAPE:
            hide();
            return true;
      }
      return Dialog::onKey(_k);
   }

   public virtual consumeAction(Action _action) : boolean {
      ActionProvider ap <= _action.getActionProvider();
      String acName <= _action.getActionName();

      switch(@(ap))
      {
         case @(bt_ok):
            hide();
            return true;

         case @(bt_revert):
            revertColor();
            return true;

         case @(tf_color):
            handleColorEntered();

            if(TextField.ACTION_TEXTENTERED == acName)
            {
               hide();
            }
            return true;

         case @(bt_clear):
            handleClear();
            // hide();
            return true;

         case @(fp_rgb_r):
         case @(fp_rgb_g):
         case @(fp_rgb_b):
         case @(fp_rgb_a):
            handleRGBAChanged();
            return true;

         case @(fp_hsv_h):
         case @(fp_hsv_s):
         case @(fp_hsv_v):
         case @(fp_hsv_a):
            handleHSVAChanged();
            return true;

         case @(color_button):
            handleColorButtonClicked();
            return true;

         case @(hsv_color_picker):
            handleHSVColorPicked(_action);
            return true;
      }

      return Dialog::consumeAction(_action);
   }

}
