import React, { useState, useEffect, useRef } from 'react';
import { Form, Button, Space, Tooltip } from 'antd';
import LocalStorage from 'local-storage';
import { useMount, useUnmount } from 'ahooks';

import ImportAction from './ImportAction';
import CatalogModal from './CatalogModal';
import { dispatchLatest } from '../../../../model'; 
import { getQueryParam, showMessage, showNotifaction } from '../../../../util';
import { Action, CatalogId, ModelerId, Hints, ModelerData, PermitCheckOut, Editable, StateId, VersionId, Holder, DDL, ReadOnly } from '../../../../util/constant';
import HistoryAndVersionDrawer from './HistoryAndVersionDrawer';
import { EditModelContext } from './ContextManage';

import './EditModel.less';

const EditModel = (props) => {

  const [ actionData, setActionData ] = useState({ action: '', catalogId: '', modelerId: '', hints: [],  roughModelerData: null, permitCheckOut: false, editable: false, stateId: '', versionId: '', ddl: '', readOnly: false });

  const [ modelerData, setModelerData ] = useState({});
  const [ terms, setTerms ] = useState([]);
  const [ confirmLoading, setConfirmLoading ] = useState(false);
  const [ catalogModalVisible, setCatalogModalVisible ] = useState(false);
  const [ historyAndVersionDrawerVisible, setHistoryAndVersionDrawerVisible ] = useState(false);
  const [ autoTabKey, setAutoTabKey ] = useState(null);

  const actionRef = useRef('');
  const attrIsEditingRef = useRef(false);
  const indexIsEditingRef = useRef(false);

  const { action, catalogId, modelerId, hints, roughModelerData, permitCheckOut, editable, stateId, versionId, holder, ddl, readOnly } = actionData;

  const [form] = Form.useForm();

  useEffect(() => {
    const _action = getQueryParam(Action, props.location.search);
    const _catalogId = getQueryParam(CatalogId, props.location.search);
    const _modelerId = getQueryParam(ModelerId, props.location.search);
    const _hintsStr = getQueryParam(Hints, props.location.search);
    const _modelerDataStr = getQueryParam(ModelerData, props.location.search)
    const _permitCheckOut = getQueryParam(PermitCheckOut, props.location.search);
    const _editable = getQueryParam(Editable, props.location.search);
    const _stateId = getQueryParam(StateId, props.location.search);
    const _versionId = getQueryParam(VersionId, props.location.search);
    const _holder = getQueryParam(Holder, props.location.search);
    const _ddl = getQueryParam(DDL, props.location.search);
    const _readOnly = getQueryParam(ReadOnly, props.location.search);

    let _hints = [];
    if ((_hintsStr||'') !== '') {
      _hints = _hintsStr.split(',');
    }

    let _roughModelerData = null;
    if ((_modelerDataStr||'') !== '') {
      _roughModelerData = JSON.parse(_modelerDataStr);

      judgeAttributeRepeat(_roughModelerData.easyDataModelerDataModelAttributes);
    } 

    setActionData({ action: _action, catalogId: _catalogId, modelerId: _modelerId, hints: _hints, roughModelerData: _roughModelerData, permitCheckOut: (_permitCheckOut==='true'), editable: (_editable==='true'), stateId: _stateId, versionId: _versionId, holder: _holder, ddl: _ddl, readOnly: _readOnly });
    actionRef.current = _action;

    const interval = setInterval(() => {
      heartbeat();
    }, 10*60*1000);

    return () => {
      clearInterval(interval);
    }
    
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  useMount(() => {
    window?.addEventListener('beforeunload', confirmQuit);
  })

  useUnmount(() => {
    window?.removeEventListener('beforeunload', confirmQuit);
  })

  const heartbeat = () => {
    dispatchLatest({
      type: 'datamodel.heartbeat'
    });
  }

  const confirmQuit = (e) => {
    if (actionRef.current==='edit' || actionRef.current==='add') {
      e.returnValue = '';
    }
  }

  const judgeAttributeRepeat = (attrs) => {
    const names = [], nameCountMap = {}, terms = [];

    var repeat = false;
    (attrs||[]).forEach(item => {
      names.push(item.name||'');

      if (nameCountMap[item.name]) {
        nameCountMap[item.name]++;
      } else {
        nameCountMap[item.name] = 1;
      }
    })

    Object.keys(nameCountMap).forEach(key => {
      if (nameCountMap[key] > 1) {
        repeat = true;
        terms.push(key);
      }
    })

    if (repeat) {
      setAutoTabKey('2');
      setTerms(terms);
    }
  }

  const save = (e) => {
    e.stopPropagation();

    if (attrIsEditingRef.current) {
      showMessage("warn", '还有字段正在编辑，需先保存该字段!');
    } else if (indexIsEditingRef.current) {
      showMessage("warn", '还有索引正在编辑，需先保存该索引!');
    } else {
      saveLogic();
    }
  }

  const saveLogic = async (e, cid = '') => {

    setAutoTabKey(null);

    try {
      const row = await form.validateFields();

      const newModelerData = {...modelerData, ...row};

      if (newModelerData.easyDataModelerModelingTemplate==='' || newModelerData.easyDataModelerModelingTemplate==={}) {
        newModelerData.easyDataModelerModelingTemplate = null;
      } 

      if (newModelerData.partition && ( !newModelerData.partition.partitionType || newModelerData.partition.partitionType==={} || (newModelerData.partition.keys||[]).length===0 )) {
        newModelerData.partition = null;
      }

      if (action==='add' && (cid||'')==='' && ((catalogId||'')==='')) {
        setCatalogModalVisible(true);
        return ;
      }

      setConfirmLoading(true);
      dispatchLatest({
        type: 'datamodel.saveDataModel',
        payload: { 
          data: newModelerData
        },
        callback: data => {
          if (action === 'add') {
            dispatchLatest({
              type: 'datamodel.bindCatalogDataModel',
              payload: { 
                params: {
                  easyDataModelCatalogId: ((cid||'')!=='')?cid:catalogId,
                  easyDataModelerDataModelIds: data.id||''
                }
              },
              callback: message => {
                setConfirmLoading(false);
                setTerms([]);

                if ((message||'')!=='' && (message||'')!=='ok') {
                  showNotifaction('提示', message, 5);
                } else {
                  showMessage("success", '新增模型成功');
                }

                setActionData({ ...actionData, ...{ action: 'detail', modelerId: data.id||'', editable: data?.editable||false, stateId: data?.state?.id||'' } });
                actionRef.current = 'detail';

                LocalStorage.set('modelId', data.id||'');
                LocalStorage.set('modelChange', !(LocalStorage.get('modelChange')||false));
              },
              error: () => {
                setConfirmLoading(false);
              }
            })
          } else {
            setConfirmLoading(false);
            setTerms([]);

            showMessage("success", '保存模型成功');

            const _action = getQueryParam(Action, props.location.search);
            
            setActionData({ ...actionData, ...{ action: (_action==='flow')?'flow':'detail', modelerId: data.id||'', stateId: data?.state?.id||'', permitCheckOut: data?.permitCheckOut||false, editable: data?.editable||false } });
            actionRef.current = (_action==='flow')?'flow':'detail';

            LocalStorage.set('modelId', data.id||'');
            LocalStorage.set('modelChange', !(LocalStorage.get('modelChange')||false));
          }
        },
        error: (err) => {
          setConfirmLoading(false);
          setTerms([err.ApiError?.message||'']);
        }
      })

    } catch (errInfo) {
      console.log('Validate Failed:', errInfo);
      setAutoTabKey('1');
    }

  }

  const edit = () => {
    setActionData({ ...actionData, action: 'edit' });
    actionRef.current = 'edit';
  }

  const cancelEdit = () => {
    const _action = getQueryParam(Action, props.location.search);

    setActionData({ ...actionData, action: (_action==='flow')?'flow':'detail' });
    actionRef.current = (_action==='flow')?'flow':'detail';
  }

  const onActionChange = (data) => {
    setModelerData(data);

    const _action = getQueryParam(Action, props.location.search);
    if (_action === 'flow' || (permitCheckOut&&data?.permitCheckOut===false)) {
      setActionData({ ...actionData, ...{modelerId: data?.id, editable: data?.editable||false, stateId: data?.state?.id||'', permitCheckOut: data?.permitCheckOut||false}  });
    }
  }

  const onCatalogModalCancel = (id = null) => {
    setCatalogModalVisible(false);

    if ((id||'') !== '') {
      saveLogic(null, id);
    }
  }

  const onHistory = () => {
    setHistoryAndVersionDrawerVisible(true);
  }

  const onHistoryAndVersionDrawerCancel = () => {
    setHistoryAndVersionDrawerVisible(false);
  }

  const attrIsEditingFunction = (value) => {
    attrIsEditingRef.current = value;
  }

  const indexIsEditingFunction = (value) => {
    indexIsEditingRef.current = value;
  }

  let title = '';
  if (action === 'add') {
    title = '新增模型';
  } else if (action === 'edit') {
    title = '模型编辑';
  } else if (action === 'detail' || action === 'flow') {
    title = '模型详情';
  } else if (action === 'detail-version') {
    title = '模型版本详情';
  }

  let actionsBtn = null;

  if (action==='add') {
    actionsBtn = (
      <Space>
        <Button 
          type='primary' 
          onClick={save}
          loading={confirmLoading}
          danger
        >
        保存
        </Button>
      </Space>
    )
  } else if (action === 'detail') {

    let editTip = '';
    if (!editable && stateId !== '4') {
      if (stateId === '2') {
        editTip = '待发布的模型不允许编辑';
      }
    }

    if (!permitCheckOut && stateId === '4') {
      editTip = `${holder||''}正在编辑中, 不允许再编辑`;
    }

    actionsBtn = (
      <Space>
        <Button type='primary' onClick={onHistory} danger >版本历史</Button>
        {
          (readOnly!=='true') && <Tooltip title={editTip}>
            <Button type='primary' onClick={edit} disabled={(stateId==='4')?!permitCheckOut:!editable} danger >
              编辑
            </Button>
          </Tooltip>
        }
      </Space>
    );
  } else if (action === 'edit') {
    actionsBtn = (
      <Space>
        <Button onClick={cancelEdit} >
        取消
        </Button>
        <Button type='primary' onClick={onHistory} danger >
          版本历史
        </Button>
        <Button 
          type='primary' 
          onClick={save}
          loading={confirmLoading}
          danger
        >
        保存
        </Button>
      </Space>
    )
  } else if (action === 'flow') {
    actionsBtn = (
      <Space>
        <Button type='primary' onClick={onHistory} danger>
        版本历史
        </Button>
        {
          editable && <Button type='primary' onClick={edit} danger >
          编辑
          </Button>
        }
      </Space>
    );
  }

  return (
    <EditModelContext.Provider value={{
      attrIsEditingFunction,
      indexIsEditingFunction,
    }}>
      <div className='edit-model position-relative'>
        <div className='edit-header'>
          <span style={{ fontSize: 16, fontWeight: 'bold', color: '#fff' }}>{title}</span>
        </div>
        <div className='edit-container'>
          <div className='edit-container-card'>
            <ImportAction hints={hints} onChange={onActionChange} action={action} modelerId={modelerId} ddl={ddl} form={form} terms={terms} roughModelerData={roughModelerData} permitCheckOut={permitCheckOut} stateId={stateId} versionId={versionId} autoTabKey={autoTabKey} {...props} /> 
          </div>
        </div>
        <div className='edit-footer'>
        {actionsBtn}  
        </div>
        <CatalogModal
          visible={catalogModalVisible}
          onCancel={onCatalogModalCancel}
        />
        <HistoryAndVersionDrawer
          id={modelerId}
          visible={historyAndVersionDrawerVisible}
          onCancel={onHistoryAndVersionDrawerCancel}
        />
      </div>
    </EditModelContext.Provider>
  );
} 

export default EditModel;