/**
 * @license
 * Visual Blocks Editor
 *
 * Copyright 2013 Google Inc.
 * https://developers.google.com/blockly/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @fileoverview Combination text + drop-down field
 * @author tmickel@mit.edu (Tim Mickel)
 */
'use strict';

goog.provide('Blockly.FieldTextDropdown');

goog.require('Blockly.DropDownDiv');
goog.require('Blockly.FieldDropdown');
goog.require('Blockly.FieldTextInput');
goog.require('goog.userAgent');


/**
 * Class for a combination text + drop-down field.
 * @param {string} text The initial content of the text field.
 * @param {(!Array.<!Array.<string>>|!Function)} menuGenerator An array of
 *     options for a dropdown list, or a function which generates these options.
 * @param {Function=} opt_validator An optional function that is called
 *     to validate any constraints on what the user entered.  Takes the new
 *     text as an argument and returns the accepted text or null to abort
 *     the change.
 * @param {RegExp=} opt_restrictor An optional regular expression to restrict
 *     typed text to. Text that doesn't match the restrictor will never show
 *     in the text field.
 * @extends {Blockly.FieldTextInput}
 * @constructor
 */
Blockly.FieldTextDropdown = function(text, menuGenerator, opt_validator, opt_restrictor) {
  this.menuGenerator_ = menuGenerator;
  Blockly.FieldDropdown.prototype.trimOptions_.call(this);
  Blockly.FieldTextDropdown.superClass_.constructor.call(this, text, opt_validator, opt_restrictor);
  this.addArgType('textdropdown');
};
goog.inherits(Blockly.FieldTextDropdown, Blockly.FieldTextInput);

/**
 * Construct a FieldTextDropdown from a JSON arg object,
 * dereferencing any string table references.
 * @param {!Object} element A JSON object with options.
 * @returns {!Blockly.FieldTextDropdown} The new field instance.
 * @package
 * @nocollapse
 */
Blockly.FieldTextDropdown.fromJson = function(element) {
  var field =
      new Blockly.FieldTextDropdown(element['text'], element['options']);
  if (typeof element['spellcheck'] == 'boolean') {
    field.setSpellcheck(element['spellcheck']);
  }
  return field;
};

/**
 * Install this text drop-down field on a block.
 */
Blockly.FieldTextDropdown.prototype.init = function() {
  if (this.fieldGroup_) {
    // Text input + dropdown has already been initialized once.
    return;
  }
  Blockly.FieldTextDropdown.superClass_.init.call(this);
  // Add dropdown arrow: "option ▾" (LTR) or "▾ אופציה" (RTL)
  // Positioned on render, after text size is calculated.
  if (!this.arrow_) {
    /** @type {Number} */
    this.arrowSize_ = 12;
    /** @type {Number} */
    this.arrowX_ = 0;
    /** @type {Number} */
    this.arrowY_ = 11;
    this.arrow_ = Blockly.utils.createSvgElement('image',
        {
          'height': this.arrowSize_ + 'px',
          'width': this.arrowSize_ + 'px'
        });
    this.arrow_.setAttributeNS('http://www.w3.org/1999/xlink',
        'xlink:href', Blockly.mainWorkspace.options.pathToMedia + 'dropdown-arrow-dark.svg');
    this.arrow_.style.cursor = 'pointer';
    this.fieldGroup_.appendChild(this.arrow_);
    this.mouseUpWrapper_ =
        Blockly.bindEvent_(this.arrow_, 'mouseup', this, this.showDropdown_);
  }
  // Prevent the drop-down handler from changing the field colour on open.
  this.disableColourChange_ = true;
};

/**
 * Close the input widget if this input is being deleted.
 */
Blockly.FieldTextDropdown.prototype.dispose = function() {
  if (this.mouseUpWrapper_) {
    Blockly.unbindEvent_(this.mouseUpWrapper_);
    this.mouseUpWrapper_ = null;
    Blockly.Touch.clearTouchIdentifier();
  }
  Blockly.FieldTextDropdown.superClass_.dispose.call(this);
};

/**
 * If the drop-down isn't open, show the text editor.
 */
Blockly.FieldTextDropdown.prototype.showEditor_ = function() {
  if (!this.dropDownOpen_) {
    Blockly.FieldTextDropdown.superClass_.showEditor_.call(this, null, null,
        true, function() {
          // When the drop-down arrow is clicked, hide text editor and show drop-down.
          Blockly.WidgetDiv.hide();
          this.showDropdown_();
          Blockly.Touch.clearTouchIdentifier();
        });
  }
};

/**
 * Return a list of the options for this dropdown.
 * See: Blockly.FieldDropDown.prototype.getOptions_.
 * @return {!Array.<!Array.<string>>} Array of option tuples:
 *     (human-readable text, language-neutral name).
 * @private
 */
Blockly.FieldTextDropdown.prototype.getOptions_ = Blockly.FieldDropdown.prototype.getOptions_;

/**
 * Position a drop-down arrow at the appropriate location at render-time.
 * See: Blockly.FieldDropDown.prototype.positionArrow.
 * @param {number} x X position the arrow is being rendered at, in px.
 * @return {number} Amount of space the arrow is taking up, in px.
 */
Blockly.FieldTextDropdown.prototype.positionArrow = Blockly.FieldDropdown.prototype.positionArrow;

/**
 * Create the dropdown menu.
 * @private
 */
Blockly.FieldTextDropdown.prototype.showDropdown_ = Blockly.FieldDropdown.prototype.showEditor_;

/**
 * Callback when the drop-down menu is hidden.
 */
Blockly.FieldTextDropdown.prototype.onHide = Blockly.FieldDropdown.prototype.onHide;

Blockly.Field.register('field_textdropdown', Blockly.FieldTextDropdown);