import React, { useEffect, useState } from 'react';
import { Modal, Select, Form, Input, Divider, Space, Button, Upload } from 'antd';
import { UploadOutlined } from '@ant-design/icons';

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

const { Option } = Select;

const UpdateDatasourceModal = (props) => {
  const { visible, onCancel, databases, action, id, scope } = props;

  const [ selectedDatabaseKey, setSelectedDatabaseKey ] = useState('');
  const [ allSupportedDatasourceTypies, setAllSupportedDatasourceTypies ] = useState([]);
  const [ currentSupportedDatasourceTypies, setCurrentSupportedDatasourceTypies ] = useState({});
  const [ currentDatasource, setCurrentDatasource ] = useState({});
  const [ confirmLoading, setConfirmLoading ] = useState(false);
  const [ validateLoading, setValidateLoading ] = useState(false);
  const [ fileListBindName, setFileListBindName ] = useState([]);

  const [ credentialForm ] = Form.useForm();
  const [ datasourceForm ] = Form.useForm();

  useEffect(() => {

    if (visible) {

      reset();
      getAllSupportedDatasourceTypies();
    }
    //eslint-disable-next-line react-hooks/exhaustive-deps
  }, [visible, action, id])

  const getAllSupportedDatasourceTypies = () => {
    dispatch({
      type: 'datasource.getAllSupportedDatasourceTypies',
      callback: data => {
        function compare(val1, val2) {
          var a = val1.seq;
          var b = val2.seq;
          return (a - b);
        }

        (data||[]).forEach(item => {
          item.credential && (item.credential.credentialParameters||[]).sort(compare);
          (item.targetParameters||[]).sort(compare);
        })

        setAllSupportedDatasourceTypies(data||[]);
        if (action === 'add') {
          const _defaultKey = (data||[]).length>0?data[0].type:'';
          setSelectedDatabaseKey(_defaultKey);
          getCurrentSupportedDatasourceTypies(data||[], _defaultKey);
        } else if (action === 'edit') {
          getCurrentDatasource(data||[]);
        }
      }
    })
  }

  const getCurrentDatasource = (typies) => {
    dispatch({
      type: 'datasource.getDatasource',
      payload: {
        datasourceId: id
      },
      callback: data => {
        const _defaultKey = (data)?(data.type||''):'';
        setSelectedDatabaseKey(_defaultKey);
        getCurrentSupportedDatasourceTypies(typies||[], _defaultKey);
        setCurrentDatasource(data);
        setFormFiledsValue(data);
      }
    })
  }

  const getCurrentSupportedDatasourceTypies = (allTypies, type) => {
    let _currentTypies = null;
    (allTypies||[]).forEach(typies => {
      if (typies.type === type) {
        _currentTypies = {...typies};
      }
    })
    console.log(_currentTypies)
    setCurrentSupportedDatasourceTypies(_currentTypies);
  }

  const setFormFiledsValue = (data) => {
    let _credentialFieldsValue = {}, _datasourceFieldsValue = {};

    data && data.credential && (data.credential.credentialParameters||[]).forEach(item => {
      _credentialFieldsValue[item.name||''] = item.value||'';
    });

    credentialForm.setFieldsValue(_credentialFieldsValue);

    data && (data.targetParameters||[]).forEach(item => {
      _datasourceFieldsValue[item.name||''] = item.value||'';
    });

    datasourceForm.setFieldsValue(_datasourceFieldsValue);
  }

  const onDatabaseChange = (value) => {

    reset();

    setSelectedDatabaseKey(value);
    getCurrentSupportedDatasourceTypies(allSupportedDatasourceTypies, value);
  }

  const onOk = async(test = false) => {
    try {
      const datasourceRow = await datasourceForm.validateFields();
      const credentialRow = await credentialForm.validateFields();

      let newDatasource = {...currentSupportedDatasourceTypies, ...{
        namespace: ((scope||[]).length>0?scope[0]:''),
        scope: ((scope||[]).length>2?scope[2]:'')
      }};

      if (action === 'edit') {
        newDatasource = {...newDatasource, ...currentDatasource};
      }

      //深拷贝
      newDatasource = JSON.parse(JSON.stringify(newDatasource));
      newDatasource && (newDatasource.targetParameters||[]).forEach(item => {
        if (item.selectMode === null && item.required) {
          item.needEnc = true;
          if (action === 'edit') {
            item.needEnc = (item.value!==datasourceRow[item.name]);
          }
        }

        item.value = datasourceRow[item.name]||'';
        if (item.selectMode === 'file') {
          const index = (fileListBindName||[]).findIndex(_item => _item.name===item.name);
          if (index !== -1) {
            item.value = fileListBindName[index].data||'';
          }
        }
      });

      newDatasource && newDatasource.credential && (newDatasource.credential.credentialParameters||[]).forEach(item => {
        if (item.selectMode === null && item.required) {
          item.needEnc = true;
          if (action === 'edit') {
            item.needEnc = (item.value!==credentialRow[item.name]);
          }
        }
        
        item.value = credentialRow[item.name]||'';
        if (item.selectMode === 'file') {
          const index = (fileListBindName||[]).findIndex(_item => _item.name===item.name);
          if (index !== -1) {
            item.value = fileListBindName[index].data||'';
          }
        }
      })

      if (test) {
        setValidateLoading(true);
        dispatch({
          type: 'datasource.validateDatasource',
          payload: {
            data: newDatasource
          },
          callback: () => {
            setValidateLoading(false);
            showMessage('success', '测试成功');
          },
          error: () => {
            setValidateLoading(false);
          }
        })
      } else {
        setConfirmLoading(true);
        dispatch({
          type: 'datasource.saveDatasource',
          payload: {
            data: newDatasource
          },
          callback: data => {
            setConfirmLoading(false);
            onCancel && onCancel(true);
          },
          error: () => {
            setConfirmLoading(false);
          }
        })
      }

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

  const reset =() => {
    setFileListBindName([]);
    credentialForm.resetFields();
    datasourceForm.resetFields();
  }

  const onRemoveFile = (name, file) => {
    const index = (fileListBindName||[]).findIndex(item => item.name===name);
    
    if (index !== -1) {
      const fileList = fileListBindName[index].fileList;
      const _index = fileList.indexOf(file);
      fileList.splice(_index, 1);

      setFileListBindName([...fileListBindName]);
    }
  }

  const beforeUpload = (name, file) => {
    const index = (fileListBindName||[]).findIndex(item => item.name===name);
    var reader = new FileReader();
    
    reader.onload = function (ext) {
      
      if (index !== -1) {
        fileListBindName[index].fileList = [file];
        fileListBindName[index].data = ext.target.result.substring(ext.target.result.indexOf(',')+1);
      } else {
        fileListBindName.push({ name, fileList: [file], data: ext.target.result.substring(ext.target.result.indexOf(',')+1) });
      } 

      setFileListBindName([...fileListBindName]);
    }

    reader.readAsDataURL(file);
  }

  const formItemLayout = {
    labelCol: {
      xs: { span: 24 },
      sm: { span: 6 },
    },
    wrapperCol: {
      xs: { span: 24 },
      sm: { span: 16 },
    },
  };

  return (
    <Modal
      forceRender
      title={action==='add'?'新增数据源':'修改数据源'}
      visible={visible}
      width={700}
      onCancel={() => { onCancel && onCancel() }}
      footer={
        <Space>
          <Button type="primary" onClick={() => { onOk(true); }} loading={validateLoading}>测试连接</Button>
          <Button onClick={() => onCancel && onCancel() }>返回</Button>
          <Button type="primary" onClick={() => {onOk(false);}} loading={confirmLoading}>保存</Button>
        </Space>
      }
    >
      <div className='d-flex mb-5' style={{ alignItems: 'center' }}>
        <span className='mr-3' style={{ marginLeft: 'auto' }}>数据源类型:</span>
        <Select 
          value={selectedDatabaseKey} 
          style={{ width: 150 }}
          onChange={onDatabaseChange}
          disabled={action==='edit'}
        >
        {
          databases && databases.map((item, index) => {
            return (
              <Option key={index} value={item.targetType}>{item.targetName}</Option>
            );
          })
        }
        </Select>
      </div>
      <Divider>数据源信息</Divider>
      <Form {...formItemLayout} form={datasourceForm}>
      {
        currentSupportedDatasourceTypies && (currentSupportedDatasourceTypies.targetParameters||[]).map((item, index) => {
          return (
            <Form.Item 
              label={item.cnName||''}
              name={item.name||''}
              key={index}
              rules={[{ required: item.required, message: '必填项'}]}
            >
            { 
              (item.selectMode==='singleSelect') ? <Select >
                {
                  (item.selectItem||[]).map((item,index) => {
                    return <Select.Option key={index} value={item||''} >{item||''}</Select.Option>
                  })
                }
              </Select> : ( item.show ? <Input placeholder={item.explain||''} /> : <Input.Password placeholder={item.explain||''} visibilityToggle={false} /> ) }
            </Form.Item>
          )
        })
      }
      </Form>
      <Divider>认证信息</Divider>
      <Form {...formItemLayout} form={credentialForm}>
      {
        currentSupportedDatasourceTypies && currentSupportedDatasourceTypies.credential && (currentSupportedDatasourceTypies.credential.credentialParameters||[]).map((item, index) => {

          let _fileList = [];
          const _index = (fileListBindName||[]).findIndex(_item => _item.name===item.name);
          if (_index !== -1) {
            _fileList = fileListBindName[_index].fileList || [];
          }

          return (
            <Form.Item 
              label={item.cnName||''}
              name={item.name||''}
              key={index}
              rules={[{ required: item.required, message: '必填项'}]}
            >
            { item.selectMode==='file' ? (
              <Upload 
                onRemove={(file) => { onRemoveFile(item.name, file); }}
                beforeUpload={(file) => { beforeUpload(item.name, file); }}
                fileList={_fileList}
                // accept='.txt'
              >
                <Button icon={<UploadOutlined />}>
                  选择文件上传
                </Button>
              </Upload> 
              ) : ( item.show ? <Input placeholder={item.explain||''}  /> : <Input.Password placeholder={item.explain||''} visibilityToggle={false} /> ) }
            </Form.Item>
          )
        })
      }
      </Form>
    </Modal>
  );
}

export default UpdateDatasourceModal;