text: "use strict";
  
  var $ = require("jquery"),
      Color = require("../../color"),
      ColorView = require("./color_view"),
      registerComponent = require("../../core/component_registrator"),
      DropDownEditor = require("../drop_down_editor/ui.drop_down_editor");
  
  var COLOR_BOX_CLASS = "dx-colorbox",
      COLOR_BOX_INPUT_CLASS = COLOR_BOX_CLASS + "-input",
      COLOR_BOX_INPUT_CONTAINER_CLASS = COLOR_BOX_INPUT_CLASS + "-container",
      COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS = COLOR_BOX_CLASS + "-color-result-preview",
      COLOR_BOX_COLOR_IS_NOT_DEFINED = COLOR_BOX_CLASS + "-color-is-not-defined",
      COLOR_BOX_OVERLAY_CLASS = COLOR_BOX_CLASS + "-overlay",
  
      COLOR_BOX_CONTAINER_CELL_CLASS = "dx-colorview-container-cell",
      COLOR_BOX_BUTTON_CELL_CLASS = "dx-colorview-button-cell",
      COLOR_BOX_BUTTONS_CONTAINER_CLASS = "dx-colorview-buttons-container",
      COLOR_BOX_APPLY_BUTTON_CLASS = "dx-colorview-apply-button",
      COLOR_BOX_CANCEL_BUTTON_CLASS = "dx-colorview-cancel-button";
  
  var colorEditorPrototype = ColorView.prototype,
      colorUtils = {
          makeTransparentBackground: $.proxy(colorEditorPrototype._makeTransparentBackground, colorEditorPrototype),
          makeRgba: $.proxy(colorEditorPrototype._makeRgba, colorEditorPrototype)
      };
  
  var ColorBox = DropDownEditor.inherit({
  
      _supportedKeys: function() {
          var arrowHandler = function(e) {
              e.stopPropagation();
              if(this.option("opened")) {
                  e.preventDefault();
                  return true;
              }
          };
  
          var upArrowHandler = function(e) {
              if(!this.option("opened")) {
                  e.preventDefault();
                  return false;
              }
              if(e.altKey) {
                  this.close();
                  return false;
              }
              return true;
          };
  
          var downArrowHandler = function(e) {
              if(!this.option("opened") && !e.altKey) {
                  e.preventDefault();
                  return false;
              }
              if(!this.option("opened") && e.altKey) {
                  this._validatedOpening();
                  return false;
              }
              return true;
          };
  
          return $.extend(this.callBase(), {
              tab: function(e) {
                  if(this.option("opened")) {
                      e.preventDefault();
                      this._colorView._rgbInputs[0].focus();
                  }
              },
              enter: this._enterKeyHandler,
              leftArrow: arrowHandler,
              rightArrow: arrowHandler,
              upArrow: upArrowHandler,
              downArrow: downArrowHandler
          });
      },
  
      _getDefaultOptions: function() {
          return $.extend(this.callBase(), {
              /**
              * @name dxColorBoxOptions_editAlphaChannel
              * @publicName editAlphaChannel
              * @type boolean
              * @default false
              */
              editAlphaChannel: false,
  
              /**
              * @name dxColorBoxOptions_applyButtonText
              * @publicName applyButtonText
              * @type string
              * @default "OK"
              */
  
              /**
              * @name dxColorBoxOptions_cancelButtonText
              * @publicName cancelButtonText
              * @type string
              * @default "Cancel"
              */
  
              /**
              * @name dxColorBoxOptions_applyValueMode
              * @publicName applyValueMode
              * @type string
              * @default "useButtons"
              * @extend_doc
              */
              applyValueMode: "useButtons",
  
              /**
              * @name dxColorBoxOptions_keyStep
              * @publicName keyStep
              * @type number
              * @default 1
              */
              keyStep: 1,
  
              /**
               * @name dxColorBoxOptions_fieldTemplate
               * @publicName fieldTemplate
               * @type template
               * @default null
               * @type_function_param1 value:string
               * @type_function_param2 fieldElement:jQuery
               * @type_function_return string|Node|jQuery
               */
              fieldTemplate: null,
  
              // TODO: convert these options to actions and publish them
              onApplyButtonClick: null,
              onCancelButtonClick: null,
  
              buttonsLocation: "bottom after",
  
              /**
              * @name dxColorBoxOptions_value
              * @publicName value
              * @type string
              * @extend_doc
              */
  
              /**
              * @name dxColorBoxOptions_fieldEditEnabled
              * @publicName fieldEditEnabled
              * @hidden
              * @extend_doc
              */
  
              /**
              * @name dxColorBoxOptions_maxLength
              * @publicName maxLength
              * @hidden
              * @extend_doc
              */
  
              /**
              * @name dxColorBoxOptions_showClearButton
              * @publicName showClearButton
              * @hidden
              * @extend_doc
              */
  
              /**
              * @name dxColorBoxOptions_valueChangeEvent
              * @publicName valueChangeEvent
              * @hidden
              * @extend_doc
              */
              valueChangeEvent: "change"
  
              /**
              * @name dxColorBoxOptions_spellcheck
              * @publicName spellcheck
              * @hidden
              * @extend_doc
              */
          });
      },
  
      _popupConfig: function() {
          return $.extend(this.callBase(), {
              height: "auto",
              width: ""
          });
      },
  
      _contentReadyHandler: function() {
          this._createColorView();
          this._addPopupBottomClasses();
      },
  
      _addPopupBottomClasses: function() {
          var $popupBottom = this._popup.bottomToolbar();
          if($popupBottom) {
              $popupBottom
                  .addClass(COLOR_BOX_CONTAINER_CELL_CLASS)
                  .addClass(COLOR_BOX_BUTTON_CELL_CLASS)
                  .find(".dx-toolbar-items-container")
                  .addClass(COLOR_BOX_BUTTONS_CONTAINER_CLASS);
  
              $popupBottom
                  .find(".dx-popup-done")
                  .addClass(COLOR_BOX_APPLY_BUTTON_CLASS);
  
              $popupBottom
                  .find(".dx-popup-cancel")
                  .addClass(COLOR_BOX_CANCEL_BUTTON_CLASS);
          }
      },
  
      _createColorView: function() {
          this._popup.overlayContent().addClass(COLOR_BOX_OVERLAY_CLASS);
  
          var $colorView = $("<div>").appendTo(this._popup.content());
  
          this._colorView = this._createComponent($colorView, ColorView, this._colorViewConfig());
  
          $colorView.on("focus", $.proxy(function() {
              this.focus();
          }, this));
      },
  
      _applyNewColor: function(value) {
          this.option("value", value);
  
          if(value) {
              colorUtils.makeTransparentBackground(this._$colorResultPreview, value);
          }
  
          if(this._colorViewEnterKeyPressed) {
              this.close();
              this._colorViewEnterKeyPressed = false;
          }
      },
  
      _colorViewConfig: function() {
          var that = this;
  
          return {
              value: that.option("value"),
              editAlphaChannel: that.option("editAlphaChannel"),
              applyValueMode: that.option("applyValueMode"),
              focusStateEnabled: that.option("focusStateEnabled"),
              onEnterKeyPressed: function() {
                  that._colorViewEnterKeyPressed = true;
                  if(that._colorView.option("value") !== that.option("value")) {
                      that._applyNewColor(that._colorView.option("value"));
                      that.close();
                  }
              },
  
              onValueChanged: function(args) {
                  var instantlyMode = that.option("applyValueMode") === "instantly";
  
                  if(!instantlyMode && !that._colorViewEnterKeyPressed) {
                      return;
                  }
  
                  that._applyNewColor(args.value);
              },
              _keyboardProcessor: that._colorViewProcessor
          };
      },
  
      _enterKeyHandler: function() {
          var newValue = this._input().val(),
              value = this.option("value"),
              oldValue = this.option("editAlphaChannel") ? colorUtils.makeRgba(value) : value;
  
          if(!newValue) return false;
  
          var color = new Color(newValue);
  
          if(color.colorIsInvalid) {
              this._input().val(oldValue);
              return;
          }
  
          if(newValue !== oldValue) {
              this._applyColorFromInput(newValue);
              this.option("value", this.option("editAlphaChannel") ? colorUtils.makeRgba(newValue) : newValue);
          }
  
          if(this._colorView) {
              var colorViewValue = this._colorView.option("value");
              if(value !== colorViewValue) {
                  this.option("value", colorViewValue);
              }
          }
  
          this.close();
          return false;
      },
  
      _applyButtonHandler: function() {
          this._applyNewColor(this._colorView.option("value"));
  
          if($.isFunction(this.option("onApplyButtonClick"))) {
              this.option("onApplyButtonClick")();
          }
  
          this.callBase();
      },
  
      _cancelButtonHandler: function() {
          this._resetInputValue();
  
          if($.isFunction(this.option("onCancelButtonClick"))) {
              this.option("onCancelButtonClick")();
          }
  
          this.callBase();
      },
  
      _attachChildKeyboardEvents: function() {
          this._colorViewProcessor = this._keyboardProcessor.attachChildProcessor();
          if(this._colorView) {
              this._colorView.option("_keyboardProcessor", this._colorViewProcessor);
              return;
          }
      },
  
      _init: function() {
          this.callBase();
      },
  
      _render: function() {
          this.callBase();
          this.element().addClass(COLOR_BOX_CLASS);
      },
  
      _renderInput: function() {
          this.callBase();
  
          this._input().addClass(COLOR_BOX_INPUT_CLASS);
          this._renderColorPreview();
      },
  
      _renderColorPreview: function() {
          this.element().wrapInner($("<div/>").addClass(COLOR_BOX_INPUT_CONTAINER_CLASS));
          this._$colorBoxInputContainer = this.element().children().eq(0);
  
          this._$colorResultPreview = $("<div>", {
              "class": COLOR_BOX_COLOR_RESULT_PREVIEW_CLASS,
              "appendTo": this._$colorBoxInputContainer
          });
  
          if(!this.option("value")) {
              this._$colorBoxInputContainer.addClass(COLOR_BOX_COLOR_IS_NOT_DEFINED);
          } else {
              colorUtils.makeTransparentBackground(this._$colorResultPreview, this.option("value"));
          }
      },
  
      _renderValue: function() {
          var value = this.option("value");
          this.option("text", this.option("editAlphaChannel") ? colorUtils.makeRgba(value) : value);
          this.callBase();
      },
  
      _resetInputValue: function() {
          var $input = this._input(),
              value = this.option("value");
  
          $input.val(value);
          this._colorView && this._colorView.option("value", value);
      },
  
      _valueChangeEventHandler: function(e) {
          var value = this._input().val();
  
          if(value) {
              value = this._applyColorFromInput(value);
  
              this._colorView && this._colorView.option("value", value);
          }
          this.callBase(e, value);
      },
  
      _applyColorFromInput: function(value) {
          var newColor = new Color(value);
  
          if(newColor.colorIsInvalid) {
              this._resetInputValue();
              value = this.option("value");
          }
  
          return value;
      },
  
      _optionChanged: function(args) {
          var value = args.value,
              name = args.name;
  
          switch(name) {
              case "value":
                  this._$colorBoxInputContainer.toggleClass(COLOR_BOX_COLOR_IS_NOT_DEFINED, !value);
  
                  if(value) {
                      colorUtils.makeTransparentBackground(this._$colorResultPreview, value);
                  } else {
                      this._$colorResultPreview.removeAttr("style");
                  }
  
                  if(this._colorView) {
                      this._colorView.option("value", value);
                  }
  
                  this.callBase(args);
                  break;
              case "applyButtonText":
              case "cancelButtonText":
                  this.callBase(args);
                  this._popup && this._addPopupBottomClasses();
                  break;
              case "editAlphaChannel":
              case "onCancelButtonClick":
              case "onApplyButtonClick":
              case "keyStep":
                  if(this._colorView) {
                      this._colorView.option(name, value);
                  }
                  break;
              case "applyValueMode":
                  this.callBase(args);
                  break;
              case "rtlEnabled":
                  if(this._colorView) {
                      this._colorView.option(name, value);
                  }
                  this.callBase(args);
                  break;
              default:
                  this.callBase(args);
          }
      }
  });
  
  registerComponent("dxColorBox", ColorBox);
  
  module.exports = ColorBox;
  