import React, { Component } from 'react';
import { createPortal } from 'react-dom';
import Mousetrap from 'mousetrap';
import style from './SearchModal.less';
import EasyvSpin from 'components/EasyvSpin';
import classname from 'classnames';
import message from 'components/message';
import { connect, ConnectedProps } from 'react-redux';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { arrayExpand } from 'utils/data-helper';
import panelThumb from 'images/panel.png';
import { addComponent } from 'models/component';
import { selectLayers, selectLayerWithScrollIntoView } from 'models/create-app';
import defaultImg from 'images/default.png';
import groupImg from 'images/thumb_group.png';
import { isGroup, isGeneralPanel ,getAssetsUrl} from 'utils/utils';
import Thumb from 'components/Thumb';
import { getConstantsIsLock } from './Gallery';
import { RootState } from 'models';
import { updateVersion } from 'models/updateVersion';
import { ComponentIcon } from 'components/IconButton';
import {Panel} from 'models/panel.types';

const imgFullPath = (path) => (path ? getAssetsUrl(`${path}`) : defaultImg);

type PropsFromRedux = (ConnectedProps<typeof connector> & RouteComponentProps) | any;
class Portal extends Component<{ top: string; root?: HTMLElement; onClose: () => void }> {
  div: HTMLDivElement;
  container: HTMLDivElement;
  root: any;
  constructor(props) {
    super(props);
    this.div = document.createElement('div');
    this.div.style.top = 'top' in props ? props.top : '50%';
    this.div.style.left = '50%';
    this.div.style.position = 'absolute';
    this.div.style.transform = `translate(-50%, ${'top' in props ? 0 : '-50%'})`;

    this.container = document.createElement('div');
    this.container.style.position = 'fixed';
    this.container.style.width = '100%';
    this.container.style.height = '100%';
    this.container.style.left = '0';
    this.container.style.top = '0';
    this.container.style['z-index'] = 20;
    this.container.appendChild(this.div);
    this.container.addEventListener('click', this.onClick);
    this.root = this.props.root || document.body;
  }
  componentDidMount() {
    document.body.appendChild(this.container);
    window.addEventListener('keydown', this.onEsc);
  }
  componentWillUnmount() {
    this.container.removeEventListener('click', this.onClick);
    document.body.removeChild(this.container);
    window.removeEventListener('keydown', this.onEsc);
  }

  onEsc = (e) => {
    // esc
    if (e.keyCode === 27) {
      const { onClose } = this.props;
      onClose && onClose();
    }
  };

  onClick = (e) => {
    const { onClose } = this.props;
    if (e.target === this.container && onClose) onClose();
  };

  render() {
    const { children } = this.props;
    return createPortal(children, this.div);
  }
}

class SearchModal extends Component<PropsFromRedux> {
  state = {
    visible: false,
    text: '',
    loading: false
  };

  componentDidMount() {
    Mousetrap.bind(['command+f', 'ctrl+f'], (e) => {
      if (!this.state.visible) {
        e.preventDefault();
        this.showModal();
      }
    });
  }

  componentDidUpdate() {
    // loading
    if (this.props.screenState === 2) {
      // 数据请求完毕
      // 条件满足
      this.state.loading &&
        this.setState({
          loading: false
        });
    }
  }

  componentWillUnmount() {
    Mousetrap.unbind(['command+f', 'ctrl+f']);
  }

  showModal = () => {
    if (this.props.screenState < 2) {
      // 当前fasle
      this.setState({
        loading: true
      });
      return;
    }
    this.setState({
      visible: true
    });
  };

  hideModal = () => {
    this.setState({
      visible: false,
      text: '',
      loading: false
    });
  };

  onClick = ({ type, data, name, fromScreen }) => {
    // 新增
    if (type === 'module') {
      const { moduleName, version, lock, edition } = data;
      if (lock) {
        const targetV = edition === 2 ? 'saas_advanced' : edition === 3 ? 'saas_vip' : null;
        if (targetV) {
          this.props.updateVersion({ show: true, targetVersion: targetV });
        } else {
          message.error('组件未分配权限，请联系平台运营人员处理');
        }
      } else {
        this.props.addComponent({ name, moduleName, version });
      }
    } else if (type === 'layer') {
      // 当前屏
      if (fromScreen == this.props.screenId) {
        this.props.selectLayerWithScrollIntoView(data.id);
      } else {
        // 转到其他屏
        const pathnameMatch = window.location.pathname.match(/\/create\/(\d+)/);
        const rootScreen = pathnameMatch ? pathnameMatch[1] : undefined;
        const { screensById, history } = this.props;
        const panelId = screensById[fromScreen].panelId;
        // 设置切换屏后选中的图层
        sessionStorage.setItem('pre_select_layer', data.id);
        //
        rootScreen == fromScreen
          ? history.push(`/create/${rootScreen}`)
          : history.push(`/create/${rootScreen}/panel_${panelId}/${fromScreen}`);
      }
    }
    this.hideModal();
  };

  render() {
    const { children, layers, constants, componentAddable, isAdmin, isRenew = false ,panelsById} = this.props;
    const panels:Panel[] = Object.values(panelsById) || [];
    const refIds = panels.filter(d=>d?.type === 1)?.reduce((all,curr)=>{ // 引用面板搜索
      return all.concat(curr.states.map(d=>d+''));
    },[]);
    // eslint-disable-next-line prefer-const
    let { visible, text, loading } = this.state;

    const foundResult: any = [];
    text = text.trim().toLowerCase();
    if (text.length) {
      if (componentAddable) {
        const foundModules = constants
          .filter((item) => ~item.name.toLowerCase().indexOf(text) && (isAdmin ? true : item.category !== '定制组件'))
          .map((item) => ({ type: 'module', name: item.name, image: imgFullPath(item.thumb), data: item }));
        foundModules.length && foundResult.push({ title: '添加组件', list: foundModules });
      }
      const foundLayers = layers.filter(d=>!refIds.includes(d.fromScreen)).filter((item) => ~item.name.toLowerCase().indexOf(text) || ~item.id.toString().indexOf(text));
      foundLayers.length && foundResult.push({ title: '现有图层', list: foundLayers });
    }

    return (
      <span>
        <span onClick={this.showModal}>
          <EasyvSpin loading={loading}>{children}</EasyvSpin>
        </span>
        {visible && (
          <Portal onClose={this.hideModal} top="92px">
            <div className={classname(style['search-container'])}>
              <div className={classname(style['search-input'], { [style['search-input--conn']]: text && !foundResult.length })}>
                <i className={classname('icon iconfont icon-a-Search2x', style['search-input__icon'])} />
                <input
                  placeholder="输入名称或ID搜索图层及组件"
                  ref={(el) => setTimeout(() => el && el.focus(), 0)}
                  onChange={(e) => this.setState({ text: e.target.value })}
                />
              </div>
              {text && <SearchList list={foundResult} onClick={this.onClick} isRenew={isRenew} />}
            </div>
          </Portal>
        )}
      </span>
    );
  }
}

function SearchList({ list, onClick, isRenew }) {
  return (
    <div className={classname(style['search-list'], { [style['serach-list--empty']]: !list.length })}>
      {!list.length && '未找到相应元素'}
      {list.reduce((acc, group, index) => {
        acc.push(
          <div className={style['search-list__title']} key={'title_' + index}>
            {group.title}
          </div>
        );
        group.list.forEach((item, x) => {
          acc.push(
            <div key={index + '_' + x} className={style['search-item']} onClick={() => onClick(item)}>
              <Thumb className={style['search-item__pic']} src={item.image} />
              {item.name} {item.id && <span>_{item.id}</span>}
              {group.title == '添加组件' && <ComponentIcon isRenew={isRenew} measureType={item.data?.edition} renderType="layout" />}
            </div>
          );
        });
        return acc;
      }, [])}
    </div>
  );
}

function mapStateToProps({ screenEdit, screensById, constants, createApp, user ,panelsById}: RootState) {
  const { id: screenId } = createApp;
  const constantList = getConstantsIsLock(constants, user);
  const isAdmin = user.userInfo.role && user.userInfo.role > 0;
  const thumbMap = constantList.reduce((acc, item) => {
    acc[item.moduleName] = item.thumb;
    return acc;
  }, {});

  const layers: any = [];
  Object.keys(screensById).filter((key) => {
    arrayExpand(
      screensById[key].layers,
      (item) => item.components,
      (item) => {
        const thumb = isGroup(item.id) ? groupImg : isGeneralPanel(item.id) ? panelThumb : imgFullPath(thumbMap[item.moduleName]);
        layers.push({
          id: item.id,
          type: 'layer',
          name: item.name,
          image: thumb,
          fromScreen: key,
          data: item
        });
      }
    );
  });

  return {
    screenId,
    thumbMap,
    layers,
    screenState: screenEdit.screenState,
    panelsById,
    screensById,
    constants: constantList,
    isAdmin: isAdmin,
    componentAddable: !(window.appConfig.LOCAL && user.userInfo.type === 'education'),
    isRenew: user.userInfo?.isRenew
  };
}

const mapDispatchToProps = {
  addComponent,
  selectLayers,
  updateVersion,
  selectLayerWithScrollIntoView
};

const connector = connect(mapStateToProps, mapDispatchToProps);

export default connector(withRouter(SearchModal));
