import { LocationState, Path } from 'history';
import React, { Suspense, useEffect } from 'react';
import { Route, Switch, useHistory } from 'react-router';

import RouterWrapNotFound from '@/Render/components/NotFound';
import RouterWrapSpin from '@/Render/components/Spin';

interface RouteChangePropsTypes {
  from: string;
  to: string;
}
interface RouteChangeProps {
  onChange?: (from: string, to: string, next: (path: Path, state?: LocationState) => void) => void;
}

const RouteBeforEachLocation: RouteChangePropsTypes = { from: '/', to: '/' };
let RouteBeforEachLocationCache: string = JSON.stringify(RouteBeforEachLocation);

/**
 * @param props beforEach
 * @Message 不阻塞渲染 异步
 */
export const BaseRouteChange: React.FC<RouteChangeProps> = (props) => {
  const { children } = props;
  const history = useHistory();
  const location = history.location;

  const getRouteBeforEachLocationCacheString = () => {
    return JSON.stringify(RouteBeforEachLocation);
  };

  /** 收集路由变更信息 */
  useEffect(() => {
    RouteBeforEachLocation.to = location.pathname;
    return () => {
      RouteBeforEachLocation.from = location.pathname;
    };
  }, [location.pathname]);

  /**
   * @路由变更处理
   */
  useEffect(() => {
    /**  */
    if (!props.onChange) return;
    if (Reflect.toString.call(props.onChange) !== '[object Function]' && Reflect.toString.call(props.onChange) !== '[object AsyncFunction]') {
      throw new Error('BaseRouteChange 参数不合法' + Reflect.toString.call(props.onChange));
    }
    /** 防重 */
    if (RouteBeforEachLocationCache === getRouteBeforEachLocationCacheString()) return;
    RouteBeforEachLocationCache = getRouteBeforEachLocationCacheString();
    props.onChange(RouteBeforEachLocation.from, RouteBeforEachLocation.to, history.push);
  }, [getRouteBeforEachLocationCacheString()]);

  return <React.Fragment>{children}</React.Fragment>;
};

/**
 * @private
 *
 * @全局路由包装组件
 */
type PackingWithAuthOnChange = (from: string, to: string, next: (path: Path, state?: LocationState) => void) => void;
export const PackingWithAuth: React.FC<{ onChange?: PackingWithAuthOnChange }> = ({ children, onChange }) => {
  const _onChange = (from: string, to: string, next: (path: Path, state?: LocationState) => void) => {
    /** if ('登录状态失效') { message.success('登录状态失效,请重新登录'); next('/login') } */
  };
  return (
    <BaseRouteChange onChange={onChange || _onChange}>
      <Suspense fallback={<RouterWrapSpin />}>
        <Switch>
          {children}
          <Route path="*" component={RouterWrapNotFound}></Route>
        </Switch>
      </Suspense>
    </BaseRouteChange>
  );
};