import { Menu } from "../../../plugins/contextMenu/menu/index.mjs";
import { clone, extend } from "../../../helpers/object.mjs";
import { arrayEach } from "../../../helpers/array.mjs";
import * as C from "../../../i18n/constants.mjs";
import { SEPARATOR } from "../../../plugins/contextMenu/predefinedItems/index.mjs";
import BaseUI from "./_base.mjs";
const privatePool = new WeakMap();

/**
 * @private
 * @class SelectUI
 */
class SelectUI extends BaseUI {
  static get DEFAULTS() {
    return clone({
      className: 'htUISelect',
      wrapIt: false
    });
  }
  constructor(hotInstance, options) {
    super(hotInstance, extend(SelectUI.DEFAULTS, options));
    privatePool.set(this, {});
    /**
     * Instance of {@link Menu}.
     *
     * @type {Menu}
     */
    this.menu = null;
    /**
     * List of available select options.
     *
     * @type {Array}
     */
    this.items = [];
    this.registerHooks();
  }

  /**
   * Register all necessary hooks.
   */
  registerHooks() {
    this.addLocalHook('click', () => this.onClick());
  }

  /**
   * Set options which can be selected in the list.
   *
   * @param {Array} items Array of objects with required keys `key` and `name`.
   */
  setItems(items) {
    this.items = this.translateNames(items);
    if (this.menu) {
      this.menu.setMenuItems(this.items);
    }
  }

  /**
   * Translate names of menu items.
   *
   * @param {Array} items Array of objects with required keys `key` and `name`.
   * @returns {Array} Items with translated `name` keys.
   */
  translateNames(items) {
    arrayEach(items, item => {
      item.name = this.translateIfPossible(item.name);
    });
    return items;
  }

  /**
   * Build DOM structure.
   */
  build() {
    super.build();
    this.menu = new Menu(this.hot, {
      className: 'htSelectUI htFiltersConditionsMenu',
      keepInViewport: false,
      standalone: true,
      container: this.options.menuContainer
    });
    this.menu.setMenuItems(this.items);
    const caption = new BaseUI(this.hot, {
      className: 'htUISelectCaption'
    });
    const dropdown = new BaseUI(this.hot, {
      className: 'htUISelectDropdown'
    });
    const priv = privatePool.get(this);
    priv.caption = caption;
    priv.captionElement = caption.element;
    priv.dropdown = dropdown;
    arrayEach([caption, dropdown], element => this._element.appendChild(element.element));
    this.menu.addLocalHook('select', command => this.onMenuSelect(command));
    this.menu.addLocalHook('afterClose', () => this.onMenuClosed());
    this.update();
  }

  /**
   * Update DOM structure.
   */
  update() {
    if (!this.isBuilt()) {
      return;
    }
    let conditionName;
    if (this.options.value) {
      conditionName = this.options.value.name;
    } else {
      conditionName = this.menu.hot.getTranslatedPhrase(C.FILTERS_CONDITIONS_NONE);
    }
    privatePool.get(this).captionElement.textContent = conditionName;
    super.update();
  }

  /**
   * Open select dropdown menu with available options.
   */
  openOptions() {
    const rect = this.element.getBoundingClientRect();
    if (this.menu) {
      this.menu.open();
      this.menu.setPosition({
        left: this.hot.isLtr() ? rect.left - 5 : rect.left - 31,
        top: rect.top - 1,
        width: rect.width,
        height: rect.height
      });
    }
  }

  /**
   * Close select dropdown menu.
   */
  closeOptions() {
    if (this.menu) {
      this.menu.close();
    }
  }

  /**
   * On menu selected listener.
   *
   * @private
   * @param {object} command Selected item.
   */
  onMenuSelect(command) {
    if (command.name !== SEPARATOR) {
      this.options.value = command;
      this.update();
      this.runLocalHooks('select', this.options.value);
    }
  }

  /**
   * On menu closed listener.
   *
   * @private
   */
  onMenuClosed() {
    this.runLocalHooks('afterClose');
  }

  /**
   * On element click listener.
   *
   * @private
   */
  onClick() {
    this.openOptions();
  }

  /**
   * Destroy instance.
   */
  destroy() {
    if (this.menu) {
      this.menu.destroy();
      this.menu = null;
    }
    const {
      caption,
      dropdown
    } = privatePool.get(this);
    if (caption) {
      caption.destroy();
    }
    if (dropdown) {
      dropdown.destroy();
    }
    super.destroy();
  }
}
export default SelectUI;