import React from 'react';
import { FormItem, FormControlProps, FormBaseControl } from './Item';
import cx from 'classnames';
import { filter } from '../../utils/tpl';
import NumberInput from '../../components/NumberInput';
import { FormOptionsControl } from './Options';
import Select, { normalizeOptions, Option } from '../../components/Select';
import { PlainObject } from '../../types';
import { EventEnum, EventSub } from '../../utils/sub';
import { focusInputAndChooseInput, standardValueText } from '../../utils/helper';
import { supportStatic } from './StaticHoc';
import { isNil } from 'lodash';
/**
 * 数字输入框
 * 文档：https://baidu.gitee.io/amis/docs/components/form/number
 */
export interface NumberControlSchema extends FormBaseControl {
  type: 'input-number';

  /**
   * 最大值
   */
  max?: number;

  /**
   * 最小值
   */
  min?: number;

  /**
   * 步长
   */
  step?: number;

  /**
   * 精度
   */
  precision?: number;

  /**
   * 默认当然是
   */
  showSteps?: boolean;
  /**
   * 边框模式，全边框，还是半边框，或者没边框。
   */
  borderMode?: 'full' | 'half' | 'none';
  /**
   * 前缀
   */
  prefix?: string;
  /**
   * 后缀
   */
  suffix?: string;

  /**
   * 单位列表
   */
  unitOptions?: string | Array<Option> | string[] | PlainObject;

  /**
   * 是否千分分隔
   */
  kilobitSeparator?: boolean;
  /**
   * 只读
   */
  readOnly?: boolean;
  /**
   * 静态展示
   */
  staticShow?: boolean;
}

export interface NumberProps extends FormControlProps {
  placeholder?: string;
  max?: number | string;
  min?: number | string;
  step?: number;
  precision?: number;
  /**
   * 边框模式，全边框，还是半边框，或者没边框。
   */
  borderMode?: 'full' | 'half' | 'none';
  /**
   * 前缀
   */
  prefix?: string;
  /**
   * 后缀
   */
  suffix?: string;
  /**
   * 是否千分分隔
   */
  kilobitSeparator?: boolean;
  /**
   * 只读
   */
  readOnly?: boolean;
}

interface NumberState {
  // 数字单位，将会影响输出
  unit?: string;
  unitOptions?: Option[];
}

export default class NumberControl extends React.Component<
  NumberProps,
  NumberState
> {
  static defaultProps: Partial<NumberProps> = {
    step: 1,
    resetValue: null
  };
  dom: any
  timer: any
  hasFormat = false;
  constructor(props: NumberProps) {
    super(props);
    this.dom = React.createRef()
    const unit = this.getUnit();
    const unitOptions = normalizeOptions(props.unitOptions);
    this.state = { unit, unitOptions };
  }


  // 解析出单位
  getUnit() {
    const props = this.props;
    if (props.unitOptions && props.unitOptions.length) {
      const optionValues = normalizeOptions(props.unitOptions).map(
        option => option.value
      );
      // 如果有值就解析出来作为单位
      if (props.value && typeof props.value === 'string') {
        let unit = optionValues[0];
        // 先找长的字符，这样如果有 ab 和 b 两种后缀相同的也能识别
        optionValues.sort((a, b) => b.length - a.length);
        for (const optionValue of optionValues) {
          if (props.value.endsWith(optionValue)) {
            unit = optionValue;
            break;
          }
        }
        return unit;
      } else {
        // 没有值就使用第一个单位
        return optionValues[0];
      }
    }
    return undefined;
  }

  handleChange = (inputValue: any) => {
    const { classPrefix: ns, onChange, resetValue, unitOptions } = this.props;
    // Jay 允许输入字符类型的值
    // if (inputValue && typeof inputValue !== 'number') {
    //   return;
    // }
    // Jay
    if (typeof inputValue !== 'number' && inputValue && (this.props.prefix || this.props.suffix)) {
      if (this.props.suffix && inputValue.indexOf(this.props.suffix) === -1) {
        inputValue = inputValue.slice(0, -1)
      }
      this.props.prefix && inputValue && (inputValue = inputValue.replace(this.props.prefix, ''))
      this.props.suffix && inputValue && (inputValue = inputValue.replace(this.props.suffix, ''))
    }
    // Jay
    if (typeof inputValue === 'number' && inputValue !== null && unitOptions && this.state.unit) {
      inputValue = inputValue + this.state.unit;
    }

    if (typeof inputValue === 'number' || inputValue == null) {
      onChange(inputValue === null ? resetValue ?? null : inputValue);
    }
  }

  filterNum(value: number | string | undefined) {
    if (typeof value !== 'number') {
      value = filter(value, this.props.data);
      value = /^[-]?\d+/.test(value) ? +value : undefined;
    }
    return value;
  }

  // 单位选项的变更
  handleChangeUnit = (option: Option) => {
    let value = this.props.value;
    const prevUnitValue = this.state.unit;
    this.setState({ unit: option.value }, () => {
      if (value) {
        value = value.replace(prevUnitValue, '');
        this.props.onChange(value + this.state.unit);
      }
    });
  }

  componentDidUpdate(prevProps: NumberProps) {
    if (this.props.value !== prevProps.value) {
      const unit = this.getUnit();
      this.setState({ unit: unit });
    }
    if (this.props.unitOptions !== prevProps.unitOptions) {
      this.setState({ unitOptions: normalizeOptions(this.props.unitOptions) });
    }
  }
  componentWillUnmount(): void {
    this.dom = null
  }

  handleKeyArrow = (e: any) => {
    const { rowIndex, colIndex } = this.props
    const containerTable = this.dom?.current?.closest('table')
    const tableId = containerTable?.getAttribute('table-id')
    let inputarray: number[] = []
    if (!this.props.quickEditForm) {
      //  触发自己
      EventSub.emit(`${tableId}/${EventEnum.ShowVistiMap}`, rowIndex, colIndex, true)
      // 并稍后聚焦
      focusInputAndChooseInput(e.currentTarget)
    }
    // 获取当前表格下的所有输入框
    const Donm: any = containerTable.querySelectorAll(`input[class*="Number-input"][col-index="${this.props.colIndex}"]`)
    for (let index = 0; index < Donm.length; index++) {
      if (Donm[index].type === "text" && this.props.name === Donm[index].name) {
        inputarray.push(index)
      }
    }

    if (inputarray.length) {
      for (let index = 0; index < Donm.length; index++) {
        if (Donm[index].type === "text" && this.props.name === Donm[index].name && e.currentTarget === Donm[index]) {
          inputarray.forEach((item, i) => {
            if (item == index) {
              if (e.key === "ArrowDown") {
                EventSub.emit(`${tableId}/${EventEnum.ShowVistiMap}`, rowIndex + 1, colIndex, true) // 广播订阅事件
                if (item + 1 >= inputarray.length) return
                focusInputAndChooseInput(Donm[inputarray[item + 1]])
              } else {
                EventSub.emit(`${tableId}/${EventEnum.ShowVistiMap}`, rowIndex - 1, colIndex, true) // 广播订阅事件
                if (item - 1 < 0) return
                focusInputAndChooseInput(Donm[inputarray[item - 1]])
              }
            }
          })
          break
        }
      }
    }

  }
  handleKeyDown = (e: KeyboardEvent) => {
    if ((e.key === "ArrowUp" || e.key === "ArrowDown")) {
      e.stopPropagation()
      this.handleKeyArrow(e)
    }
  }

  @supportStatic()
  render(): JSX.Element {
    const {
      className,
      classPrefix: ns,
      value,
      step,
      precision,
      max,
      min,
      disabled,
      placeholder,
      showSteps,
      borderMode,
      suffix,
      prefix,
      kilobitSeparator,
      unitOptions,
      readOnly
    } = this.props;

    let precisionProps: any = {};

    const finalPrecision = this.filterNum(precision);
    if (typeof finalPrecision === 'number') {
      precisionProps.precision = finalPrecision;
    }

    const unit = this.state?.unit;
    // 数据格式化
    const formatter = (value: string | number) => {
      if (isNil(value) || value === '') return '';
      let precision = this.props.precision ?? 0
      let suffix = this.props.suffix
      let prefix = this.props.prefix
      let carry = false

      if (this.hasFormat) {
        precision = Math.min(("" + value).toString().split('.')[1]?.length ?? 0, this.props.precision ?? 0)
        suffix = undefined
        prefix = undefined
        carry = true
      }

      value = standardValueText(value + '', {
        precision,
        prefix,
        suffix,
        kilobitSeparator,
        carry
      })

      return value;
    };

    // 将数字还原
    const parser = (value: string) => {
      if (value) {
        prefix && (value = value.replace(prefix, ''));
        suffix && (value = value.replace(suffix, ''));
        kilobitSeparator && (value = value.replace(/,/g, ''));
      }
      return value;
    };

    const finalValue =
      unit && value && typeof value === 'string'
        ? value.replace(unit, '')
        : value;

    return (
      <div
        ref={this.dom}
        className={cx(
          `${ns}NumberControl`,
          {
            [`${ns}NumberControl--withUnit`]: unitOptions
          },
          className
        )}
      >
        <NumberInput
          colIndex={this.props.colIndex}
          value={finalValue}
          step={step || 1}
          max={this.filterNum(max)}
          min={this.filterNum(min)}
          formatter={formatter}
          parser={parser}
          name={this.props.name || ''}
          onChange={this.handleChange}
          onBlur={(e) => {
            this.props.onBlur?.(e)
            this.hasFormat = false
          }}
          onFocus={() => {
            this.hasFormat = true
          }}
          disabled={disabled}
          keyboard={this.props.keyboard || false}
          placeholder={placeholder}
          precision={finalPrecision}
          onKeyDown={this.handleKeyDown}
          showSteps={showSteps}
          borderMode={borderMode}
          readOnly={readOnly}
          prefix={prefix}
          suffix={suffix}
        />
        {unitOptions ? (
          <Select
            value={unit}
            clearable={false}
            options={this.state.unitOptions || []}
            onChange={this.handleChangeUnit}
          />
        ) : null}
      </div>
    );
  }
}

@FormItem({
  type: 'input-number'
})
export class NumberControlRenderer extends NumberControl {
  static defaultProps: Partial<FormControlProps> = {
    validations: 'isNumeric',
    ...NumberControl.defaultProps
  };
}
