import React, { ChangeEvent, useState, useMemo, useEffect } from 'react';
import { connect } from 'react-redux';
import { useHistory } from 'react-router-dom';
import { Button, Table } from '@easyv/antd';
import { ColumnsType } from '@easyv/antd/lib/table';
import { getAllCallbackKeys } from 'utils/component';
import { selectComponentWithId } from 'models/create-app';
import { Drawer, Input } from '@easyv/react-gui';
import styles from '../index.less';
import localStyles from './Relationship.less';
import { ComponentItem } from 'models/component.types';
import EasyvEmpty from 'components/EasyvEmpty';
import { CloseOutlined } from '@easyv/react-icons';

interface CallbackListInterface {
  value: { [value: string]: string };
  receiveComponents: ComponentItem[];
  emitComponents: ComponentItem[];
}

function RelationshipCallback({ visible, componentsById, filters, onClose, selectComponentWithId, recycledComponentIdList, searchText }) {
  const history = useHistory();
  const [search, setSearch] = useState<string>('');
  const title = (
    <div className={styles.title}>
      <span>全局回调参数管理</span>
      <CloseOutlined
        onClick={() => {
          onClose?.();
        }}
        className={styles.icon}
      />
    </div>
  );
  useEffect(() => {
    if (searchText) {
      setSearch(searchText);
    }
  }, [searchText]);

  const callbackList: CallbackListInterface[] = useMemo(() => {
    // 这里需要做一层过滤处理，就是在回收站中的组件不应该在后续的components中显示
    const components = Object.keys(componentsById)
      .filter((item) => !recycledComponentIdList.includes(item))
      .map((d) => componentsById[d]);

    const callbacks = getAllCallbackKeys(components, filters);
    const { filter, data, interaction } = callbacks;

    const getCallbackKeys = (obj) => {
      return Object.keys(obj).reduce((all, item) => all.concat(obj[item]), []);
    };

    const callbackKeys = Array.from(
      new Set(getCallbackKeys(filter).concat(getCallbackKeys(data)).concat(getCallbackKeys(interaction)))
    ).filter((d: string) => d.toString().toLowerCase().includes(search.toLowerCase()));

    // 获取源组件
    const emitComponents = callbackKeys.map((d) => {
      return Object.keys(interaction)
        .filter((o) => interaction[o].includes(d))
        .map((o) => componentsById[o]);
    });

    // 获取目标组件
    const receiveComponents = callbackKeys.map((d) => {
      const filterComponentIds = Object.keys(filter).filter((o) => filter[o].includes(d));
      const dataComponentIds = Object.keys(data).filter((o) => data[o].includes(d));
      return Array.from(new Set(filterComponentIds.concat(dataComponentIds))).map((o) => componentsById[o]);
    });

    return callbackKeys.reduce((pre, cur, index) => {
      if (!receiveComponents[index].length && !emitComponents[index].length) {
        return [...pre];
      }
      return [...pre, { value: cur, receiveComponents: receiveComponents[index], emitComponents: emitComponents[index] }];
    }, []);
  }, [recycledComponentIdList, filters, visible, search, componentsById]);

  const handleSelect = (id) => {
    onClose();
    selectComponentWithId(id, history);
  };

  const closeDrawer = () => {
    onClose();
    if (searchText) {
      setSearch(searchText);
    }
  };

  const columns: ColumnsType<CallbackListInterface> = [
    {
      key: 1,
      title: '源组件',
      align: 'center',
      dataIndex: 'emitComponents',
      colSpan: 1,
      render(row) {
        return (
          <span className={localStyles.cell}>
            {row.length
              ? row.map((o) => {
                  return (
                    <Button key={o.id} type="primary" ghost onClick={() => handleSelect(o.id)} title={o.name}>
                      {o.name}
                    </Button>
                  );
                })
              : '无对应组件'}
          </span>
        );
      }
    },
    {
      key: 2,
      title: '回调参数',
      width: 140,
      align: 'center',
      ellipsis: true,
      dataIndex: 'value'
    },
    {
      key: 3,
      title: '目标组件',
      align: 'center',
      dataIndex: 'receiveComponents',
      colSpan: 1,
      render(row) {
        return (
          <span className={localStyles.cell}>
            {row.length
              ? row.map((o) => {
                  return (
                    <Button key={o.id} type="primary" ghost onClick={() => handleSelect(o.id)} title={o.name}>
                      {o.name}
                    </Button>
                  );
                })
              : '无对应组件'}
          </span>
        );
      }
    }
  ];

  const handleSearch = (e: ChangeEvent<HTMLInputElement>) => {
    setSearch(e.target.value);
  };

  return (
    <Drawer
      className={`${styles.drawer} ${styles.painter} ${styles.drawerTitle}`}
      closable={false}
      title={title}
      placement="right"
      visible={visible}
      mask={false}
      width={520}
      destroyOnClose={true}
      onClose={closeDrawer}>
      <div className={localStyles.search}>
        <Input
          prefix={<i className="icon iconfont icon-btn_search" />}
          value={search}
          onChange={handleSearch}
          placeholder="请搜索回调参数"
          style={{ width: 294, height: 28 }}
        />
      </div>
      <Table
        locale={{
          emptyText: (
            <div style={{ margin: '40px 0' }}>
              <EasyvEmpty />
            </div>
          )
        }}
        className={localStyles.table}
        columns={columns}
        dataSource={callbackList}
        pagination={false}
        bordered
        rowKey="value"
      />
    </Drawer>
  );
}

const mapStateToProps = ({ componentsById, filters, recycleBinData }) => {
  return {
    componentsById,
    filters: filters.list,
    recycleBinData,
    recycledComponentIdList: recycleBinData.map((item) => item.componentId)
  };
};

const mapDispatchToProps = {
  selectComponentWithId
};

export default connect(mapStateToProps, mapDispatchToProps)(RelationshipCallback);
