import React, {useState, useRef, useEffect} from 'react';
import classname from 'classnames'
import {message} from 'antd'
import {createNode, checkSymbol, checkKeycode} from './createNode'
import RuleInfo from './RuleInfo';
import style from './index.less'

const attrList = [
  'properties_realtime', // 实时属性
  'properties_analysis', // 计量属性
  'event', // 事件
  'attr',
]

const EditNode = (props) => {
  const {onEdit, expression, attrInfo, symbolInfo, oStyle,
    clearSymbol, clearAttr, isEdit, addDevice, deleteDevice
  } = props;
  const inputParent = useRef()
  const [extra, setExtra] = useState({})
  const [focusIndex, setFocusIndex] = useState()

  /* 自动获取节点 */
  const autoFocus = (keyIndex, direction) => {
    // console.log('next focus')
    const inputDom = inputParent?.current?.querySelectorAll('input');
    if (!inputDom) return;
    const target = direction ? keyIndex + 1 : keyIndex - 1;
    if (target > inputDom.length) return;
    if(inputDom[target]) inputDom[target].focus()
  }
  /* 添加Node */
  const addNode = (keyIndex, type = 'number', value) => {
    // console.log('addNode')
    let nodeConfig = {type}
    if (type === 'symbol') {nodeConfig.operator = value}
    if (type === 'number') {nodeConfig.value = value}
    if (attrList.includes(type)){
      nodeConfig = {...nodeConfig, ...value}
    }
    const newNode = createNode(nodeConfig)
    const newFuncNode = [...expression]
    newFuncNode.splice(keyIndex, 0, newNode);
    onEdit(newFuncNode)
  }
  /* 键盘输入事件 */
  const inputChange = (event, keyIndex) => {
    const valueCode = event.target.value.charCodeAt(0);
    if (valueCode >= 255) return false;
  };
  /* 失去焦点事件 */
  const finishAdd = (keyIndex) => {
    // console.log('onBLUR', keyIndex)
    setExtra({})
    if (extra.value) {
      const asyncStep = async () => {
        await addNode(keyIndex, 'number', extra.value)
        await autoFocus(keyIndex, true)
      }
      asyncStep().then()

    }
  }
  /* 监听回车删除事件 */
  const keydownAction = (event, keyIndex) => {
    const keyCode = window.event ? event.keyCode : event.which || null
    // console.log(keyCode, 'keyCode')
    // console.log(event.shiftKey, String.fromCharCode(keyCode))
    if (String.fromCharCode(keyCode) === 'å'){
      message.error('请切换英文输入法')
      return;
    }
    const extraValue = extra?.value || '';
    /* 删除事件 */
    if (keyCode === 8) {
      /* 如果有输入内容则删除 */
      if (extra?.keyIndex === keyIndex && extra.value) {
        const newExtra = {...extra}
        const extraValue = newExtra.value
        newExtra.value = extraValue.substring(0, extraValue.length -1)
        setExtra(newExtra)
      }else {
        /* 删除前一节点 */
        if (keyIndex === 0) return;
        const newFuncNode = [...expression];
        // console.log(newFuncNode[keyIndex -1])
        const deleteNode = newFuncNode[keyIndex -1];
        if (attrList.includes(deleteNode.type)){
          // console.log('delete attr')
          deleteDevice && deleteDevice(deleteNode.deviceId)
        }
        newFuncNode.splice(keyIndex - 1, 1);
        onEdit(newFuncNode)
        autoFocus(keyIndex, false)
      }
    }
    /* 回车事件 */
    if (keyCode === 13) {
      const asyncStep = async () => {
        await finishAdd(keyIndex);
        await autoFocus(keyIndex, true)
      }
      asyncStep().then()
    }
    /* 前进事件 */
    if (keyCode === 39 && !extra.value && !event.keyCode) {
      // console.log('---->')
      const inputDom = inputParent.current.querySelectorAll('input');
      const target =  keyIndex + 1;
      if (target > inputDom.length) return;
      if(inputDom[target]) inputDom[target].focus()
    }
    /* 后退事件 */
    if (keyCode === 37 && !extra.value && !event.keyCode) {
      // console.log('<----')
      const inputDom = inputParent.current.querySelectorAll('input');
      const target =  keyIndex - 1;
      if (target < 0) return;
      if(inputDom[target]) inputDom[target].focus()
    }
    /* 数字 */
    if ((keyCode >= 48 && event.keyCode <= 57 || keyCode === 190) && !event.shiftKey){
      const keyNum = String.fromCharCode(keyCode);
      const newExtra = {
        keyIndex,
        value: extraValue + (keyNum === '¾' ? '.' : keyNum)
      }
      setExtra(newExtra);
    }
    /* 符号 */
    const hasShift = event.shiftKey;
    const testSymbol = checkKeycode(hasShift, keyCode)
    if (testSymbol.isSymbol){
      const { symbolValue } = testSymbol
      setExtra({})
      if (extraValue.trim() !== '') {
        const newFuncNode = [...expression]
        const addNumAndSym = () => {
          const targetNumber = {
            type: 'number',
            value: extraValue
          }
          const numberNode = createNode(targetNumber)
          newFuncNode.splice(keyIndex, 0, numberNode);
          const targetSymbol = {
            type: 'symbol',
            operator: symbolValue
          }
          const symbolNode = createNode(targetSymbol)
          newFuncNode.splice(keyIndex + 1, 0, symbolNode);
          onEdit(newFuncNode)
        }
        const asyncStep = async () => {
          // await finishAdd(keyIndex)
          await addNumAndSym();
          await autoFocus(keyIndex + 1, true)
        }
        asyncStep().then()
      }else {
        const asyncStep = async () => {
          await addNode(keyIndex, 'symbol', symbolValue);
          await autoFocus(keyIndex, true)
        }
        asyncStep().then()
      }
    }
  }

  /* input onFocus 事件  */
  const inputFocus = (event, keyIndex) => {
    setFocusIndex(keyIndex)
    if (keyIndex < 0) return;
    const inputDom =inputParent.current.querySelectorAll('input');
    inputDom[keyIndex].focus()
  }
  const defaultFocus = () => {
    const inputDom =inputParent.current.querySelectorAll('input');
    if (inputDom.length > 0) inputDom[inputDom.length - 1].focus()
  }

  useEffect(() => {
    if (isEdit && symbolInfo && focusIndex !== undefined && focusIndex !== null) {
      const asyncStep = async () => {
        await addNode(focusIndex === 0 ? 0 : focusIndex, 'symbol', symbolInfo);
        if (clearSymbol) await clearSymbol();
        await autoFocus(focusIndex, true)
      }
      asyncStep().then()
    } else {
      clearSymbol()
    }
  }, [symbolInfo])

  useEffect(() => {
    if (isEdit && attrInfo && focusIndex !== undefined && focusIndex !== null) {
      if(addDevice) addDevice(attrInfo)
      const asyncStep = async () => {
        await addNode(focusIndex === 0 ? 0 :focusIndex, attrInfo.type, attrInfo);
        await clearAttr();
        await autoFocus(focusIndex, true)
      }
      asyncStep().then()
    } else {
      clearAttr()
    }
  }, [attrInfo])

  return (
    <div
      ref={inputParent}
      onClick={defaultFocus}
      className={classname(style.edit_area)}
      style={oStyle}
    >
      {extra?.keyIndex === 0 && extra?.value && (
        <div style={{marginLeft: 13,marginRight: '-5px'}}>{extra?.value}</div>
      )}
      <input
        value=""
        onClick={event => event.stopPropagation()}
        onFocus={event => inputFocus(event, 0)}
        onBlur={() => finishAdd(0)}
        onKeyDown={event => keydownAction(event, 0)}
        onChange={(event) => inputChange(event, 0)}
        className={classname(style.hide_input, style.inner_input)}
      />
      {expression?.length > 0 && expression.map((item, index) => (
        <div key={index} className={style.pos_aline_no_wrap} onClick={event => event.stopPropagation()}>
          <RuleInfo
            parentRef={inputParent}
            {...item}
            targetKey={index + 1}
          />
          {extra?.keyIndex - 1 === index && extra?.value && (
            <div
              className="pos_center"
              style={{marginLeft: 13,marginRight: '-5px'}}
            >{extra?.value}</div>
          )}
          <input
            value=""
            onFocus={event => inputFocus(event, index + 1)}
            onBlur={() => finishAdd(index + 1)}
            onKeyDown={event => keydownAction(event, index + 1)}
            onChange={(event) => inputChange(event, index + 1)}
            className={classname(style.hide_input, style.inner_input)}
          />

        </div>
      ))}
    </div>
  );
};

export default EditNode;