/* eslint-disable */
import React from "react";
import { List } from "../../list";
import { DropdownBox } from "../../dropdown";
import { SearchBox } from "../../searchbox";
import { EmptyTip } from "../../tips/EmptyTip";
import { searchFilter } from "../../_util/search-filter";

export interface SingleValueSelectProps {
  values: any[];
  inputValue: string;
  onChange?: (value: any[]) => void;
  onSelect?: (value: any[]) => void;
  offset: number;
  maxHeight: number;

  /**
   * 是否支持搜索
   * @default false
   * @since 2.5.0
   */
  searchable?: boolean;
}

export interface SingleValueSelectState {
  select: number;
  searchValue: string;
}

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

export class SingleValueSelect extends React.Component<
  SingleValueSelectProps,
  SingleValueSelectState
> {
  constructor(props) {
    super(props);
    const { values, inputValue } = this.props;

    let select = -1;
    values.forEach((item, index) => {
      if (item.name === inputValue) {
        select = index;
      }
    });

    this.state = {
      select,
      searchValue: "",
    };
  }

  componentDidMount() {
    const { select } = this.state;
    if (select < 0 && this.props.onSelect) {
      this.props.onSelect(this.getValue(select));
    }
  }

  static getDerivedStateFromProps(props: SingleValueSelectProps) {
    const { values, inputValue } = props;
    const list = values.map(item => item.name);
    const select = list.indexOf(inputValue);
    return { select };
  }

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

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

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

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

  getValue(select: number): any[] {
    if (select < 0) return [];
    const { values, inputValue } = this.props;
    const list = values;
    if (select < list.length) {
      return [list[select]];
    } else {
      const select = list.map(item => item.name).indexOf(inputValue);
      this.setState({ select });
      if (select < 0) return [];
      return [list[select]];
    }
  }

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

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

  render() {
    const { select, searchValue } = this.state;
    const { values, offset, maxHeight, searchable } = this.props;

    const list = values
      .map((item, index) => ({ ...item, index }))
      .filter(({ name }) => searchFilter(name, searchValue))
      .map(({ index, ...item }) => {
        return (
          <List.Item
            key={index}
            selected={select === index}
            onClick={e => this.handleClick(e, index)}
          >
            <span title={item.name} style={item.style || {}}>
              {item.name}
            </span>
          </List.Item>
        );
      });

    return (
      <DropdownBox
        style={{ marginLeft: offset }}
        onClick={e => e.stopPropagation()}
      >
        {!!searchable && (
          <SearchBox
            simple
            value={searchValue}
            onChange={searchValue => this.setState({ searchValue })}
          />
        )}
        <List type="option" style={{ maxHeight }}>
          {list.length === 0 ? (
            <List.StatusTip>
              <EmptyTip />
            </List.StatusTip>
          ) : (
            list
          )}
        </List>
      </DropdownBox>
    );
  }
}
