/* eslint-disable */
import React from "react";
import { TagInput } from "./TagInput";
import { AttributeValue, Value } from "./AttributeSelect";
import { FocusPosType } from "./TagSearchBox";
import { withTranslation, WithTranslationProps } from "../i18n";
import { Bubble } from "../bubble";
import { Icon } from "../icon";
import { withConfig, WithConfigProps } from "../_util/config-context";
import { Text } from "../text";

export interface TagValue {
  /**
   * 标签属性
   */
  attr?: AttributeValue;

  /**
   * 标签属性值
   */
  values?: Value[];
}

export interface TagProps extends WithConfigProps, WithTranslationProps {
  /**
   * 标签属性
   */
  attr?: AttributeValue;

  /**
   * 标签属性值
   */
  values?: Value[];

  /**
   * 触发标签相关事件
   */
  dispatchTagEvent?: (type: string, payload?: any) => void;

  /**
   * 所有属性集合
   */
  attributes: AttributeValue[];

  /**
   * 当前聚焦状态
   */
  focused: FocusPosType;

  /**
   * 最大长度
   */
  maxWidth?: number;

  /**
   * 搜索框是否处于展开状态
   */
  active: boolean;
}

export interface TagState {
  inEditing: boolean;
}

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

class ITag extends React.Component<TagProps, TagState> {
  state: TagState = {
    inEditing: false,
  };

  focusTag(): void {
    (this["input-inside"] as any)?.focusInput();
  }

  focusInput(): void {
    (this["input"] as any)?.focusInput();
  }

  resetInput() {
    (this["input-inside"] as any)?.resetInput();
  }

  setInputValue(value: string, callback?: Function): void {
    (this["input"] as any)?.setInputValue(value, callback);
  }

  getInputValue(): string {
    return this["input"]?.getInputValue();
  }

  addTagByInputValue(): boolean {
    return this["input"]?.addTagByInputValue();
  }

  addTagByEditInputValue(): boolean {
    if (!this["input-inside"]) return;
    return this["input-inside"]?.addTagByInputValue();
  }

  setInfo(info: any, callback?: Function): void {
    return this["input"]?.setInfo(info, callback);
  }

  moveToEnd(): void {
    return this["input"]?.moveToEnd();
  }

  getInfo(): any {
    const { attr, values } = this.props;
    return { attr, values };
  }

  edit(pos: string): void {
    this.setState({ inEditing: true });
    const input = this["input-inside"];
    input?.setInfo(this.getInfo(), () => {
      if (pos === "attr") {
        return input.selectAttr();
      }
      return input.selectValue();
    });
  }

  editDone(): void {
    this.setState({ inEditing: false });
  }

  handleTagClick = (e, pos?: string): void => {
    this.props.dispatchTagEvent("click", pos);
    e.stopPropagation();
  };

  handleDelete = e => {
    e.stopPropagation();
    this.props.dispatchTagEvent("del");
  };

  handleKeyDown = (e): void => {
    if (!keys[e.keyCode]) return;

    e.preventDefault();

    switch (keys[e.keyCode]) {
      case "tab":
      case "enter":
        this.props.dispatchTagEvent("click", "value");
        break;

      case "backspace":
        this.props.dispatchTagEvent("del", "keyboard");
        break;
    }
  };

  render() {
    const { inEditing } = this.state;
    const {
      t,
      config: { classPrefix },
      active,
      attr,
      values,
      dispatchTagEvent,
      attributes,
      focused,
      maxWidth,
    } = this.props;

    let attrStr = attr ? attr.name : "";
    if (attr && attr.name) {
      attrStr += ": ";
    }
    const valueStr = values.map(item => item.name).join(" | ");

    const removeable = attr && "removeable" in attr ? attr.removeable : true;

    return (
      <div
        style={{
          display: "inline-block",
          minHeight: 20,
          width: inEditing && !active ? 0 : "auto",
          position: "relative",
          verticalAlign: "inherit",
        }}
      >
        <Bubble content={active ? t.tagSearchBoxEditingTips : null}>
          <div
            className={`${classPrefix}-tag`}
            ref={div => (this["content"] = div)}
            style={{
              display: inEditing ? "none" : undefined,
              paddingRight: removeable ? undefined : 8,
            }}
            onClick={this.handleTagClick}
          >
            <Text
              parent="span"
              theme="label"
              onClick={e => this.handleTagClick(e, "attr")}
            >
              {attrStr}
            </Text>
            <span onClick={e => this.handleTagClick(e, "value")}>
              {valueStr}
            </span>
            {active && removeable && (
              <Icon type="dismiss" onClick={this.handleDelete} />
            )}
          </div>
        </Bubble>
        <TagInput
          type="edit"
          hidden={!inEditing}
          maxWidth={maxWidth}
          handleKeyDown={this.handleKeyDown}
          active={active}
          ref={input => (this["input-inside"] = input)}
          attributes={attributes}
          dispatchTagEvent={dispatchTagEvent}
          isFocused={focused === FocusPosType.INPUT_EDIT}
        />
      </div>
    );
  }
}

export const Tag = withConfig(withTranslation(ITag));
