/* eslint-disable */
import React from "react";
import { List } from "../list";
import { DropdownBox } from "../dropdown";
import { TagSearchBoxContext } from "./TagSearchBoxContext";

export interface Value {
  /**
   * 唯一标识
   */
  key?: string;

  /**
   * 属性展示值
   */
  name: string;
}

export interface AttributeRenderProps {
  /**
   * 当前输入值
   */
  inputValue: string;

  /**
   * 监听某些操作键位被按下
   * @since 2.7.0
   */
  onOperationalKeyDown?: (
    listener: (key: "ArrowDown" | "ArrowUp" | "Enter" | "Tab") => void
  ) => void;

  /**
   * 确认选择
   */
  onSelect: (value: Value[]) => void;

  /**
   * 取消
   */
  onCancel: () => void;
}

export type AttributeType = "input" | "single" | "multiple" | "render";

export type AttributeTypeOptions =
  | ["input", {}]
  | ["render", {}]
  | [
      "single",
      {
        /**
         * 是否启用搜索
         * @default false
         * @since 2.5.0
         */
        searchable?: boolean;

        /**
         * 无可选项时提示内容
         */
        emptyText?: React.ReactNode;

        // /**
        //  * 是否启用虚拟滚动
        //  */
        // virtual?: boolean;

        // /**
        //  * 列表宽度，启用虚拟滚动后无法自适应宽度
        //  */
        // listWidth?: number;
      }
    ]
  | [
      "multiple",
      {
        /**
         * 是否开启全选
         * @default true
         */
        all?: boolean;

        /**
         * 是否启用搜索
         * @default false
         * @since 2.5.0
         */
        searchable?: boolean;

        /**
         * 无可选项时提示内容
         */
        emptyText?: React.ReactNode;

        // /**
        //  * 是否启用虚拟滚动
        //  */
        // virtual?: boolean;

        // /**
        //  * 列表宽度，启用虚拟滚动后无法自适应宽度
        //  */
        // listWidth?: number;
      }
    ];

export interface AttributeValue {
  /**
   * 为资源属性需求值的类型
   *
   * 可使用数组形式进行详细配置，如：
   *
   * ```js
   * ["multiple", { all: true }]
   * ```
   *
   * 其中：
   *
   *`"single"`：
   *  - `searchable` 是否启用搜索
   *  - `emptyText` 无可选项时提示内容
   *  - `virtual` 是否启用虚拟滚动
   *  - `listWidth` 列表宽度，启用虚拟滚动后无法自适应宽度
   *
   *`"multiple"`：
   *  - `all` 是否启用全选
   *  - `searchable` 是否启用搜索
   *  - `emptyText` 无可选项时提示内容
   *  - `virtual` 是否启用虚拟滚动
   *  - `listWidth` 列表宽度，启用虚拟滚动后无法自适应宽度
   *
   * @docType "input" | "single" | "multiple" | "render" | [AttributeType, AttributeOptions]
   */
  type: AttributeType | AttributeTypeOptions;

  /**
   * 属性的唯一标识，会在结果中返回
   */
  key: string;

  /**
   * 资源属性值名称
   */
  name: string;

  /**
   * 资源属性可用值
   * @docType Value[] | (() => Value[]) | (() => Promise<Value[]>)
   */
  values?: Value[] | (() => Value[]) | (() => Promise<Value[]>);

  /**
   * 该属性是否可重复选择
   * @default false
   */
  reusable?: boolean;

  /**
   * 该属性是否可移除
   * @default true
   */
  removeable?: boolean;

  /**
   * 自定义渲染
   */
  render?: (props: AttributeRenderProps) => React.ReactNode;
}

export interface AttributeSelectProps {
  attributes: AttributeValue[];
  inputValue: string;
  onSelect?: (attribute: AttributeValue) => void;
  maxHeight: number;
}

export interface AttributeSelectState {
  select: number;
  lastInputValue: string;
}

const keys = {
  "8": "backspace",
  "9": "tab",
  "13": "enter",
  "37": "left",
  "38": "up",
  "39": "right",
  "40": "down",
};

export class AttributeSelect extends React.Component<
  AttributeSelectProps,
  AttributeSelectState
> {
  static contextType = TagSearchBoxContext;
  state: AttributeSelectState = {
    select: -1,
    lastInputValue: this.props.inputValue,
  };

  static getDerivedStateFromProps(
    props: AttributeSelectProps,
    state: AttributeSelectState
  ) {
    if (state.lastInputValue !== props.inputValue) {
      return { select: -1, lastInputValue: props.inputValue };
    }
    return null;
  }

  // 父组件调用
  handleKeyDown = (keyCode: number): boolean => {
    if (!keys[keyCode]) return;
    const { onSelect } = this.props;
    const { select } = this.state;

    switch (keys[keyCode]) {
      case "enter":
      case "tab":
        if (select < 0) break;
        if (onSelect) {
          onSelect(this.getAttribute(select));
        }
        return false;

      case "up":
        this.move(-1);
        break;

      case "down":
        this.move(1);
        break;
    }
  };

  getUseableList(): Array<AttributeValue> {
    const { attributes, inputValue } = this.props;
    const { disableAttributesFilter } = this.context;

    if (disableAttributesFilter) {
      return attributes;
    }

    // 获取冒号前字符串模糊查询
    const fuzzyValue = /(.*?)(:|：).*/.test(inputValue)
      ? RegExp.$1
      : inputValue;

    return attributes.filter(
      item => item.name.includes(inputValue) || item.name.includes(fuzzyValue)
    );
  }

  getAttribute(select: number): AttributeValue {
    const list = this.getUseableList();
    if (select < list.length) {
      return list[select];
    }
  }

  move = (step: number): void => {
    const { select } = this.state;
    const list = this.getUseableList();
    if (list.length <= 0) return;
    this.setState({ select: (select + step + list.length) % list.length });
  };

  handleClick = (e: React.MouseEvent, index: number): void => {
    e.stopPropagation();
    e.nativeEvent.stopPropagation();
    if (this.props.onSelect) {
      this.props.onSelect(this.getAttribute(index));
    }
  };

  render() {
    const { attributesSelectTips } = this.context;
    const { select } = this.state;
    const { maxHeight } = this.props;
    const list = this.getUseableList().map((item, index) => {
      return (
        <List.Item
          key={index}
          selected={select === index}
          onClick={e => this.handleClick(e, index)}
        >
          {item.name}
        </List.Item>
      );
    });

    if (list.length === 0) return null;

    return (
      <DropdownBox onClick={e => e.stopPropagation()}>
        <List type="option" style={{ maxHeight }}>
          {attributesSelectTips && (
            <List.Item disabled>{attributesSelectTips}</List.Item>
          )}
          {list}
        </List>
      </DropdownBox>
    );
  }
}
