import React, { useState, useCallback, useRef, useEffect, useContext, useMemo } from 'react';
import { Input, Form, Typography, Button, Select, Row, Col, Popover, Checkbox, Tooltip, Table, Space } from 'antd';
import { DeleteOutlined, CloseOutlined, CheckOutlined, PlusOutlined, QuestionCircleOutlined, DownOutlined, UpOutlined } from '@ant-design/icons';
import { DndProvider, useDrag, useDrop } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import { useClickAway } from 'ahooks';
import { useContextMenu, Menu as RcMenu, Item as RcItem } from "react-contexify";

import DebounceInput from './DebounceInput';
import { addEventListenerForSidebar, removeEventListenerForSidebar } from './Help';
import { showMessage, highlightSearchContentByTerms, inputWidth } from '../../../../util';
import { EditModelContext } from './ContextManage';
import { ValidateTip } from './ImportActionHeader';
import { DragableBodyRow, EditableCell } from './ImportActionIndex';

const { Option } = Select;

const type = 'DragableProcessBodyRow';
const MENU_ID = 'model-process-menu';

const InputDebounce = DebounceInput(300)(Input);

const ImportActionProcess = (props) => {
  const { modelerData, onChange, editable, terms, constraint, template } = props;

  const [data, setData] = useState([]);
  const [ filterData, setFilterData ] = useState([]);

  const [form] = Form.useForm();
  const [editingKey, setEditingKey] = useState(null);
  const [ keywordCondition, setKeywordCondition ] = useState({ keyword: '', needFilter: true });
  const { keyword, needFilter } = keywordCondition;

  const [insertIndex, setInsertIndex] = useState(0);
  const [ currentItem, setCurrentItem ] = useState(null);
  const [isCollapse, setCollapse] = useState(true);

  const { processIsEditingFunction } = useContext(EditModelContext);

  const dataRef = useRef();

  const tableRef = useRef(null);
  const termsRef = useRef(null);

  const { show } = useContextMenu({
    id: MENU_ID,
  });

  useClickAway(() => {
    save();
  }, tableRef);

  useEffect(() => {
    processIsEditingFunction && processIsEditingFunction(editingKey);
    //eslint-disable-next-line react-hooks/exhaustive-deps    
  }, [ editingKey ])
  
  //规则改变的时候 数据表为可编辑状态
  useEffect(() => {
    setEditingKey(null);
  }, [constraint, template, modelerData])

  useEffect(() => {
    termsRef.current = terms;

    setData(modelerData.processingList||[]);
    dataRef.current = (modelerData.processingList||[]);

    setFilterData(
      (modelerData.processingList||[]).filter(item => 
        !keyword || (item.sequenceNumber||'').indexOf(keyword)!==-1 || (item.name||'').indexOf(keyword)!==-1 || (item.remark||'').indexOf(keyword)!==-1
      ));
  }, [modelerData, terms])

  useEffect(() => {
    if (needFilter) {
      setFilterData(
        (modelerData.processingList||[]).filter(item => 
          !keyword || (item.sequenceNumber||'').indexOf(keyword)!==-1 || (item.name||'').indexOf(keyword)!==-1 || (item.remark||'').indexOf(keyword)!==-1
        ));
    }
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [keywordCondition])

  const menuData = useMemo(() => {
    return [
      { title: '在上方插入行', key: 'up' },
      { title: '在下方插入行', key: 'down' },
      { title: '删除', key: 'delete' },
    ]
  }, [])
  
  const isEditing = (record) => record.sequenceNumber === editingKey;

  const onAddClick = (event) => {
    event.stopPropagation(); 

    save().then(result => {
      if (result) {
        setKeywordCondition({ keyword: '', needFilter: false });
        const newData = [...dataRef.current??[], {sequenceNumber: ''}];

        setFilterData(newData);    
        setInsertIndex(newData.length-1);
        edit(newData[newData.length-1], false);   
      }
    })
  }

  const onInsertToFrontClick = (record) => {
    save().then(result => {
      if (result) {
        setKeywordCondition({ keyword: '', needFilter: false });
        let newData = [...dataRef.current??[]];

        const index = newData.findIndex((item) => record.sequenceNumber === item.sequenceNumber);

        if (index === -1) {

          if (insertIndex === 0) {
            newData = [{sequenceNumber: ''}, ...newData];
  
            edit(newData[0], false);
          } else {
            newData.splice(insertIndex, 0, {sequenceNumber: ''});
            edit(newData[insertIndex], false);
          }

        } else if (index === 0) {
          newData = [{sequenceNumber: ''}, ...newData];

          setInsertIndex(0);
          edit(newData[0], false);
        } else {
          newData.splice(index, 0, {sequenceNumber: ''});
          setInsertIndex(index);
          edit(newData[index], false);
        }

        setFilterData(newData);
      }
    })
  }

  const onInsertToBackClick = (record) => {
    save().then(result => {
      if (result) {
        setKeywordCondition({ keyword: '', needFilter: false });
        const newData = [...dataRef.current];
        const index = newData.findIndex((item) => record.sequenceNumber === item.sequenceNumber);

        if (index === -1) {
          newData.splice(insertIndex+1, 0, {sequenceNumber: ''});
          setFilterData(newData);
          
          setInsertIndex(insertIndex+1);
          edit(newData[insertIndex+1], false);
        } else {
          newData.splice(index+1, 0, {sequenceNumber: ''});
          setFilterData(newData);
          
          setInsertIndex(index+1);
          edit(newData[index+1], false);
        }
      }
    })
  }

  const editLogic = (record) => {
    form.resetFields();
    form.setFieldsValue(record);
    setEditingKey(record?.sequenceNumber);
  }

  const edit = (record, needSave = true) => {

    if (needSave) {
      save().then(result => {
        if (result) {
          editLogic(record);
        }
      })
    } else {
      editLogic(record);
    }
  };

  const removeLogic = (record) => {
    const newData = [...dataRef.current];
    const index = newData.findIndex((item) => record.sequenceNumber === item.sequenceNumber);
  
    if (index !== -1) {
      newData.splice(index, 1);
    }

    onChange && onChange(newData);
  }

  const onRemoveClick = (record) => {

    if (record.sequenceNumber === '') {
      const newData = [...dataRef.current];
      onChange && onChange(newData);
    } else {
      if (record.sequenceNumber !== editingKey) {
        save().then(result => {
          if (result) {
            removeLogic(record);
          }
        })
      } else {
        removeLogic(record);
      }
    }

    save().then(result => {
      if (result) {
        const newData = [...dataRef.current];
        const index = newData.findIndex((item) => record.sequenceNumber === item.sequenceNumber);
    
        if (index !== -1) {
          newData.splice(index, 1);
        }
    
        onChange && onChange(newData);
      }
    })
  }

  const save = async() => {
    try {
      if (editingKey!==null) {
        const row = await form.validateFields();

        // console.log('row', row);  
        
        const newData = [...data];
        const index = newData.findIndex((item) => editingKey === item.sequenceNumber);
    
        let _index;
        if (index === -1) {
          _index = (data||[]).findIndex(item => item.sequenceNumber === row.sequenceNumber);
        } else {
          const newDataExcludeSelf = [...data];
          newDataExcludeSelf.splice(index, 1);  
          _index = (newDataExcludeSelf||[]).findIndex(item => item.sequenceNumber === row.sequenceNumber);
        }

        if (_index !== -1) {
          form.setFields([{ name: 'sequenceNumber', errors: ['加工步骤不能重复'] }]);
          return;
        }

        if (index === -1) {

          newData.splice(insertIndex, 0, row);

        } else {
          newData.splice(index, 1, row);
        }

        dataRef.current = newData;
    
        onChange && onChange(newData, true);

        setEditingKey(null);
      }

      return true;
      
    } catch (errInfo) {
      console.log('Validate Failed:', errInfo);
      return false;
    }
  };

  const onValuesChange = (changedValues, allValues) => {
    // console.log('changed values', changedValues);
    // console.log('all values', allValues);
  };

  const columns = [
    {
      title: '加载步骤',
      dataIndex: 'sequenceNumber',
      width: 200,
      editable: true,
      ellipsis: true,
      require: true,
      render: (_, record, __) => {
        return (
          <Tooltip title={record.sequenceNumber}>
          <span >{highlightSearchContentByTerms(record.sequenceNumber, termsRef.current)}</span>
          </Tooltip>
        )
      }
    },
    {
      title: '加载表名',
      dataIndex: 'name',
      editable: true,
      ellipsis: true,
      require: true,
      inputType: 'textarea',
      render: (_, record, __) => {
        return (
          <Tooltip title={record.name}>
          <span >{highlightSearchContentByTerms(record.name, termsRef.current)}</span>
          </Tooltip>
        )
      }
    },
    {
      title: '步骤说明',
      dataIndex: 'remark',
      editable: true,
      ellipsis: true,
      require: true,
      inputType: 'textarea',
      render: (_, record, __) => {
        return (
          <Tooltip title={record.remark}>
          <span >{highlightSearchContentByTerms(record.remark, termsRef.current)}</span>
          </Tooltip>
        )
      }
    },
  ];

  const mergedColumns = () => {
    if (editable) {
      return columns.map((col) => {
        if (!col.editable) {
          return col;
        }
    
        return {
          ...col,
          onCell: (record) => ({
            record,
            dataIndex: col.dataIndex,
            inputType: col.inputType??'text',
            colTitle: col.title,
            require: col.require,
            editing: isEditing(record),
          }),
        };
      });
    }

    return columns;
  }

  const moveRow = useCallback(
    (dragIndex, hoverIndex) => {

      const dragRow = dataRef.current[dragIndex];
      const newData = update(dataRef.current, {
        $splice: [
          [dragIndex, 1],
          [hoverIndex, 0, dragRow],
        ],
      })
      onChange && onChange(newData);
    },
    //eslint-disable-next-line react-hooks/exhaustive-deps
    [dataRef.current, onChange],
  );

  const onSearchInputChange = (value) => {
    setEditingKey(null);
    setKeywordCondition({ keyword: value||'', needFilter: true });
  }

  const displayMenu = (e) => {
    show(e);
  }

  const handleItemClick = ({ event, props, data, triggerEvent }) => {
    const key = event.currentTarget.id;

    if (key === 'up') {
      onInsertToFrontClick(currentItem);
    } else if (key === 'down') {
      onInsertToBackClick(currentItem);
    } else if (key === 'delete') {
      onRemoveClick(currentItem);
    }
  }

  return (
    <div className='model-import-action-process' id='model-import-action-process'>
      <div className='d-flex mb-3' style={{ justifyContent: 'space-between' }}>
        <Space>
          <h3 style={{ marginBottom: 0 }}>加工步骤</h3>
          { 
            editable && <Popover content='点击行进行编辑,表格可以通过拖拽来排序'>
              <QuestionCircleOutlined className='pointer' /> 
            </Popover> 
          }
          {
            isCollapse ? <Button type='primary' size='small' onClick={() => {
              setCollapse(!isCollapse)
            }}>展开<DownOutlined /></Button> : <Button type='primary' size='small' onClick={() => {
              setCollapse(!isCollapse)
            }}>收起<UpOutlined /></Button>
          }
        </Space>
        <Space>
          { 
            editable && <Tooltip>
              <Button onClick={onAddClick} >新建</Button>
            </Tooltip>
          }
          <div className='d-flex' style={{ alignItems: 'center' }}>
            <InputDebounce 
              placeholder="请输入关键字" 
              allowClear 
              value={keyword}
              onChange={onSearchInputChange} 
              style={{ width: inputWidth }}
            />
          </div>
        </Space>
      </div>
      {
        !isCollapse && <div className='mb-3' id="containerId" ref={tableRef}>
          <DndProvider backend={HTML5Backend} >
            <Form form={form} component={false} onValuesChange={onValuesChange}>
              <Table
                components={{
                  body: {
                    cell: EditableCell,
                    //编辑或者搜索状态下不允许拖动
                    row: (editable&&editingKey===null&&!keyword)?DragableBodyRow:null,
                  },
                }}
                onRow={(record, index) => {
                  let rowParams = {
                    index,
                  };

                  if (editable) {
                    rowParams = {...rowParams, onContextMenu: event => {
                        setCurrentItem(record);
                        displayMenu(event);
                      }
                    };

                    if (!isEditing(record)) {
                      rowParams = {...rowParams, onClick: (event) => {
                          event.stopPropagation();
                          edit(record);
                        }
                      }

                      if (keyword.length===0) {
                        rowParams = {...rowParams, moveRow};
                      }
                    }
                  }

                  return rowParams;
                }}
                dataSource={filterData||[]}
                columns={mergedColumns()}
                size='small'
                rowKey='name'
                rowClassName="editable-row"
                pagination={false}
                sticky
              />
            </Form>
          </DndProvider>
        </div>
      }
      <RcMenu id={MENU_ID} >
      {
        (menuData??[]).map(item => (
          <RcItem key={item.key} id={item.key} onClick={handleItemClick}>
            {item.title}
          </RcItem>
        ))
      }
      </RcMenu>
    </div>
  );
}

export default ImportActionProcess;