import React, { useEffect, useState } from 'react';
import { useHistory, withRouter, RouteComponentProps } from 'react-router-dom';
import { useBookmark } from './useBookmark';
import * as R from 'ramda';
import {
  YBookmarkProps,
  Panes,
  BookmarkActionType,
  RouteState,
} from './bookmark.interface';
import { YRouterItem } from '@/application/application.interface';
import { TabsStyle, TabPaneStyle, EmptyStyle } from './styles';

//用户登陆次数
function Tab(props: YBookmarkProps & RouteComponentProps) {
  const history = useHistory();
  const { namePage } = useBookmark();
  const appState = props.state;
  const {
    router,
    projectId = '',
    number = 5,
    originProps,
    location,
    userId,
  } = props;

  /**
   * 筛选有权限的路由
   * @param path 路由地址
   * @param routeEle 权限路由
   */
  const checkRouter = (
    path: string,
    routeEle: YRouterItem[],
    parent: string = '',
  ): { path: string; name: string; parent: string } | undefined => {
    for (let i = 0; i < routeEle.length; i++) {
      const element = routeEle[i];
      if (element.path === path) {
        return {
          path: element.meta?.title || '',
          name: element.name || '',
          parent: parent,
        };
      }
      const child = element.children;
      if (child && Array.isArray(child)) {
        let routePath = checkRouter(path, child, element.name);
        if (routePath) return routePath;
      }
    }
  };
  let sessionKey = userId ? projectId + userId : projectId;
  let enterCount = sessionStorage.getItem('enterCount');
  let storagePanes: Panes[] = [];
  let storageActive: Panes = {
    path: '',
    name: '',
    search: '',
    active: true,
  };

  const jumpdefaultMenu = () => {
    if (
      typeof window !== 'undefined' &&
      location.pathname === '/' &&
      appState.defaultMenu?.path
    ) {
      let pathO = checkRouter(appState.defaultMenu?.path, router);
      if (pathO && pathO.path) {
        history.push(appState.defaultMenu?.path);
      }
    }
  };

  const judgeJumpCondition = () => {
    let newPanes = [...panes];
    const { state, pathname } = location;
    const pathObj = checkRouter(pathname, router);

    const conMap = new Map([
      ['invalidPath', !(pathObj && pathObj.path)],
      ['noPath', pathname === '/'],
      [
        'specialPath',
        state && (state as RouteState).hidden && !(state as RouteState).replace,
      ],
    ]);

    const hiddenCondition =
      conMap.get('invalidPath') ||
      conMap.get('noPath') ||
      conMap.get('specialPath');
    if (!hiddenCondition && pathname !== appState.pageName) {
      updatePanes(pathname, pathObj, state, newPanes);
    }
  };

  const updatePanes = (
    pathname: string,
    pathObj: { path: string; name: string; parent: string } | undefined,
    state: any,
    newPanes: any[],
  ) => {
    namePage({
      pageName: pathname || '',
      selectedMenu: pathObj ? [pathObj.name] : [''],
      openMenu: pathObj ? [pathObj.parent] : [''],
    });

    const panesObj = {
      path: pathname,
      name: pathObj ? pathObj.path : '',
      search: location.search,
      active: true,
    };
    if (!enterCount && userId) {
      if (panes.length === 0) {
        setPanes([panesObj]);
        setActiveKey(panesObj.path + panesObj.search);
        projectId &&
          sessionStorage.setItem(sessionKey, JSON.stringify([panesObj]));
      } else {
        history.push(activeKey);
      }
      sessionStorage.setItem('enterCount', '1');
    }

    if (state && (state as RouteState).replace) {
      let panesIndex: number = R.findIndex<any>(R.propEq<any>('active', true))(
        newPanes,
      );
      let pathIndex: number = R.findIndex<any>(
        R.propEq<any>('path', panesObj.path),
      )(newPanes);
      if (pathIndex !== -1) {
        newPanes[panesIndex].active = false;
        newPanes[pathIndex] = panesObj;
      } else {
        newPanes[panesIndex] = panesObj;
      }
    } else {
      //清除active
      newPanes = R.map((o) => ({ ...o, active: false }), newPanes);
      //添加新路由
      let panesIndex: number = R.findIndex<any>(
        R.propEq<any>('path', panesObj.path),
      )(newPanes);

      if (panesIndex === -1 && pathObj && pathObj.path) {
        if (newPanes.length === number) {
          newPanes.shift();
        }
        newPanes.push(panesObj);
      } else {
        newPanes[panesIndex].search = panesObj.search;
        newPanes[panesIndex].active = true;
      }
    }
    setActiveKey(panesObj.path + panesObj.search);
    setPanes(newPanes);
    projectId &&
      userId &&
      sessionStorage.setItem(sessionKey, JSON.stringify(newPanes));
  };

  if (projectId) {
    let validPanes: [] = JSON.parse(sessionStorage.getItem(sessionKey) || '[]');
    storagePanes = validPanes.filter((panesItem: any) => {
      let pathO = checkRouter(panesItem.path, router);
      return !!(pathO && pathO.path);
    });

    storagePanes.length !== 0 &&
      (storageActive = R.find<any>(R.propEq<any>('active', true))(
        storagePanes,
      ));
  }

  const [panes, setPanes] = useState<Panes[]>(storagePanes);
  const [activeKey, setActiveKey] = useState(
    storageActive.path + storageActive.search,
  );

  useEffect(() => {
    jumpdefaultMenu();
  }, [appState.defaultMenu]);

  useEffect(() => {
    if (typeof window !== 'undefined') {
      judgeJumpCondition();
    }
  }, [location, projectId]);

  const onChange = (activeKey: string) => {
    setActiveKey(activeKey);
    history.push(activeKey);
  };

  const onEdit = (
    targetKey:
      | string
      | React.MouseEvent<Element, MouseEvent>
      | React.KeyboardEvent<Element>,
    action: BookmarkActionType,
  ): void => {
    if (action === 'remove') remove(targetKey);
  };

  const remove = (
    targetKey:
      | string
      | React.MouseEvent<Element, MouseEvent>
      | React.KeyboardEvent<Element>,
  ) => {
    let lastIndex = 0;
    panes.forEach((pane, i) => {
      if (pane.path === targetKey) {
        lastIndex = i - 1;
      }
    });
    const filterPanes = panes.filter(
      (pane) => pane.path + pane.search !== targetKey,
    );
    const filterPanesActive = panes.filter(
      (pane) => pane.path + pane.search === targetKey,
    );
    if (filterPanes.length && activeKey === targetKey) {
      if (lastIndex >= 0) {
        setActiveKey(
          filterPanes[lastIndex].path + filterPanes[lastIndex].search,
        );
        history.push(
          filterPanes[lastIndex].path + filterPanes[lastIndex].search,
        );
      } else {
        setActiveKey(filterPanes[0].path + filterPanes[0].search);
        history.push(filterPanes[0].path + filterPanes[0].search);
      }
    }
    setPanes(filterPanes);
    if (filterPanesActive.length === 1 && filterPanesActive[0].active) {
      filterPanes[filterPanes.length - 1].active = true;
    }
    projectId &&
      sessionStorage.setItem(sessionKey, JSON.stringify(filterPanes));
  };

  return panes.length > 0 ? (
    <TabsStyle
      hideAdd
      onChange={onChange}
      activeKey={activeKey}
      type="editable-card"
      onEdit={onEdit}
      size="small"
      {...originProps}
    >
      {panes.map((pane) => (
        <TabPaneStyle
          tab={pane.name}
          key={pane.path + pane.search}
          closable={panes.length !== 1}
        />
      ))}
    </TabsStyle>
  ) : (
    <EmptyStyle />
  );
}

export default withRouter(Tab);
