import React, { useContext, useState, MouseEvent, ReactNode, FC, useEffect } from 'react';

import classNames from 'classnames';
import { NavigationContext } from '../../context';
import NewBadge from '../../../new-badge';

import { Secondary } from './components';
import { ConfigContext } from '../../../config-provider';

interface ItemURLDetails {
  path: string;
  exact?: boolean;
  disabled?: boolean;
  excludePaths?: string[];
}

export interface SubNavigationItem extends ItemURLDetails {
  path: string;
  name: string;
  badge?: ReactNode;
  onClick?(): void;
}

interface SecondaryAction {
  path: string;
  icon: React.ReactNode;
}

export interface ItemProps extends ItemURLDetails {
  icon?: React.ReactNode;
  badge?: ReactNode;
  name?: string;
  subNavigationItems?: SubNavigationItem[];
  secondaryAction?: SecondaryAction;
  onClick?(): void;
  selected?: boolean;
}

enum MatchState {
  MatchUrl,
  NoMatch,
  Excluded,
}

function normalizePathname(pathname: string) {
  const barePathname = pathname.split('?')[0].split('#')[0];
  return barePathname.endsWith('/') ? barePathname : `${barePathname}/`;
}

function safeEqual(location: string, path: string) {
  return normalizePathname(location) === normalizePathname(path);
}

function safeStartsWith(location: string, path: string) {
  return normalizePathname(location).startsWith(normalizePathname(path));
}

function matchStateForItem({ path, exact, excludePaths }: ItemURLDetails, location: string) {
  if (path == null) {
    return MatchState.NoMatch;
  }

  if (excludePaths && excludePaths.some(excludePath => safeStartsWith(location, excludePath))) {
    return MatchState.Excluded;
  }

  const matchesUrl = exact ? safeEqual(location, path) : safeStartsWith(location, path);
  return matchesUrl ? MatchState.MatchUrl : MatchState.NoMatch;
}

export const Item: FC<ItemProps> = props => {
  const {
    path,
    icon,
    name,
    subNavigationItems = [],
    excludePaths,
    secondaryAction,
    disabled,
    onClick,
    badge,
    exact,
  } = props;
  const { location, menuItemRender } = useContext(NavigationContext);
  const [expanded, setExpanded] = useState(false);
  const { getPrefixCls } = useContext(ConfigContext);

  const prefixCls = getPrefixCls('navigation');

  useEffect(() => {
    if (expanded) {
      setExpanded(false);
    }
  }, [expanded]);

  // 动态小圆点
  // const indicatorMarkup = (
  //   <span className="Indicator">
  //     <Indicator pulse />
  //   </span>
  // ) : null;

  const iconMarkup = icon ? <div className={`${prefixCls}-icon`}>{icon}</div> : null;

  let badgeMarkup: ReactNode = null;
  if (typeof badge === 'string') {
    badgeMarkup = <NewBadge>{badge}</NewBadge>;
  } else {
    badgeMarkup = badge;
  }

  const wrappedBadgeMarkup =
    badgeMarkup == null ? null : <div className={`${prefixCls}-badge`}>{badgeMarkup}</div>;

  function getClickHandler(click: ItemProps['onClick']) {
    return (event: MouseEvent<HTMLElement>) => {
      const { currentTarget } = event;

      if (currentTarget.getAttribute('href') === location) {
        event.preventDefault();
      }

      if (subNavigationItems && subNavigationItems.length > 0) {
        event.preventDefault();
        setExpanded(!expanded);
      }

      if (click) {
        click();
      }
    };
  }

  const matchState = matchStateForItem({ path, exact, excludePaths }, location);

  const matchingSubNavigationItems = subNavigationItems.filter(item => {
    const subMatchState = matchStateForItem(item, location);
    return subMatchState === MatchState.MatchUrl;
  });

  const childIsActive = matchingSubNavigationItems.length > 0;

  const selected =
    props.selected !== undefined ? props.selected : matchState === MatchState.MatchUrl;

  const showExpanded = selected || expanded || childIsActive;

  const itemClassName = classNames({
    [`${prefixCls}-item`]: true,
    [`${prefixCls}-item-disabled`]: disabled,
    [`${prefixCls}-item-selected`]: selected && subNavigationItems.length === 0,
    [`${prefixCls}-sub-navigation-active`]: showExpanded,
  });

  const itemContentMarkup = (
    <>
      {iconMarkup}
      <span className={`${prefixCls}-text`}>
        {name}
        {/* {indicatorMarkup} */}
      </span>
      {subNavigationItems.length > 0 && (
        <svg
          xmlns="http://www.w3.org/2000/svg"
          width="6"
          height="10"
          viewBox="0 0 6 10"
          className={`${prefixCls}-arrow`}
          style={{ transform: showExpanded ? 'rotate(-90deg)' : undefined }}
        >
          <path d="M2.21855 5.00001L5.51855 8.30001L4.57589 9.24268L0.333221 5.00001L4.57589 0.75734L5.51855 1.70001L2.21855 5.00001Z" />
        </svg>
      )}
      {wrappedBadgeMarkup}
    </>
  );

  if (path == null) {
    const className = classNames({
      [`${prefixCls}-item`]: true,
      [`${prefixCls}-item-disabled`]: disabled,
    });

    return (
      <li className={`${prefixCls}-list-item`}>
        <button
          type="button"
          className={className}
          disabled={disabled}
          onClick={getClickHandler(onClick)}
        >
          {itemContentMarkup}
        </button>
      </li>
    );
  }

  const secondaryActionMarkup = secondaryAction && (
    <div className={`${prefixCls}-secondary-action`}>{secondaryAction.icon}</div>
  );

  let secondaryNavigationMarkup: ReactNode = null;

  if (subNavigationItems.length > 0) {
    const SecondaryNavigationClassName = classNames({
      [`${prefixCls}-secondary-navigation`]: true,
      [`${prefixCls}-is-expanded`]: showExpanded,
      [`${prefixCls}-secondary-navigation-no-icon`]: !icon,
    });

    secondaryNavigationMarkup = (
      <div className={SecondaryNavigationClassName}>
        <Secondary expanded={showExpanded}>
          {subNavigationItems.map(item => {
            const { name: itemName, ...rest } = item;
            return <Item {...rest} key={itemName} name={itemName} onClick={item.onClick} />;
          })}
        </Secondary>
      </div>
    );
  }

  const className = classNames({
    [`${prefixCls}-list-item`]: true,
    [`${prefixCls}-list-item-has-action`]: secondaryAction,
  });

  return (
    <li className={className}>
      <div className={`${prefixCls}-item-wrapper`}>
        {menuItemRender ? (
          menuItemRender(
            { className: itemClassName, onClick: getClickHandler(onClick) },
            props,
            itemContentMarkup,
          )
        ) : (
          <a className={itemClassName} onClick={getClickHandler(onClick)}>
            {itemContentMarkup}
          </a>
        )}
        {secondaryActionMarkup}
      </div>
      {secondaryNavigationMarkup}
    </li>
  );
};
