import {Col, List, Row, Space} from 'antd';
import debounce from 'lodash/debounce';
import {forwardRef, memo, useCallback, useImperativeHandle, useRef, useState} from 'react';
import MonacoEditor from 'react-monaco-editor';
import {styled} from "styled-components";
import DatartQueryLanguageSpecification from "./DatartQueryLanguageSpecification";
import ComputedFunctionDescriptions from './computed-function-description-map';
import {FieldTemplate, FunctionTemplate, VariableTemplate} from "./utils";
import ChartComputedFieldEditorDarkTheme from "./ChartComputedFieldEditorDarkTheme";
import {useAppSelector} from "../../../redux/configureStore";
import {selectTheme} from "../../../styles/theme/slice/selectors";
import {
  CloseSquareOutlined,
  DeleteTwoTone,
  MinusSquareOutlined,
  PlusSquareOutlined
} from "@ant-design/icons";

const TextType = {
  Field: 'field',
  Variable : 'variable',
  Function : 'function',
}


const component = forwardRef(({
  value,
  fields,
  onChange,
  toolbar
}, ref) => {
  const editorRef = useRef(null);
  const monacoRef = useRef(null);
  const [description, setDescription] = useState();
  const THEME = useAppSelector(selectTheme);

  // 数据格式化
  const formatValue = (expression="",type)=>{
    let syntax = expression;
    let arr = [];
    fields.forEach(({name,bizName,id})=>{
      if (type==='change'){
        const flag = syntax.includes(`[${name}]`)
        if (flag){
          syntax = syntax.replaceAll(`[${name}]`, `[${bizName}]`);
          arr.push({name,bizName,id})
        }
      }
      if (type==="init"){
        const flag = syntax.includes(bizName)
        if (flag){
          syntax = syntax.replaceAll(bizName, `[${name}]`);
          arr.push({name,bizName,id})
        }
      }
    })
    return {
      syntax,
      expr:syntax.replaceAll(/\[|\]/g, ''),
      metrics:arr,
      filterSql:''
    }
  }

  // 插入字段
  const insertField = (value, funcDesc) => {
    if (!value) {
      return;
    }
    if (funcDesc) {
      setDescription(funcDesc);
    }
    editorRef?.current?.trigger('keyboard', 'type', { text: value });
    editorRef?.current?.focus();
  }

  // 清空数据
  const clear = ()=>{
    editorRef.current?.getModel()?.setValue("")
  }

  useImperativeHandle(ref, () => ({
    insertField,
    formatValue,
    clear
  }));

  // 右侧函数的数据
  const defaultFunctionCategory = 'all';
  const [selectedFunctionCategory, setSelectedFunctionCategory] = useState(
    defaultFunctionCategory,
  );

  const getEditorNewLineCharactor = () => {
    return editorRef?.current?.getModel()?.getEOL();
  };

  const onEditorChange = debounce(newValue => {
    const removeNewLineCharactor = value => value.replaceAll(getEditorNewLineCharactor(), ' ');
    const formatData = removeNewLineCharactor(newValue);
    onChange && onChange(formatData);
  }, 200);

  const handleDescriptionChange = debounce(descKey => {
    if (!descKey) {
      return;
    }
    const funcDesc = ComputedFunctionDescriptions.find(d => d.name === descKey);
    if (!!funcDesc) {
      setDescription(funcDesc);
    }
  }, 200);

  const handleEdtiorWillMount = monacoEditor => {
    monacoEditor.languages.register({ id: 'dql' });
    monacoEditor.languages.setMonarchTokensProvider('dql', {
      ...DatartQueryLanguageSpecification,
      builtinFunctions: ComputedFunctionDescriptions.map(f => f.name),
    });

    // monacoEditor.editor.defineTheme(
    //   'dqlTheme',
    //   ChartComputedFieldEditorDarkTheme,
    // );
  };

  const handleEditorDidMount = (editor, monaco) => {
    editorRef.current=editor;
    monacoRef.current=monaco;
    const model = editor.getModel();
    editor.onDidChangeCursorPosition(listener => {
      const positionWord = model.getWordAtPosition(listener.position);
      handleDescriptionChange(positionWord?.word);
    });
  };
  const getInputText = (value, type) => {
    switch (type) {
      case TextType.Field:
        return FieldTemplate(value);
      case TextType.Variable:
        return VariableTemplate(value);
      case TextType.Function:
        return FunctionTemplate(value);
      default:
        return value;
    }
  };

  const getFunctionList = () => {
    return ComputedFunctionDescriptions.filter(
      item =>
        item.type === selectedFunctionCategory ||
        !selectedFunctionCategory ||
        selectedFunctionCategory === defaultFunctionCategory,
    ).map(item => ({
      label: item.name,
      value: item.name,
    }));
  };

  const handleFieldFunctionSelected = funName => {

    const functionDescription = ComputedFunctionDescriptions.find(
      f => f.name === funName,
    );

    editorRef.current?.trigger('keyboard', 'type', { text: getInputText(funName, TextType.Function) });
    editorRef.current?.focus();
    setDescription(functionDescription);
  };

  const renderFunctionDescriptionInfo = () => {
    if (!description) {
      return '';
    }
    return `${description.description}: ${description.syntax}`;
  };

  const handleFieldSelected = useCallback(field => {
    editorRef.current?.trigger('keyboard', 'type', { text: getInputText(field, TextType.Field) });
    editorRef.current?.focus();
  }, []);

  const insertSymbol = (text)=>{
    editorRef.current?.trigger('keyboard', 'type', { text });
    editorRef.current?.focus();
  }

  const iconStyle = {fontSize:20,cursor: 'pointer'}

  return (
    <Row>
      <Col span={5}>
        <ListSelector
          type="center"
          bordered
          dataSource={fields}
          renderItem={(item) => (
            <List.Item
              style={{cursor: "pointer"}}
              onClick={()=>handleFieldSelected(item.name)}
            >
              {item.name}
            </List.Item>
          )}
        />
      </Col>
      <Col span={19}>
        <StyledChartComputedFieldEditor>
          <Toolbar>
            <Space>
              <PlusSquareOutlined style={{...iconStyle,marginLeft:55}} onClick={()=>insertSymbol("+")}/>
              <MinusSquareOutlined style={iconStyle} onClick={()=>insertSymbol("-")}/>
              <CloseSquareOutlined style={iconStyle} onClick={()=>insertSymbol("*")}/>
              <CustomIcon children="÷" onClick={()=>insertSymbol("/")}/>
              <CustomIcon children="=" onClick={()=>insertSymbol("=")}/>
              <CustomIcon children="(" style={{fontSize:14,verticalAlign:'0.18em'}} onClick={()=>insertSymbol("()")}/>
              <CustomIcon children=")" style={{fontSize:14,verticalAlign:'0.18em'}} onClick={()=>insertSymbol(")")}/>
            </Space>
            <DeleteTwoTone twoToneColor="red" style={{...iconStyle,float:'right',marginRight:10}} onClick={clear} />
          </Toolbar>
          <MonacoEditor
            width="100%"
            height="180"
            language="dql"
            theme={THEME['mainTheme'] === 'white' ? THEME : 'vs-dark'}
            value={formatValue(value, 'init').syntax}
            onChange={onEditorChange}
            editorWillMount={handleEdtiorWillMount}
            editorDidMount={handleEditorDidMount}
            options={{
              lineDecorationsWidth: 1,
              minimap: {enabled: false},
            }}
            overrideServices={
              {
                // onDidChangeCursorPosition: () => console.log('overrideServices |onDidChangeCursorPosition ---->'),
              }
            }
          />
        </StyledChartComputedFieldEditor>
      </Col>
      {/*<Col span={3}>*/}
      {/*  <ListSelector*/}
      {/*    type="left"*/}
      {/*    bordered*/}
      {/*    dataSource={getFunctionList()}*/}
      {/*    renderItem={(item) => (*/}
      {/*      <List.Item*/}
      {/*        style={{cursor: "pointer"}}*/}
      {/*        onClick={() => handleFieldFunctionSelected(item.value)}*/}
      {/*      >*/}
      {/*        {item.label}*/}
      {/*      </List.Item>*/}
      {/*    )}*/}
      {/*  />*/}
      {/*</Col>*/}
      {/*<p>{renderFunctionDescriptionInfo()}</p>*/}
    </Row>
  );
})

export const ComputedEditor = memo(component);

const StyledChartComputedFieldEditor = styled.div`
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 200px;
  border: 1px solid ${p=>p.theme.colorBorder};
  margin-bottom: 20px
`;

const ListSelector = styled(List)`
  height:202px;
  overflow: hidden;
  ${props => props?.type === 'right' && `
    border-bottom-right-radius: 0;
    border-top-right-radius: 0;
    border-right: none;
  `}
  ${props => props?.type === 'left' && `
    border-bottom-left-radius: 0;
    border-top-left-radius: 0;
    border-left: none;
  `}
  ${props => props?.type === 'center' && `
    border-bottom-right-radius: 0;
    border-top-right-radius: 0;
    border-bottom-left-radius: 0;
    border-top-left-radius: 0;
    border-right: none;
  `}
  &:hover {
    overflow-y: auto;  /* 鼠标悬停时显示滚动条 */
  }
`
const Toolbar = styled.div`
  height: 23px;
  width: 100%;
  padding:3px 0;
`;
const CustomIcon = styled.span`
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: rgba(0, 0, 0, 0.78);
  font-style: normal;
  line-height: 0;
  text-align: center;
  text-transform: none;
  vertical-align: 0.15em;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
  border: 2px solid rgba(0, 0, 0, 0.78);
  font-size: 16px;
  height:12px;
  width:14px;
  font-weight: bold;
  padding-bottom: 2px;
`