import React from 'react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import { useVersions, useLatestVersion, useActiveDocContext } from '@theme/hooks/useDocs';
import clsx from 'clsx';
import Link from '@theme/Link';
import useBaseUrl from '@docusaurus/useBaseUrl';

function NavLink({
  activeBasePath,
  activeBaseRegex,
  to,
  href,
  label,
  activeClassName = '',
  prependBaseUrlToHref,
  ...props
}) {
  // TODO all this seems hacky
  // {to: 'version'} should probably be forbidden, in favor of {to: '/version'}
  const toUrl = useBaseUrl(to);
  const activeBaseUrl = useBaseUrl(activeBasePath);
  const normalizedHref = useBaseUrl(href, {
    forcePrependBaseUrl: true,
  });
  return (
    <Link
      {...(href
        ? {
            target: '_blank',
            rel: 'noopener noreferrer',
            href: prependBaseUrlToHref ? normalizedHref : href,
          }
        : {
            isNavLink: true,
            activeClassName,
            to: toUrl,
            ...(activeBasePath || activeBaseRegex
              ? {
                  isActive: (_match, location) =>
                    activeBaseRegex
                      ? new RegExp(activeBaseRegex).test(location.pathname)
                      : location.pathname.startsWith(activeBaseUrl),
                }
              : null),
          })}
      {...props}
    >
      {label}
    </Link>
  );
}

function NavItemDesktop({ items, position, className, ...props }) {
  const navLinkClassNames = (extraClassName, isDropdownItem = false) =>
    clsx(
      {
        '': !isDropdownItem,
        dropdown__link: isDropdownItem,
      },
      extraClassName,
    );

  if (!items) {
    return <NavLink className={navLinkClassNames(className)} {...props} />;
  }

  return (
    <div className="dropdown dropdown--hoverable">
      <NavLink
        className={navLinkClassNames(className)}
        {...props}
        onClick={props.to ? undefined : (e) => e.preventDefault()}
        onKeyDown={(e) => {
          function toggle() {
            e.target.parentNode.classList.toggle('dropdown--show');
          }

          if (e.key === 'Enter' && !props.to) {
            toggle();
          }

          if (e.key === 'Tab') {
            toggle();
          }
        }}
      >
        {props.label}
      </NavLink>
      <ul className="dropdown__menu">
        {items.map(({ className: childItemClassName, ...childItemProps }, i) => (
          <li key={i}>
            <NavLink
              activeClassName="dropdown__link--active"
              className={navLinkClassNames(childItemClassName, true)}
              {...childItemProps}
            />
          </li>
        ))}
      </ul>
    </div>
  );
}

const getVersionMainDoc = (version) => version.docs.find((doc) => doc.id === version.mainDocId);

export default function VersionDropdown({ mobile, docsPluginId, ...props }) {
  const {
    siteConfig: { customFields },
  } = useDocusaurusContext();
  const activeDocContext = useActiveDocContext(docsPluginId);
  const versions = useVersions(docsPluginId);
  const latestVersion = useLatestVersion(docsPluginId);

  function getItems() {
    return versions
      .map((version) => {
        // We try to link to the same doc, in another version
        // When not possible, fallback to the "main doc" of the version
        const versionDoc = activeDocContext?.alternateDocVersions[version.name] || getVersionMainDoc(version);
        return {
          isNavLink: true,
          label: version.label,
          to: versionDoc.path,
          isActive: () => version === activeDocContext?.activeVersion,
        };
      })
      .concat(customFields.legacyVersions || []);
  }

  const dropdownVersion = activeDocContext.activeVersion ?? latestVersion; // Mobile is handled a bit differently
  const dropdownLabel = mobile ? 'Versions' : dropdownVersion.label;
  const dropdownTo = mobile ? undefined : getVersionMainDoc(dropdownVersion).path;

  return (
    <NavItemDesktop items={getItems()} {...props} label={dropdownLabel} to={dropdownTo}></NavItemDesktop>
  );
}
