var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { MapToComponentField, MapToComponentMethod, VegaSlimmer } from 'vega-slimmer/core';
import { isArrayEqual } from '../../../../utils/array';
import { findParent } from '../../../../utils/ui';
import { LogUtility } from '../../../../utils/log';
/**
 * The `VegaDropdownSelectedController` class handles the selection of items in a dropdown menu,
 * either adding them to an array or setting them as the only selected item.
 */
export class VegaDropdownSelectedController extends VegaSlimmer {
  /**
   * Component lifecycle - componentWillLoad
   */
  componentWillLoad() {
    this.checkSelectedSourceKey(this.selectedSourceKey);
  }
  /**
   * The function clears the selected source key based on the select type.
   */
  clearSelection() {
    this.selectedSourceKey = this.selectType === 'multiple' ? [] : '';
  }
  /**
   * The callback to handle [getSelection]{@link VegaTable.getSelection}
   *
   * @returns {string[] | string} The selected row keys array
   */
  getSelection() {
    return this.selectedSourceKey;
  }
  /**
   * The function `watchSelectedRowKeySet` sets the `selectedSourceKey` property based on the
   * `selectType` and the provided `keys`.
   *
   * @param {string[] | string} keys - The parameter "keys" can be either a string or an array of
   * strings.
   * @returns {void} -.
   */
  watchSelectedRowKeySet(keys) {
    this.checkSelectedSourceKey(keys);
  }
  /**
   * The function `watchSelectType()` updates the value of `selectedSourceKey` based on the value of
   * `selectType`.
   *
   * @returns {void} -.
   */
  watchSelectType() {
    this.checkSelectedSourceKey(this.selectedSourceKey);
  }
  /**
   * The function "watchSelectedSourceKey" assigns a value to the variable "selectedSourceKey" by calling
   * the function "checkSelectedSourceKey" with the current value of "selectedSourceKey" as an argument.
   *
   * @param {string[] | string} newValue - new value.
   * @param {string[] | string} oldValue - old value.
   */
  watchSelectedSourceKey(newValue, oldValue) {
    if (Array.isArray(oldValue) && Array.isArray(newValue) && isArrayEqual(oldValue, newValue))
      return;
    this.checkSelectedSourceKey(newValue);
  }
  /**
   * The function "watchSource" synchronizes the dropdown current data and checks the selected source
   * key.
   */
  watchSource() {
    this.checkSelectedSourceKey(this.selectedSourceKey);
  }
  /**
   * The function checks if the input is an acceptable item selection observer.
   *
   * @param {unknown} input - The input parameter is of type unknown, which means it can be any type.
   * @returns {boolean} a boolean value.
   */
  isAcceptableItemSelectionObserver(input) {
    if (input['host']['tagName'] === 'VEGA-DROPDOWN-ITEM') {
      return this.isCurrentDropdown(input['host']);
    }
    /* istanbul ignore next */
    return false;
  }
  /**
   * The select function handles the selection of a key, either adding it to the selectedSourceKey array
   * or setting it as the only selected key.
   *
   * @param {string} key - The key parameter is a string that represents the selected item.
   */
  select(key) {
    if (this.selectType === 'multiple') {
      if (this.selectedSourceKey.includes(key)) {
        this.selectedSourceKey = [
          ...this.selectedSourceKey.filter((itemKey) => itemKey !== key),
        ];
      }
      else {
        this.selectedSourceKey = [...this.selectedSourceKey, key];
      }
    }
    else if (this.selectType === 'single') {
      this.selectedSourceKey = key;
      this.appenderController.hide();
    }
    else {
      this.appenderController.hide();
    }
    this.dropdownClickEventEmitter.emit(key);
  }
  /**
   * The reset action.
   */
  reset() {
    this.selectedSourceKey = this.selectType === 'multiple' ? [] : '';
    if (this.selectType !== 'multiple') {
      this.appenderController.hide();
    }
    this.resetEventEmitter.emit();
  }
  /**
   * The function checks if the given item belongs to the current dropdown.
   * There have two cases:
   *   <vega-dropdown trigger="click">
   *      <div slot="items">
   *          // Case 1:
   *          // This item is in current vega-dropdown-content-box
   *	        <vega-dropdown-item label="Item 1" item-key="item1"></vega-dropdown-item>
   *          <vega-dropdown trigger="click">
   *              // Case 2:
   *              // This item is in current vega-dropdown-content-box, but it also in nest dropdown content slot
   *              // and not the realy item of parent dropdown, So we should have filter it out.
   *              <vega-dropdown-item label="Item 2" item-key="item2"></vega-dropdown-item>
   *              <div slot="items">
   *                 ...
   *              </div>
   *          </vega-dropdown>
   *      </div>
   *  <vega-dropdown>
   *
   * @param {HTMLElement} item - The `item` parameter is an HTMLElement, which represents an element in
   * the DOM (Document Object Model). It is the element that we want to check if it is currently in a
   * dropdown.
   * @returns {boolean} a boolean value.
   */
  isCurrentDropdown(item) {
    const appender = findParent(item, 'vega-dropdown-content-box');
    const isNestTriggerItem = item.parentElement.tagName === 'VEGA-DROPDOWN' || !!findParent(item, 'vega-dropdown');
    return this.host === appender['data-parent-ref'] && !isNestTriggerItem;
  }
  /**
   * The function `checkSelectedSourceKey` checks if the selected source key is valid based on the select
   * type and returns the key or an empty array/string if it is invalid.
   *
   * @param {string | string[]} key - The `key` parameter can be either a string or an array of strings.
   * @returns {void} The function `checkSelectedSourceKey` returns either a string or an array of strings.
   */
  checkSelectedSourceKey(key) {
    if (this.renderModeController.isSourceRenderMode() && !this.preserveValueIfNotInSource) {
      let result;
      if (typeof key === 'string' &&
        this.selectType === 'single' &&
        this.childrenController.isKeyExist(key)) {
        result = key;
      }
      else if (Array.isArray(key) && this.selectType === 'multiple') {
        result = this.checkMultipleSelectedKeys(key);
      }
      else {
        LogUtility.warn(`Invalid selectedSourceKey ${key} for ${this.selectType} mode`);
        result = this.selectType === 'multiple' ? [] : '';
      }
      this.selectedSourceKey = result;
    }
    else {
      this.selectedSourceKey = key;
    }
  }
  /**
   * The function checks if multiple selected keys exist and removes invalid keys, returning the valid
   * keys.
   *
   * @param {string[]} keys - An array of strings representing the selected keys.
   * @returns {string[]} an array of valid keys after removing any invalid keys from the input array.
   */
  checkMultipleSelectedKeys(keys) {
    const invalidKeys = [];
    const result = keys.filter((key) => {
      const isExist = this.childrenController.isKeyExist(key);
      if (!isExist)
        invalidKeys.push(key);
      return isExist;
    });
    if (invalidKeys.length > 0) {
      LogUtility.warn(`Invalid selectedSourceKey ${keys} for ${this.selectType} mode`);
    }
    return result;
  }
}
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "host", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "selectType", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "source", void 0);
__decorate([
  MapToComponentField({ writable: true })
], VegaDropdownSelectedController.prototype, "selectedSourceKey", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "preserveValueIfNotInSource", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "vegaDropdownClick", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "appenderController", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "childrenController", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "renderModeController", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "dropdownClickEventEmitter", void 0);
__decorate([
  MapToComponentField()
], VegaDropdownSelectedController.prototype, "resetEventEmitter", void 0);
__decorate([
  MapToComponentMethod('componentWillLoad')
], VegaDropdownSelectedController.prototype, "componentWillLoad", null);
__decorate([
  MapToComponentMethod('clearSelection')
], VegaDropdownSelectedController.prototype, "clearSelection", null);
__decorate([
  MapToComponentMethod('getSelection')
], VegaDropdownSelectedController.prototype, "getSelection", null);
__decorate([
  MapToComponentMethod('setSelection')
], VegaDropdownSelectedController.prototype, "watchSelectedRowKeySet", null);
__decorate([
  MapToComponentMethod('watchSelectType')
], VegaDropdownSelectedController.prototype, "watchSelectType", null);
__decorate([
  MapToComponentMethod('watchSelectedSourceKey')
], VegaDropdownSelectedController.prototype, "watchSelectedSourceKey", null);
__decorate([
  MapToComponentMethod('watchSource')
], VegaDropdownSelectedController.prototype, "watchSource", null);
