import React, { useState, useCallback, useRef, useEffect, useContext, useMemo } from 'react';
import { Input, Form, Typography, Button, Select, Row, Col, Popover, Checkbox, Tooltip, Table, Pagination, Space } from 'antd';
import { CheckOutlined, PlusOutlined, QuestionCircleOutlined, DeleteOutlined } 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 ResizeObserver from 'rc-resize-observer';
import { Resizable } from 'react-resizable';

import { generateUUID, highlightSearchContentByTerms, showMessage, inputWidth, paginate } from '../../../../util';
import { dispatch, dispatchLatest } from '../../../../model'; 
import { addEventListenerForSidebar, removeEventListenerForSidebar } from './Help';
import { AppContext } from '../../../../App';
import DebounceInput from './DebounceInput';
import Suggest from './suggest';
import { AttentionSvg, UnAttentionSvg } from './ModelSvg';
import { EditModelContext } from './ContextManage';
import { ValidateTip } from './ImportActionHeader';

import './ImportActionTable.less';
import 'react-contexify/dist/ReactContexify.css';

const { Option } = Select;

const type = `DragableTableBodyRow${generateUUID()}`;
const perSuggestCount = 5;
const supportMaxAttributeCountPerPage = 100;
const MENU_ID = 'model-attribute-menu';

export const InputDebounce = DebounceInput(300)(Input);

const ResizeableHeaderCell = props => {
  const { onResize, width, onClick, ...restProps } = props;

  if (!width) {
    return <th {...restProps} />;
  }

  return (
    <Resizable
      width={width}
      height={0}
      handle={
        <span
          className="react-resizable-handle"
          onClick={(e) => {
            e.stopPropagation();
          }}
        />
      }
      onResize={onResize}
      draggableOpts={{ enableUserSelectHack: false }}
    >
      <th
        onClick={onClick}
        {...restProps}
      />
    </Resizable>
  );
};

export const DatatypeInput = ({ value = {}, datatypes = [], onChange }) => {

  const onNameChange = (value) => {

    let currentDatatype = {}; 
    (datatypes||[]).forEach((datatype, index) => {
      if (value === datatype.name) {
        currentDatatype = datatype;
      }
    })

    triggerChange({ 
      name: value,
      cnName: currentDatatype.cnName,
      parameterNames: currentDatatype.parameterNames,
      parameterCnNames: currentDatatype.parameterCnNames,
      parameterValues: currentDatatype.parameterValues
    });
  }

  const onParameterValuesChange = (e, index) => {

    const parameterValue = e.target.value;
    const reg = /^-?\d*(\.\d*)?$/;
    if ((!isNaN(parameterValue) && reg.test(parameterValue)) || parameterValue === '') {
      const newParameterValues = [...(value.parameterValues||[])];

      //默认为0
      newParameterValues[index] = parameterValue;
      triggerChange({ parameterValues: newParameterValues });
    }
  }

  const triggerChange = (changedValue) => {
    onChange && onChange({
      ...value,
      ...changedValue,
    });
  };

  //value有可能为空
  value = value ? value: {};

  return (
    <div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{ flex: 1 }}>
        <Select 
          onChange={onNameChange} 
          value={value.name || ''} 
          placeholder='请选择类型名称'
          style={{ width: '100%' }}
        >
        {
          (datatypes||[]) && datatypes.map((_datatype, index) => {
            return (
              <Option key={_datatype.name||''}>{_datatype.name||''}</Option>
            );
          })
        }
        </Select>
      </div>
      {
        (value.parameterCnNames||[]).map((parameterCnName, index) => {
          //使用InputNumber:当value改变时 InputNumber显示值没改变 但实际值有改变 是ant design的bug 这里使用只能输入数字的Input
          return (
            <div key={index} className='ml-2' style={{ flex: 1 }}>
              <Input        
                onChange={(e) => {
                  onParameterValuesChange(e, index);
                }}  
                value={value.parameterValues[index]} 
                style={{ width: '100%' }}
                placeholder={parameterCnName}
              />
            </div>
          );
        })
      }
    </div>
  )
}

export const EditableCell = ({
  editing,
  dataIndex,
  colTitle,
  inputType,
  record,
  index,
  datatypes,
  require,
  onPressEnter,
  children,
  ...restProps
}) => {
  let editingComponent = null;
  if (editing) {
    let inputNode = <InputDebounce onPressEnter={() => { onPressEnter?.() }} />;

    if (inputType === 'check') {
      inputNode = <Checkbox />;
    } else if (inputType === 'textarea') {
      inputNode = <Input.TextArea rows={3} />;
    } else if (inputType === 'datatype') {
      inputNode = <DatatypeInput datatypes={datatypes} />;
    }

    editingComponent = (
      <Form.Item
        name={dataIndex}
        style={{
          margin: 0,
        }}
        valuePropName={(inputType==='check')? 'checked': 'value'}
        rules={[
          {
            required: (require===null)?false:require,
            message: `请输入${colTitle}!`,
          },
        ]}
      >
      { inputNode }
      </Form.Item>
    );
  }

  return (
    <td {...restProps}>
      {editing ? (
        editingComponent
      ) : (
        children
      )}
    </td>
  );
};

export const DragableBodyRow = ({ index, moveRow, className, style, ...restProps }) => {

  const ref = useRef();
  const [{ isOver, dropClassName }, drop] = useDrop(
    () => ({
      accept: type,
      collect: monitor => {

        const { index: dragIndex } = monitor.getItem() || {};
        if (dragIndex === index) {
          return {};
        }
        return {
          isOver: monitor.isOver(),
          dropClassName: dragIndex < index ? ' drop-over-downward' : ' drop-over-upward',
        };
      },
      drop: item => {
        if (moveRow) {
          moveRow(item.index, index);
        }
      },
    }),
    [index, moveRow],
  );
  const [, drag] = useDrag(
    () => ({
      type,
      item: () => {
        addEventListenerForSidebar("containerId");
        return { index }; 
      },
      end: (_, __) => {
        removeEventListenerForSidebar();
      }, 
      collect: monitor => ({
        isDragging: monitor.isDragging(),
      }),
    }),
    [index, moveRow],
  );
  drop(drag(ref));

  return (
    <tr
      ref={ref}
      className={`${className}${isOver ? dropClassName : ''}`}
      style={{ cursor: 'move', ...style }}
      {...restProps}
    />
  );
};

export const ImportActionTable = (props) => {
  const { modelerData, onChange, editable, supportedDatatypes, constraint, template, validateReports, type = 'model', terms, action, originAction } = props;
  const [ data, setData ] = useState([]);

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

  const [ filterPageCondition, setFilterPageCondition ] = useState({ pageNum: 1, pageSize: supportMaxAttributeCountPerPage, filterData: [] });
  const [ filterPageData, setFilterPageData ] = useState([]);
  const { pageNum, pageSize, filterData } = filterPageCondition;
  const [ insertIndex, setInsertIndex ] = useState(0);
  const [ currentItem, setCurrentItem ] = useState(null);
  const [suggestParams, setSuggestParams] = useState({
    visible: false,
    name: undefined,
    cnName: undefined,
    triggerType: undefined,
    hiveDeployed: false,
  })

  const { attrIsEditingFunction } = useContext(EditModelContext);

  const moveRowRef = useRef({ data, pageNum, pageSize });
  const tableRef = useRef(null);
  const termsRef = useRef(null);
  const autoTranslateRef = useRef(false);

  const app = useContext(AppContext)

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

  const cols = [
    {
      title: '序号',
      dataIndex: 'key',
      editable: false,
      width: 44,
      fixed: 'left',
      render: (text, record, index) => {
        return (index+1).toString();
      }
    },
    {
      title: '中文名称',
      width: 200,
      dataIndex: 'cnName',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      require: true,
      fixed: 'left',
      render: (text, record, __) => {
        return (
          <React.Fragment>
            <ValidateTip type='DataModelAttribute' propertyName='cnName' validateReports={validateReports} iid={record.iid} />
            <Tooltip title={text||''}>
            <span>{highlightSearchContentByTerms(text, termsRef.current)}</span>
            </Tooltip>
          </React.Fragment>
        )
      }
    },
    {
      title: '英文名称',
      width: 200,
      dataIndex: 'name',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      require: true,
      render: (text, record, index) => {
        return (
          <React.Fragment>
            <ValidateTip type='DataModelAttribute' propertyName='name' validateReports={validateReports} iid={record.iid} />
            <Tooltip title={text||''}>
            <span>{highlightSearchContentByTerms(text, termsRef.current)}</span>
            </Tooltip>
          </React.Fragment>
        )
      }
    },
    {
      title: '类型',
      width: (editingKey!=='')?250:150,
      dataIndex: 'datatype',
      editable: true,
      ellipsis: true,
      require: true,
      render: (_, record, __) => {
        if (record?.datatype) {

          if ((record?.datatype?.name==='Char'||record?.datatype?.name==='Varchar') && record?.datatype?.parameterValues?.length>0) {

            return `${record?.datatype?.name||''}(${(record?.datatype?.parameterValues[0]?record.datatype.parameterValues[0]:0)})`;
          
          } else if ((record?.datatype?.name==='Decimal'||record?.datatype?.name==='Numeric') && record?.datatype?.parameterValues?.length>1) {
            return `${record?.datatype?.name||''}(${(record?.datatype?.parameterValues[0]?record.datatype.parameterValues[0]:0)},${(record?.datatype?.parameterValues[1]?record.datatype.parameterValues[1]:0)})`;
          }

          return record.datatype.name||'';
        }

        return '';
      }
    },
    {
      title: 'Not Null',
      width: 70,
      dataIndex: 'notNull',
      editable: true,
      ellipsis: true,
      render: (notNull, record, index) => {
        if (!notNull) {
          return '-'; 
        } else if (notNull) {
          return (
            <CheckOutlined />
          )
        }

        return '';
      }
    },
    {
      title: '主键',
      width: 44,
      dataIndex: 'partOfPrimaryKeyLogically',
      editable: (type==='model'?true:false),
      render: (partOfPrimaryKeyLogically, record, index) => {
        if (!partOfPrimaryKeyLogically) {
          return '-'; 
        } else if (partOfPrimaryKeyLogically === true) {
          return (
            <CheckOutlined />
          )
        }

        return '';
      }
    },
    {
      title: '外键',
      width: 44,
      dataIndex: 'foreignKey',
      editable: (type==='model'?true:false),
      render: (foreignKey, record, index) => {
        if (!foreignKey) {
          return '-'; 
        } else if (foreignKey === true) {
          return (
            <CheckOutlined />
          )
        }

        return '';
      }
    },
    {
      title: '重点关注',
      width: 80,
      dataIndex: 'needAttention',
      editable: false,
      render: (needAttention, record, index) => {
        if (!needAttention) {
          return '-'; 
        } else if (needAttention === true) {
          return (
            <CheckOutlined />
          )
        }

        return '';
      }
    },
    {
      title: '业务含义',
      dataIndex: 'remark',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      // require: true,
      width: 200,
      render: (text, record, __) => {
        return (
          <React.Fragment>
            <ValidateTip type='DataModelAttribute' propertyName='remark' validateReports={validateReports} iid={record.iid} />
            <Tooltip title={text||''}>
            <span>{highlightSearchContentByTerms(text, termsRef.current)}</span>
            </Tooltip>
          </React.Fragment>
        )
      }
    },
    {
      title: '默认值',
      dataIndex: 'defaultValue',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      width: 100,
      render: (text, _, __) => {
        return (
          <Tooltip title={text||''}>
            <Typography.Text ellipsis={true}>
            {highlightSearchContentByTerms(text, termsRef.current)}
            </Typography.Text>
          </Tooltip>
        )
      }
    },
    {
      title: '计算规则',
      dataIndex: 'definition',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      width: 200,
      render: (text, record, __) => {
        return (
          <React.Fragment>
            <ValidateTip type='DataModelAttribute' propertyName='definition' validateReports={validateReports} iid={record.iid} />
            <Tooltip title={text||''}>
            <span>{highlightSearchContentByTerms(text, termsRef.current)}</span>
            </Tooltip>
          </React.Fragment>
        )
      }
    },
    {
      title: '值域',
      dataIndex: 'valueRange',
      editable: true,
      hiveEditable: true,
      ellipsis: true,
      width: 100,
      render: (text, record, __) => {
        return (
          <React.Fragment>
            <ValidateTip type='DataModelAttribute' propertyName='valueRange' validateReports={validateReports} iid={record.iid} />
            <Tooltip title={text||''}>
            <span>{highlightSearchContentByTerms(text, termsRef.current)}</span>
            </Tooltip>
          </React.Fragment>
        )
      }
    },
  ];

  const [ columns, setColumns ] = useState(cols);

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

  useEffect(() => {
    attrIsEditingFunction && attrIsEditingFunction(editingKey!=='');
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [ editingKey ])

  //规则改变的时候 数据表为可编辑状态
  useEffect(() => {
    setEditingKey('');
  }, [constraint, template, modelerData])

  useEffect(() => {
    termsRef.current = terms;
    setData(modelerData?.easyDataModelerDataModelAttributes||[]);

    moveRowRef.current.data = (modelerData?.easyDataModelerDataModelAttributes||[]);

    let _filterData = (modelerData?.easyDataModelerDataModelAttributes||[]).filter(item => (item?.name||'').indexOf(keyword)!==-1 || (item.cnName).indexOf(keyword)!==-1);

    setFilterPageCondition({...filterPageCondition, filterData: _filterData});

    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [modelerData, terms])

  useEffect(() => {
    if (needFilter) {
      let _filterData = (modelerData.easyDataModelerDataModelAttributes||[]).filter(item => (item?.name||'').indexOf(keyword)!==-1 || (item.cnName).indexOf(keyword)!==-1);

      setFilterPageCondition({...filterPageCondition, ...{filterData: _filterData, pageNum: 1} });
    }
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [keywordCondition])

  useEffect(() => {
    moveRowRef.current.pageNum = pageNum;
    moveRowRef.current.pageSize = pageSize;

    if (filterData.length > supportMaxAttributeCountPerPage) {

      let _filterPageData = paginate(filterData, pageNum, pageSize);

      if ((_filterPageData||[]).length===0 && pageNum > 1) {
        setFilterPageCondition({...filterPageCondition, pageNum: (pageNum-1)});
        moveRowRef.current.pageNum = pageNum - 1;
      } else {
        setFilterPageData(_filterPageData);
      }
    } else {
      setFilterPageData(filterData);
    }
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [filterPageCondition])

  useEffect(() => {
    mergedColumns();
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [validateReports, editable, editingKey])

  const menuData = useMemo(() => {
    let newMenuData = []
    if (action === 'flow') {
      if (currentItem?.isPossibleNewRecommendedDefinition?.possible) {
        newMenuData.push({
          title: '加入标准',
          key: 'addToStandard',
        })
      }

      if (currentItem?.isPossibleNewTerm?.possible) {
        newMenuData.push({
          title: '加入词汇',
          key: 'addToWord',
        })
      }
    } 

    if (editable) {
      newMenuData = [...newMenuData, ...[
        { title: '在上方插入行', key: 'up' },
        { title: '在下方插入行', key: 'down' },
      ]]

      if (modelerData?.dbType!=='Hive'||!currentItem?.deployed) {
        newMenuData.push({ title: '删除', key: 'delete' })
      }
      if (originAction !== 'flow') {
        newMenuData.push({
          title: currentItem?.needAttention ? '取消送审关注': '送审关注',
          key: 'attention'
        })
      }
    }

    return newMenuData;
  }, [currentItem, action, originAction, editable, modelerData])

  const isEditing = (record) => record?.iid === editingKey;

  const onAddClick = (event) => {

    event.stopPropagation();  

    save().then(result => {
      if (result) {

        setKeywordCondition({ keyword: '', needFilter: false });

        const iid = generateUUID();
        const newData = [...moveRowRef.current.data, {iid}];
        
        if (newData.length > supportMaxAttributeCountPerPage) {
          
          const totalNum = parseInt(newData.length/supportMaxAttributeCountPerPage) + ((newData.length%supportMaxAttributeCountPerPage===0)?0:1);
          
          setFilterPageCondition({...filterPageCondition, ...{ filterData: newData, pageNum: totalNum }});
        } else {
          setFilterPageCondition({...filterPageCondition, ...{ filterData: newData}});
        }
    
        setInsertIndex(newData.length-1);
    
        edit(newData[newData.length-1], false);
        setTimeout(() => {
          document.getElementById(`field-${iid}`)?.scrollIntoView();
        }, 200)
      }
    })
  }

  const onInsertToFrontClick = (record) => {
    save().then(result => {
      if (result) {
        setKeywordCondition({ keyword: '', needFilter: false });

        let newData = [...moveRowRef.current.data];
        const index = newData.findIndex((item) => record.iid === item.iid);

        const iid = generateUUID();

        if (index === 0) {
          newData = [{iid}, ...newData];
          setInsertIndex(0);
          edit(newData[0], false);
        } else {
          newData.splice(index, 0, {iid});
          setInsertIndex(index);
          edit(newData[index], false);
        }

        const _pageNum = parseInt((index+1)/supportMaxAttributeCountPerPage) + (((index+1)%supportMaxAttributeCountPerPage===0)?0:1);

        setFilterPageCondition({...filterPageCondition, ...{ filterData: newData, pageNum: _pageNum}});

        setTimeout(() => {
          document.getElementById(`field-${iid}`)?.scrollIntoView();
        }, 200)
      }
    })
  }

  const onInsertToBackClick = (record) => {
    save().then(result => {
      if (result) {
        setKeywordCondition({ keyword: '', needFilter: false });

        const newData = [...moveRowRef.current.data];
        const index = newData.findIndex((item) => record.iid === item.iid);

        const iid = generateUUID();
        newData.splice(index+1, 0, {iid});

        const _pageNum = parseInt((index+2)/supportMaxAttributeCountPerPage) + (((index+2)%supportMaxAttributeCountPerPage===0)?0:1);

        setFilterPageCondition({...filterPageCondition, ...{ filterData: newData, pageNum: _pageNum}});
        
        setInsertIndex(index+1);
        edit(newData[index+1], false);

        setTimeout(() => {
          document.getElementById(`field-${iid}`)?.scrollIntoView();
        }, 200)
      }
    })
  }

  const editLogic = (record) => {
    form.resetFields();
    form.setFieldsValue(record);

    setEditingKey(record?.iid);
    autoTranslateRef.current = ((record?.name||'')==='');

    if ((record?.cnName||'')!=='') {
      onValuesChange({ cnName: record?.cnName }, record, 1, record?.iid);
    } else if ((record?.name||'')!=='') {
      onValuesChange({ name: record?.name }, record, 1, record?.iid);
    }
  }

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

  const removeLogic = (record) => {
    const newData = [...moveRowRef.current.data];
    const index = newData.findIndex((item) => record.iid === item.iid);

    if (index !== -1) {
      newData.splice(index, 1);
    }

    onChange && onChange(newData);
  }

  const onRemoveClick = (record) => {
    if (record.iid !== editingKey) {
      save().then(result => {
        if (result) {
          removeLogic(record);
        }
      })
    } else {
      removeLogic(record);
    }
  }

  const onAttentionClick = (record) => {
    if (record.needAttention === null) {
      record.needAttention = true;
    } else {
      record.needAttention = !record.needAttention;
    }

    const newData = [...moveRowRef.current.data];

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

    if (index !== -1) {
      newData.splice(index, 1, {...record});

      setData(newData);
      moveRowRef.current.data = newData;
      onChange && onChange(newData, false);

      if (!record.needAttention) {
        preSaveDataModel(record);
      }
    }
  }

  const onAddToStandardClick = (record) => {
    app.setGlobalState?.({
      message: 'data-govern-show-standard-create',
      data: {
        column: {...record, ...{ modelName: modelerData?.name, modelCnName: modelerData?.cnName }},
        type: record?.isPossibleNewRecommendedDefinition?.type
      }
    });
  }

  const onAddToWordClick = (record) => {
    app.setGlobalState?.({
      message: 'data-govern-show-standard-create',
      data: {
        column: record,
        type: record?.isPossibleNewTerm?.type
      }
    })
  }

  const preSaveDataModel = (attribute) => {
    dispatch({
      type: 'datamodel.preSaveDataModel',
      payload: { 
        data: attribute
      },
      callback: remoteData => {
        const newData = [...moveRowRef.current.data];
        const index = (newData||[]).findIndex((item) => attribute.iid === item.iid);
    
        if (index !== -1) {
          newData.splice(index, 1, remoteData);
          moveRowRef.current.data = newData;
          onChange && onChange(newData, false);
        }
      },
    })
  }

  const save = async() => {

    try {

      if (editingKey!=='') {

        const row = await form.validateFields();

        if (row.datatype) {
          if ((row.datatype.name||'')==='') {
            form.setFields([{ name: 'datatype', errors: ['必须选择类型'] }]);
            return;
          }
  
          (row.datatype.parameterNames||[]).forEach((parameterName, index) => {
            if (!row.datatype.parameterValues[index] || row.datatype.parameterValues[index]==='') {
              row.datatype.parameterValues[index] = 0;
            }
          })
        }

        const newData = [...data];
    
        const index = newData.findIndex((item) => editingKey === item.iid);
    
        if (row.name) {
          //判断字段名称是否唯一
          let _index;
          if (index === -1) {
            _index = (data||[]).findIndex(item => item.name === row.name);
          } else {
            const newDataExcludeSelf = [...data];
            newDataExcludeSelf.splice(index, 1);  
            _index = (newDataExcludeSelf||[]).findIndex(item => item.name === row.name);
          }

          if (_index !== -1) {
            form.setFields([{ name: 'name', errors: ['字段名称不能重复'] }]);
            return;
          }
        }

        let attribute = {};
        if (index === -1) {

          attribute = {...row, iid: editingKey, modelingTemplateTag: null};
          newData.splice(insertIndex, 0, attribute);
          
        } else {
          const item = newData[index];

          attribute = { ...item, ...row, modelingTemplateTag: null };
          newData.splice(index, 1, attribute);
        }

        moveRowRef.current.data = newData;

        onChange && onChange(newData, true);

        if (!attribute.needAttention) {
          preSaveDataModel(attribute);
        }

        setEditingKey('');
        setEnglishSuggests([]);
      }

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

  const onValuesChange = (changedValues, allValues, offset = 1, iid = editingKey) => {
    // console.log('changed values', changedValues);
    // console.log('all values', allValues);

    let ownPrimaryKey = false;
    if (modelerData?.easyDataModelerPrimaryKey) {
      ownPrimaryKey = (modelerData.easyDataModelerPrimaryKey.filter(item => item.name===allValues.name).length>0);
    }

    if (changedValues.hasOwnProperty('cnName')) {
      if (autoTranslateRef.current) {
        dispatchLatest({
          type: 'datamodel.translatePhase',
          payload: {
            params: {
              phaseInChinese: changedValues.cnName,
            }
          },
          callback: data => {
            if ((data?.translated||'') !== '') {
              form.setFieldsValue({ name: data?.translated||'' });
            }
          }
        })
      } 
    } else if (changedValues.hasOwnProperty('name')) {
      autoTranslateRef.current(changedValues.name==='');
    } else if(changedValues.hasOwnProperty('notNull') ) {
      if (!changedValues.notNull && ownPrimaryKey) {
        showMessage('info', '主键不允许为空');
      }
    } 
     
    if (ownPrimaryKey) {
      form.setFieldsValue({
        notNull: true
      });
    } 

  };

  const onSuggestChange = (record, hiveDeployed) => {
    const { notNull, partOfPrimaryKeyLogically, foreignKey, ...restRecord } = record;

    if (hiveDeployed) {
      const { name, datatype, notNull, partOfPrimaryKeyLogically, foreignKey, ..._restRecord } = restRecord
      form.setFieldsValue({ 
        ..._restRecord
      });
    } else {
      form.setFieldsValue({ 
        ...restRecord
      });
    }
  };

  const onColumnPressEnter = (title, hiveDeployed) => {
    if (title === '中文名称') {
      setSuggestParams({
        visible: true,
        name: form?.getFieldValue('name'),
        cnName: form?.getFieldValue('cnName'),
        triggerType: 'cnName',
        hiveDeployed,
      })
    } else if (title === '英文名称') {
      setSuggestParams({
        visible: true,
        name: form?.getFieldValue('name'),
        cnName: form?.getFieldValue('cnName'),
        triggerType: 'name',
        hiveDeployed,
      })
    }
  }

  const mergedColumns = () => {
    if (editable) {
      const _columns = cols.map((col) => {
        if (!col.editable) {
          return col;
        }

        let inputType = 'text';
        if (
          col.dataIndex==='notNull'|| 
          col.dataIndex==='partOfDistributionKey' || 
          col.dataIndex==='partOfPrimaryKeyLogically' || 
          col.dataIndex==='needAttention' || 
          col.dataIndex==='foreignKey'
        ) {
          inputType = 'check';  
        } else if (
          col.dataIndex === 'remark' ||
          col.dataIndex === 'definition'
        ) {
          inputType = 'textarea';
        } else if (col.dataIndex === 'datatype') {
          inputType = 'datatype';
        }
    
        return {
          ...col,
          onCell: (record) => ({
            record,
            dataIndex: col.dataIndex,
            inputType,
            colTitle: col.title,
            editing: (!col.hiveEditable&&modelerData?.dbType==='Hive'&&record?.deployed)?false:isEditing(record),
            datatypes: (supportedDatatypes??[]).filter(item => item.supportedDBTypes.indexOf(modelerData?.dbType) !== -1),
            require: col.require,
            onPressEnter: () => {
              onColumnPressEnter(col.title, modelerData?.dbType==='Hive'&&record?.deployed)
            }
          }),
        };
      });

      setColumns(_columns);
    } else {
      setColumns(cols);
    }
  }

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

      const { data, pageNum, pageSize } = moveRowRef.current;

      let realDragIndex = dragIndex;
      let realHoverIndex = hoverIndex;

      if ((data||[]).length>supportMaxAttributeCountPerPage) {
        realDragIndex = (pageNum-1)*pageSize + dragIndex;
        realHoverIndex = (pageNum-1)*pageSize + hoverIndex;
      }

      const dragRow = data[realDragIndex];

      const newData = update(data, {
        $splice: [
          [realDragIndex, 1],
          [realHoverIndex, 0, dragRow],
        ],
      })

      onChange && onChange(newData);
    },
    //eslint-disable-next-line react-hooks/exhaustive-deps
    [moveRowRef.current, onChange],
  );

  const onSearchInputChange = (value) => {
    setEditingKey('');

    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); 
    } else if (key === 'attention') {
      onAttentionClick(currentItem);
    } else if (key === 'addToStandard') {
      onAddToStandardClick(currentItem);
    } else if (key === 'addToWord') {
      onAddToWordClick(currentItem);
    }
  }

  const handleResize = index => (e, { size }) => {
    const nextColumns = [...columns];
    nextColumns[index] = {
      ...nextColumns[index],
      width: size.width,
    };

    setColumns(nextColumns);
  };

  const resizeColumns = () => {
    return (
      columns.map((column, index) => { 
        return {
          ...column,
          onHeaderCell: column => ({
            width: column.width,
            onResize: handleResize(index),
          }),
        };
      })
    );
  }

  return (
    <div className='model-import-action-table' id='model-import-action-table'>
      <div className='d-flex mb-3' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
        <Space>
          <h3 style={{ marginBottom: 0 }}>数据表结构</h3> 
          { 
            editable && <Popover content={<span>
              新增: 点击操作列的加号按钮在当前字段前新增一个字段<br />
              修改: 点击字段表格中的一行任意位置进入该字段编辑页面<br />
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;输入中文名，自动推荐英文名，可选择采用或者手工修改<br />
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;输入中文名，自动推荐可参考引用的数据标准或者数据字典，可选择采用<br />
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;支持拖拽方式调整模型字段顺序<br />
              &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;点击表格外部任意位置退出字段编辑状态<br />
              删除: 点击操作列垃圾桶图标删除该字段<br />
              保存: 页面右下角保存按钮<br />
              中/英文输入框回车键触发推荐浮窗
            </span>}>
              <QuestionCircleOutlined className='pointer' /> 
            </Popover> 
          }
        </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>
      <div className='mb-3' id="containerId" ref={tableRef}>
        <ResizeObserver
          onResize={({ width }) => {
            setTableWidth(width);
          }}
        >
          <DndProvider backend={HTML5Backend} >
            <Form form={form} component={false} onValuesChange={onValuesChange}>
              <Table
                components={{
                  header: {
                    cell: ResizeableHeaderCell,
                  },
                  body: {
                    cell: EditableCell,
                    //编辑或者搜索状态下不允许拖动
                    row: (editable&&editingKey===''&&keyword==='')?DragableBodyRow:null,
                  },
                }}
                rowClassName={(record, index) => {
                  if (type==='model' && !isEditing(record)) {
                    if (record?.partOfPrimaryKeyLogically) {
                      return 'editable-row primary-row';
                    }
                    if (record?.provided || record?.inherited || record?.modelingTemplateTag?.id) {
                      return 'editable-row gray-row';
                    }
                  }
         
                  return 'editable-row';
                }}
                onRow={(record, index) => {
                  let rowParams = {
                    index,
                    id: `field-${record.iid}`,
                  }
                  let shouldRowContextMenu = false
                  if (action==='flow') {
                    if (record?.isPossibleNewRecommendedDefinition?.possible || record?.isPossibleNewTerm?.possible) {
                      shouldRowContextMenu = true
                    }
                  } 

                  if (editable) {
                    shouldRowContextMenu = true
                  }

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

                  if (editable) {
                    if (!isEditing(record)) {
                      rowParams = {...rowParams, onClick: (event) => {
                          event.stopPropagation();
                          if (record.inherited || record.provided) {
                            showMessage('warn', '请到对应的当前表修改');
                          } else {
                            edit(record);
                          }
                        }
                      }

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

                  return rowParams;
                }}
                dataSource={filterPageData||[]}
                columns={resizeColumns()}
                size='small'
                rowKey='iid'
                pagination={false}
                sticky
                scroll={{
                  x: 1500,
                  //解决屏幕尺寸窄时,字段不好横向拖动的问题
                  y: tableWidth>1500?'100%':630,
                }}
              />
            </Form>
          </DndProvider>
        </ResizeObserver>
        {
          (filterData.length > supportMaxAttributeCountPerPage) && <Pagination
            className="text-center mt-3"
            showSizeChanger
            showQuickJumper
            onChange={(_pageNum, _pageSize) => {
              setFilterPageCondition({...filterPageCondition, ...{ pageNum: _pageNum, pageSize: _pageSize || supportMaxAttributeCountPerPage }})
            }}
            onShowSizeChange={(_pageNum, _pageSize) => {
              setFilterPageCondition({...filterPageCondition, ...{ pageNum: _pageNum || 1, pageSize: _pageSize }})
            }}
            current={pageNum}
            pageSize={pageSize}
            defaultCurrent={1}
            total={(filterData||[]).length}
            pageSizeOptions={[50, supportMaxAttributeCountPerPage]}
            showTotal={total => `共 ${(filterData||[]).length} 条`}
          />
        }

        <div onClick={(e) => { e.stopPropagation() }}>
          <Suggest 
            {...suggestParams}
            onCancel={() => {
              setSuggestParams({
                visible: false,
                name: undefined,
                cnName: undefined,
                triggerType: undefined,
                hiveDeployed: false,
              })
            }}
            onOk={onSuggestChange}
          />
        </div>

        <RcMenu id={MENU_ID} >
          {
            (menuData??[]).map(item => (
              <RcItem key={item.key} id={item.key} onClick={handleItemClick}>
                {item.title}
              </RcItem>
            ))
          }
        </RcMenu> 
        
      </div>
    </div>
  );
};
