/**
 * @license
 * Copyright The Closure Library Authors.
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @fileoverview Component for an input field with bidi direction automatic
 * detection. The input element directionality is automatically set according
 * to the contents (value) of the element.
 *
 * @see ../demos/bidiinput.html
 */


goog.provide('goog.ui.BidiInput');


goog.require('goog.dom');
goog.require('goog.dom.InputType');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.events.InputHandler');
goog.require('goog.i18n.bidi');
goog.require('goog.ui.Component');



/**
 * Default implementation of BidiInput.
 *
 * @param {goog.dom.DomHelper=} opt_domHelper  Optional DOM helper.
 * @constructor
 * @extends {goog.ui.Component}
 */
goog.ui.BidiInput = function(opt_domHelper) {
  'use strict';
  goog.ui.Component.call(this, opt_domHelper);
};
goog.inherits(goog.ui.BidiInput, goog.ui.Component);


/**
 * The input handler that provides the input event.
 * @type {goog.events.InputHandler?}
 * @private
 */
goog.ui.BidiInput.prototype.inputHandler_ = null;


/**
 * Decorates the given HTML element as a BidiInput. The HTML element can be an
 * input element with type='text', a textarea element, or any contenteditable.
 * Overrides {@link goog.ui.Component#decorateInternal}.  Considered protected.
 * @param {Element} element  Element to decorate.
 * @protected
 * @override
 */
goog.ui.BidiInput.prototype.decorateInternal = function(element) {
  'use strict';
  goog.ui.BidiInput.superClass_.decorateInternal.call(this, element);
  this.init_();
};


/**
 * @return {?HTMLInputElement}
 * @override
 */
goog.ui.BidiInput.prototype.getElement = function() {
  return /** @type {?HTMLInputElement} */ (
      goog.ui.BidiInput.superClass_.getElement.call(this));
};


/**
 * Creates the element for the text input.
 * @protected
 * @override
 */
goog.ui.BidiInput.prototype.createDom = function() {
  'use strict';
  this.setElementInternal(this.getDomHelper().createDom(
      goog.dom.TagName.INPUT, {'type': goog.dom.InputType.TEXT}));
  this.init_();
};


/**
 * Initializes the events and initial text direction.
 * Called from either decorate or createDom, after the input field has
 * been created.
 * @private
 */
goog.ui.BidiInput.prototype.init_ = function() {
  'use strict';
  // Set initial direction by current text
  this.setDirection_();

  // Listen to value change events
  this.inputHandler_ = new goog.events.InputHandler(this.getElement());
  goog.events.listen(
      this.inputHandler_, goog.events.InputHandler.EventType.INPUT,
      this.setDirection_, false, this);
};


/**
 * Set the direction of the input element based on the current value. If the
 * value does not have any strongly directional characters, remove the dir
 * attribute so that the direction is inherited instead.
 * This method is called when the user changes the input element value, or
 * when a program changes the value using
 * {@link goog.ui.BidiInput#setValue}
 * @private
 */
goog.ui.BidiInput.prototype.setDirection_ = function() {
  'use strict';
  var element = this.getElement();
  if (element) {
    var text = this.getValue();
    goog.i18n.bidi.setElementDirByTextDirectionality(element, text);
  }
};


/**
 * Returns the direction of the input element.
 * @return {?string} Return 'rtl' for right-to-left text,
 *     'ltr' for left-to-right text, or null if the value itself is not
 *     enough to determine directionality (e.g. an empty value), and the
 *     direction is inherited from a parent element (typically the body
 *     element).
 * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration
 */
goog.ui.BidiInput.prototype.getDirection = function() {
  'use strict';
  var dir = this.getElement().dir;
  if (dir == '') {
    dir = null;
  }
  return dir;
};


/**
 * Sets the value of the underlying input field, and sets the direction
 * according to the given value.
 * @param {string} value  The Value to set in the underlying input field.
 * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration
 */
goog.ui.BidiInput.prototype.setValue = function(value) {
  'use strict';
  var element = this.getElement();
  if (element.value != null) {
    element.value = value;
  } else {
    goog.dom.setTextContent(element, value);
  }
  this.setDirection_();
};


/**
 * Returns the value of the underlying input field.
 * @return {string} Value of the underlying input field.
 * @suppress {strictMissingProperties} Part of the go/strict_warnings_migration
 */
goog.ui.BidiInput.prototype.getValue = function() {
  'use strict';
  var element = this.getElement();
  return element.value != null ? element.value :
                                 goog.dom.getRawTextContent(element);
};


/** @override */
goog.ui.BidiInput.prototype.disposeInternal = function() {
  'use strict';
  if (this.inputHandler_) {
    goog.events.removeAll(this.inputHandler_);
    this.inputHandler_.dispose();
    this.inputHandler_ = null;
  }
  goog.ui.BidiInput.base(this, 'disposeInternal');
};
