import React, { useEffect, useState, useCallback } from 'react';
import { Modal, Checkbox, Row, Col, Form, Input, Empty, Select } from 'antd';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import update from 'immutability-helper';

import DragTag from './DragTag';
import PreviewTree from './PreviewTree';
import { dispatch, dispatchLatest } from '../../../../model';
import { AssetManageReference, AssetBrowseReference, ResourceBrowseReference } from '../../../../util/constant';

import { showMessage } from '../../../../util';

const resourceTypes = [
  { key: 'innerSource', name: '内部资源' },
  { key: 'outerSource', name: '外部资源' },
  { key: 'dataAsset', name: '资产' },
]

const CustomDirectoryModal = (props) => {
  const { visible, onCancel, action, dirId, reference = AssetManageReference } = props;

  const [ keyword, setKeyword ] = useState('');
  const [ data, setData ] = useState([]);
  const [ filterData, setFilterData ] = useState([]);
  const [ previewTreeData, setPreviewTreeData ] = useState(null);
  const [ checkedValues, setCheckedValues ] = useState([]);
  const [ checkedData, setCheckedData ] = useState([]);
  const [ confirmLoading, setConfirmLoading ] = useState(false);

  const [ form ] = Form.useForm();

  useEffect(() => { 
    if (visible) {
      getAllElementsThenGetCurrentDirectory();
    } 
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [visible])

  useEffect(() => {

    if ((checkedValues||[]).length>0) {
      getPreviewTreeData();
    }

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

  const getAllElementsThenGetCurrentDirectory = () => {
    dispatch({
      type: 'assetmanage.listCustomElements',
      callback: elements => {
        setData(elements||[]);
        setFilterData((elements||[]).filter(item => (item.name||'').indexOf(keyword)!==-1));
        if (action === 'edit') {
          getCurrentDirectory(elements||[]);
        }
      }
    })
  }

  const getCurrentDirectory = (elements) => {
    dispatch({
      type: 'assetmanage.getDirectoryById',
      payload: { 
        dirId
      },
      callback: data => {
        setCheckedValues(data.elementIds||[]);
        form.setFieldsValue({ name: data.name||'', desc: data.desc||'' });
        onCheckboxChange(data.elementIds||[], elements);
      }
    })
  }

  const getPreviewTreeData = () => {
    if ((checkedValues||[]).length === 0) {
      return;
    }

    let url = 'assetmanage.previewTreeByCustomElements';

    let payload = {
      data: checkedValues
    } 

    if (reference===AssetManageReference) {
      payload.params = {
        resourceTypes: (form.getFieldValue('resourceTypes')||[]).join(',')
      };
    }

    if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
      url = 'assetmanage.previewTreeByCustomElementsAndResourceType';

      payload.params = {
        resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset',
      }
    }

    dispatchLatest({
      type: url,
      payload,
      callback: data => {
        setPreviewTreeData((data||[]).length>0?data[0]:{});
      }
    })
  }

  const onSearchChange = (e) => {
    setKeyword(e.target.value);
    setFilterData((data||[]).filter(item => (item.name||'').indexOf(e.target.value)!==-1));
  }

  const onCheckboxChange = (checkedValues, elements = data) => {
    setCheckedValues(checkedValues);
    const _checkedData = [];

    (checkedValues||[]).forEach(value => {
      (elements||[]).forEach(item => {
        if (value === item.id) {
          _checkedData.push(item);
        }
      })
    })

    setCheckedData(_checkedData);
  }

  const onValuesChange = (changedValues, allValues) => {
    if (changedValues.hasOwnProperty('resourceTypes')) {
      getPreviewTreeData();  
    }
  }

  const reset = () => {
    setConfirmLoading(false);
    setKeyword('');
    setCheckedValues([]);
    setCheckedData([]);
    setPreviewTreeData(null);
    form.resetFields();
  }

  const onOk = async() => {
    if ((checkedValues||[]).length === 0) {
      showMessage('info', '请先选择要素');
      return;
    }

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

      let payload = {
        data: checkedValues,
        params: row
      }

      if (action === 'edit') {
        payload.params = {...payload.params, dirId};
      }

      let url = 'assetmanage.saveTreeByCustomElements';

      if (reference===AssetManageReference) {
        payload.params = {
          ...payload.params,
          resourceTypes: (row.resourceTypes||[]).join(',')
        }
      }

      if (reference===AssetBrowseReference || reference===ResourceBrowseReference) {
        url = 'assetmanage.saveTreeByCustomElementsAndResourceType';

        payload.params = { ...payload.params, resourceType: (reference===ResourceBrowseReference)?'resource':'dataAsset' };
      }

      dispatch({
        type: url,
        payload,
        callback: data => {
          setConfirmLoading(false);
          reset();
          onCancel && onCancel(true, data?.id);
        },
        error: () => {
          setConfirmLoading(false);
        }
      })

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

  const moveTag = useCallback((dragIndex, hoverIndex) => {
    const dragTag = checkedData[dragIndex];

    const newCheckedData = update(checkedData, {
      $splice: [
        [dragIndex, 1],
        [hoverIndex, 0, dragTag],
      ],
    });

    const newCheckedValues = [];
    newCheckedData.forEach(item=> {
      newCheckedValues.push(item.id);
    })

    setCheckedData(newCheckedData);
    setCheckedValues(newCheckedValues);
  }, [checkedData]);  

  const onTagClose = (id) => {
    const newCheckedValues = [...checkedValues];
    const index = newCheckedValues.indexOf(id);
    if (index !== -1) {
      newCheckedValues.splice(index, 1);
      onCheckboxChange(newCheckedValues);
    }
  }
  
  const renderItem = (item, index) => {
    return (<DragTag key={item.id} index={index} id={item.id} text={item.name||''} moveTag={moveTag} onClose={()=>{onTagClose(item.id)}}/>);
  };

  const formItemLayout = {
    labelCol: {
      xs: { span: 24 },
      sm: { span: 5 },
    },
    wrapperCol: {
      xs: { span: 24 },
      sm: { span: 17 },
    },
  };

  return (
    <Modal
      forceRender
      title={action==='add'?'新增自定义':'修改自定义'}
      visible={visible}
      width={800}
      centered
      confirmLoading={confirmLoading}
      onCancel={() => { 
        reset();
        onCancel && onCancel() 
      }}
      onOk={onOk}
    >
      <Row gutter={30}>
        <Col span={8} style={{ borderRight: '1px solid #EFEFEF' }}>
          <div className='mb-3'>资产目录要素</div>
          <Input  
            value={keyword}
            placeholder='请输入资产目录要素'
            style={{ marginBottom:10 }} 
            onChange={(e) => { onSearchChange(e) }}
          />
          <div style={{ maxHeight: 500, overflow: 'auto' }}>
            <Checkbox.Group value={checkedValues} onChange={onCheckboxChange}>
            {
              (data||[]).map((item, index) => {

                const exsit = (filterData||[]).some(filterItem => filterItem.id === item.id);

                return (
                  <Row key={index} style={{ display: exsit?'':'none' }}>
                    <Checkbox value={item.id||''}>{item.name||''}</Checkbox>
                  </Row>
                );
              })
            }
            </Checkbox.Group>
          </div>
        </Col>
        <Col span={16}>
          {
            (checkedData||[]).length===0 && <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无层级" />
          }
          {
            (checkedData||[]).length>0 && <> 
              <div className='mb-3'>拖动可调整层级</div>
              <DndProvider backend={HTML5Backend}>
              {
                (checkedData||[]).map((item, index) => renderItem(item, index))
              }
              </DndProvider>
              <div style={{ height: 300 }}>
                <PreviewTree data={previewTreeData} />
              </div>
            </>
          }
          <Form className='mt-5' {...formItemLayout} form={form} onValuesChange={onValuesChange}>
            <Form.Item 
              label='命名'
              name='name'
              rules={[{ required: true, message: '请命名'}]}
            >
              <Input />
            </Form.Item>
            {
              reference===AssetManageReference && <Form.Item
                label='数据范围'
                name='resourceTypes'
              >
                <Select mode="multiple" allowClear>
                {
                  resourceTypes.map((item,index) => {
                    return <Select.Option key={item.key}>{item.name}</Select.Option>
                  })
                }
                </Select>
              </Form.Item>
            }
            <Form.Item 
              label='描述或原因'
              name='desc'
            >
              <Input />
            </Form.Item>
          </Form>
        </Col>
      </Row>
    </Modal>
  );
}

export default CustomDirectoryModal;