import React, {
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react';

import classNames from 'classnames';
import PinyinMatch from 'pinyin-match';
import { useHistory } from 'react-router-dom';

import Icon, { RightCircleOutlined } from '@ant-design/icons';

import Modal from '../modal';
import styes from './index.less';

const HistorySvg = () => (
  <svg
    className="icon"
    viewBox="0 0 1024 1024"
    version="1.1"
    width="10"
    height="10"
  >
    <path
      d="M1016.405333 0h-351.573333a7.594667 7.594667 0 0 0-5.376 12.885333l149.077333 149.674667-244.224 249.770667H434.346667A7.594667 7.594667 0 0 0 426.666667 419.84v169.898667c0 4.266667 3.413333 7.594667 7.594666 7.594666h169.813334c4.266667 0 7.68-3.413333 7.68-7.594666V486.826667l263.253333-257.792 136.106667 135.509333A7.594667 7.594667 0 0 0 1024 359.253333V7.68A7.594667 7.594667 0 0 0 1016.405333 0z"
      fill="#C1C1C1"
    />
    <path
      d="M979.626667 640a45.226667 45.226667 0 0 0-44.202667 46.08v249.258667H88.490667V88.576h245.418666l1.194667-0.085333A45.056 45.056 0 0 0 378.88 44.288 45.056 45.056 0 0 0 333.994667 0H7.68A7.68 7.68 0 0 0 0 7.68v1008.64c0 4.266667 3.413333 7.68 7.68 7.68h1008.64c4.266667 0 7.68-3.413333 7.68-7.68V686.08a45.226667 45.226667 0 0 0-44.373333-46.08z"
      fill="#C1C1C1"
    />
  </svg>
);
const DelHistory = () => (
  <svg
    className="icon"
    viewBox="0 0 1024 1024"
    version="1.1"
    width="12"
    height="12"
  >
    <path
      d="M153.6 345.6a38.4 38.4 0 0 1 0-76.8h665.6a38.4 38.4 0 1 1 0 76.8H153.6z"
      fill="#888888"
    />
    <path
      d="M345.6 307.2a38.4 38.4 0 0 1-76.8 0V204.8c0-49.4592 40.1408-89.6 89.6-89.6h256c49.4592 0 89.6 40.1408 89.6 89.6v102.4a38.4 38.4 0 1 1-76.8 0V204.8a12.8 12.8 0 0 0-12.8-12.8H358.4a12.8 12.8 0 0 0-12.8 12.8v102.4zM166.4 460.8a38.4 38.4 0 0 1 76.8 0v358.4c0 7.0656 5.7344 12.8 12.8 12.8h460.8a12.8 12.8 0 0 0 12.8-12.8V460.8a38.4 38.4 0 1 1 76.8 0v358.4A89.6 89.6 0 0 1 716.8 908.8H256A89.6 89.6 0 0 1 166.4 819.2V460.8z"
      fill="#888888"
    />
    <path
      d="M371.2 460.8a38.4 38.4 0 0 1 76.8 0v256a38.4 38.4 0 1 1-76.8 0V460.8zM524.8 460.8a38.4 38.4 0 0 1 76.8 0v256a38.4 38.4 0 1 1-76.8 0V460.8z"
      fill="#888888"
    />
  </svg>
);
const HistoryHrefIcon = props => <Icon component={HistorySvg} {...props} />;
const DelIcon = props => <Icon component={DelHistory} {...props} />;
const unique = (arr, val) => {
  const res = new Map();
  return arr.filter(item => !res.has(item[val]) && res.set(item[val], 1));
};
const SearchPanel = props => {
  const [visible, setVisible] = useState(false);
  // const [disabled, setDisabled] = useState(false);
  // const [axis, setAxis] = useState('both');
  // const [currentIndex, setCurrentIndex] = useState(-1);
  const [eventCounts, setEventCounts] = useState(() => ['resultConsole', -1]);
  const featureRef = useRef(null);
  const consoleRef = useRef(null);
  let recentKeywords = props.recentKeywords.toJS
    ? props.recentKeywords.toJS()
    : props.recentKeywords;
  recentKeywords = Array.isArray(recentKeywords)
    ? recentKeywords
    : [recentKeywords];

  let recentVisited = props.recentVisited.toJS
    ? props.recentVisited.toJS()
    : props.recentVisited;
  recentVisited = Array.isArray(recentVisited)
    ? recentVisited
    : [recentVisited];

  let recentProducts = props.recentProducts.toJS
    ? props.recentProducts.toJS()
    : props.recentProducts;
  recentProducts = Array.isArray(recentProducts)
    ? recentProducts
    : [recentProducts];

  const history = useHistory();
  // eslint-disable-next-line consistent-return
  function getParents(data, key) {
    // eslint-disable-next-line guard-for-in,no-restricted-syntax
    for (const i in data) {
      if (data[i].key === key) {
        return [];
      }
      if (data[i].routes) {
        const ro = getParents(data[i].routes, key);
        if (ro !== undefined) return ro.concat(data[i]);
      }
    }
  }
  const goFeature = (path, rect, value) => {
    // eslint-disable-next-line no-param-reassign
    value = value || props.value;
    const findKeywordIndex =
      recentKeywords.length > 0
        ? recentKeywords.findIndex(item => item.data === value)
        : -1;
    const findRecentVisitedIndex =
      recentVisited.length > 0
        ? recentVisited.findIndex(item => item.data.name === rect.name)
        : -1;
    if (findKeywordIndex === -1)
      props.updateRecentKeywords && props.updateRecentKeywords(value);
    if (findRecentVisitedIndex === -1)
      props.updateRecentVisited && props.updateRecentVisited(rect);
    let parents = getParents(props.menu, rect.key);
    parents = parents[parents.length - 1];
    const findIndex = props.menu.findIndex(k => k.name === parents.name);
    props.updateCurrentIndex && props.updateCurrentIndex(findIndex);
    props.updateOpenKeys && props.updateOpenKeys([parents.key]);
    props.updateComplexConfig && props.updateComplexConfig({});
    props.updateComplexPathName && props.updateComplexPathName(null);

    if (rect && rect.routes && rect.routes.length > 0) {
      props.updateComplexConfig && props.updateComplexConfig(rect);
      props.updateComplexPathName &&
        props.updateComplexPathName(rect.routes[0].path);
      history.push(rect.routes[0].path);
    } else {
      history.push(path);
    }
    props.updateSelectedKeys && props.updateSelectedKeys(rect.key);
    props.updatePathname && props.updatePathname(rect.key);
  };
  const goProduct = (event, item) => {
    /* eslint-disable */
    event.persist && event.persist();
    event && event.stopPropagation();
    const findRecentIndex =
      recentProducts.length > 0
        ? recentProducts.findIndex(item => item.data.name === item.name)
        : -1;
    if (findRecentIndex === -1)
      props.updateRecentProduct && props.updateRecentProduct(item);
    const findIndex = props.menu.findIndex(k => k.name === item.name);
    props.updateCurrentIndex && props.updateCurrentIndex(findIndex);
  };

  const handlerMore = event => {
    event.persist && event.persist();
    event && event.nativeEvent.stopImmediatePropagation();
    setVisible(!visible);
    props.onClose && props.onClose(event);
  };

  const handlerDelHistory = () => {
    props.clearRecentProduct && props.clearRecentProduct();
  };

  const matchValue = (str, value) => {
    const match = PinyinMatch.match(str, value || props.value);
    return match;
  };

  const transformRecentProduct = () =>
    unique(recentProducts.map(item => item.data), 'name');

  const transformWillSearch = () => {
    if (props.willSearch.length === 0) {
      return null;
    }
    return (
      <div className={styes.item}>
        <div className={styes.title}>你是不是想搜：</div>
        <div className={styes.label}>
          {(unique(props.willSearch, 'name') || []).map(item => (
            // eslint-disable-next-line react/button-has-type
            <button
              className={styes.btn}
              key={item.name}
              title={item.title}
              onClick={() => props.onWillSearch(item.name)}
            >
              {item.name}
            </button>
          ))}
        </div>
      </div>
    );
  };

  const transformConsole = () => {
    if (props.console.length === 0) {
      return <div className={styes.empty}>没有找到相关内容</div>;
    }
    return (props.console || []).map((item, index) => {
      const match = matchValue(item.name);
      const name = match ? (
        <span>
          {item.name.substring(0, match[0])}
          <em>{item.name.substring(match[0], match[1] + 1)}</em>
          {item.name.substring(match[1] + 1)}
        </span>
      ) : (
        item.name
      );
      return (
        <a
          className={styes.featureItem}
          key={item.name}
          onClick={event => goProduct(event, item)}
          tabIndex="1"
          onKeyDown={event => event.key === 'Enter' && event.keyCode === 13 && goProduct(event, item)}
        >
          <span className={styes.text}>{name}</span>
          <span className={styes.featIn}>
            <RightCircleOutlined />
          </span>
        </a>
      );
    });
  };

  const transformFeature = () => {
    if (props.willSearch.length === 0) {
      return <div className={styes.empty}>没有找到相关内容</div>;
    }
    return (unique(props.willSearch.slice(0, 20), 'path') || []).map(
      (item, index) => {
        const match = matchValue(item.name);
        const name = match ? (
          <span>
            {item.name.substring(0, match[0])}
            <em>{item.name.substring(match[0], match[1] + 1)}</em>
            {item.name.substring(match[1] + 1)}
          </span>
        ) : (
          item.name
        );
        return (
          <a
            className={styes.featureItem}
            key={index}
            onClick={() => goFeature(item.path, item)}
            tabIndex="1"
            onKeyDown={event => event.key === 'Enter' && event.keyCode === 13 && goFeature(item.path, item)}
          >
            <span className={styes.text}>
              {name}
              <HistoryHrefIcon className={styes.href} />
            </span>
            <span className={styes.featIn}>
              {item.parent && item.parent.name}
            </span>
          </a>
        );
      },
     );
  };
  useEffect(() => {
    setEventCounts(['resultConsole', -1])
  }, [props.value]);

  const RESULT_KEYS = ['resultConsole', 'resultFeature'];
  const getFistKey = (response, key, type) => {
    const result = RESULT_KEYS.filter(item => {
      const ret = response[item];
      return !!(ret && 'success' === ret.type && ret.response.items.length > 0);
    });
    if(0 === result.length) {
      return null;
    };
    if(!key) {
      return "down" === type ? result[0]: type === "left" ? result[0]: type === "right" ? result[result.length - 1]:result[result.length - 1];
    }
    const index = result.indexOf(key);
    return index < 0 ? null: 'down' === type ? index + 1 < result.length ? result[index + 1]: null: index - 1 >= 0 ? result[index - 1]: null;

  }
  const transfromEventHander = useCallback((children, data, type, handlerKey) => {
    if (children === 'none') {
      return
    }

    if (null === children) {
      const key = getFistKey(data, null, handlerKey ? handlerKey: type);
      if (!key) {
        return null;
      }
      children = key === 'resultConsole' ? consoleRef.current.children: featureRef.current.children
      const ret = data[key];
      const currentIndex = 'up' === type ? ret.response.items.length - 1 : 0
      return 'success' !== ret.type ? null : (
        setEventCounts([key, currentIndex]),
        'up' === type ? (props.onNavUp && (props.onNavUp(), children[currentIndex].focus())): props.onNavDown && (props.onNavDown(), children[currentIndex].focus())
      );
    }

    let eventsKey = eventCounts[0];
    let eventsIndex = eventCounts[1];
    let resultData = data[eventsKey];
    if(resultData.response.items.length === 0) {
      const key = getFistKey(data, null, type);
      eventsKey = key;
      eventsIndex= -1;
      resultData = data[key];
      children = key === 'resultConsole' ? consoleRef.current.children: featureRef.current.children
    }
    if ('success' !== resultData.type) {
      return null;
    }
    const index= "up" === type ? eventsIndex - 1: eventsIndex + 1;
    if(index >=0 && index < resultData.response.items.length) {
      return setEventCounts([eventsKey, index]), 'up' === type ? (props.onNavUp && (props.onNavUp(), children[index].focus())): props.onNavDown && (props.onNavDown(), children[index].focus())
    }
    const getKey = getFistKey(data, eventsKey, type);
    if(!getKey) {
      return null;
    }
    const result = data[getKey];
    if('success' !== result.type) {
      return null;
    }
    if('up' === type) {
      children = getKey === 'resultConsole' ? consoleRef.current.children: featureRef.current.children
      return setEventCounts([getKey, result.response.items.length - 1]), props.onNavUp && ( props.onNavUp(), children[result.response.items.length - 1].focus())
    }
    return setEventCounts([getKey, 0]), (props.onNavDown && (props.onNavDown(), featureRef.current.children[0].focus()))
  }, [eventCounts, props.console, props.willSearch])

  const transfomResponse = (data) => {
    return {
      query: props.value,
      response: {
        items: data,
        total: data.length
      },
      type: 'success'
    }
  }
  let children = null;
  const eventHander = useCallback((event) => {
    const transformData = {
      resultConsole: transfomResponse(props.console),
      resultFeature: transfomResponse( unique(props.willSearch.slice(0, 20), 'path')),
    };

    switch (event.key) {
      case "Escape":
        props.onEsc && ( event.preventDefault(), props.onEsc())
        break;
      case "ArrowRight":
        event.preventDefault();
        children = featureRef.current.children;
        transfromEventHander(null, transformData, 'down', 'right')
        break;
      case "ArrowDown":
        const type = eventCounts[0]
        children = type === 'resultFeature'  ? featureRef.current.children: consoleRef.current.children;
        event.preventDefault();
        transfromEventHander(children, transformData, 'down')
        break;
      case "ArrowLeft":
        event.preventDefault();
        // const leftChildren = consoleRef.current.children;
        setEventCounts(['resultConsole', -1])
        transfromEventHander(null, transformData, 'up', 'left')
        break;
      case "ArrowUp":
        children = eventCounts[0] === 'resultFeature'  ? featureRef.current.children: consoleRef.current.children;
        event.preventDefault();
        transfromEventHander(children, transformData, 'up')
        break
    }
  }, [eventCounts, props.console, props.willSearch]);

  useEffect(() => {
    props.test && document.addEventListener('keydown', eventHander);
    return function() {
      return document.removeEventListener('keydown', eventHander)
    }
  }, [props.test, eventHander, eventCounts])


  return (
    <div
      className={classNames(styes.searchPanel, props.className)}
      style={props.style}
      onMouseEnter={props.onMouseEnter}
      onMouseLeave={props.onMouseLeave}
      onFocus={props.onFocusChange}
    >
      <div className={styes.container} ref={props.wrapperRef}>
        {props.value === '' && (
          <div className={styes.body} style={{ display: 'flex' }}>
            <div className={styes.flexItem}>
              {recentKeywords.length > 0 ? (
                <>
                  <h5 className={styes.historyTitle}>
                    最近搜索
                    <DelIcon onClick={handlerDelHistory} />
                  </h5>
                  <div className={styes.label}>
                    {(unique(recentKeywords, 'data') || []).map(item => (
                      // eslint-disable-next-line react/button-has-type
                      <button
                        className={styes.btn}
                        title={item.data}
                        key={item.data}
                        onClick={() => props.onWillSearch(item.data)}
                      >
                        {item.data}
                      </button>
                    ))}
                  </div>
                </>
              ) : null}

              <h5
                className={styes.historyTitle}
                style={{
                  margin: recentKeywords.length > 0 ? '16px 0px 0px' : '0',
                }}
              >
                最近访问的产品
              </h5>
              {recentProducts.length > 0 ? (
                (transformRecentProduct() || []).map(item => (
                  <a
                    title={item.name}
                    className={styes.historyHref}
                    key={item.name}
                    onClick={event => goProduct(event, item)}
                    onKeyDown={(event => console.log(event))}
                  >
                    <span className={styes.title}>{item.name}</span>
                    <span className={styes.featIn}>
                      <RightCircleOutlined />
                    </span>
                  </a>
                ))
              ) : (
                <div className={styes.empty}>无最近访问的产品</div>
              )}
            </div>
            <div className={styes.flexItem}>
              <div className={styes.title}>关注更多信息</div>
              <div className={styes.label}>
                <div className={styes.empty}>没有找到相关内容</div>
              </div>
            </div>
          </div>
        )}
        {props.value !== '' && (
          <>
            <div className={styes.body}>
              {transformWillSearch()}

              <div className={styes.features}>
                <div className={styes.flex}>
                  <h5 className={styes.title}>
                    产品入口({props.console.length})
                  </h5>
                  <div className={styes.feature} ref={consoleRef}>{transformConsole()}</div>
                </div>
                <div className={styes.flex}>
                  <h5 className={styes.title}>快捷操作</h5>
                  <div className={styes.feature} ref={featureRef}>{transformFeature()}</div>
                </div>
              </div>
            </div>
            {props.willSearch.length > 0 || props.console.length > 0 ? (
              <div className={styes.footer}>
                <span onClick={handlerMore}>查看全部结果</span>
              </div>
            ) : null}
          </>
        )}
      </div>
      <Modal
        visible={visible}
        triggerElRef={props.target}
        {...props}
        matchValue={matchValue}
        goFeature={goFeature}
        goProduct={goProduct}
      />
    </div>
  );
};

export default SearchPanel;
