import React, { useState, useCallback, useEffect, useRef, useContext } from 'react';
import clsx from 'clsx';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import Link from '@theme/Link';
import isInternalUrl from '@docusaurus/isInternalUrl';
import VersionDropdown from '@theme/VersionDropdown';
import SearchBar from '@theme/SearchBar';
import SidebarContext from '@theme/_contexts/SidebarContext';

function usePrevious(value) {
  const ref = useRef(value);
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
} // Compare the 2 paths, ignoring trailing /

const isSamePath = (path1, path2) => {
  const normalize = (str) => (str.endsWith('/') ? str : `${str}/`);

  return normalize(path1) === normalize(path2);
};

const isActiveSidebarItem = (item, activePath) => {
  if (item.type === 'link') {
    return isSamePath(item.href, activePath);
  }

  if (item.type === 'category') {
    return item.items.some((subItem) => isActiveSidebarItem(subItem, activePath));
  }

  return false;
};

function SidebarItemCategory({ item, level, onItemClick, collapsible, activePath, ...props }) {
  const { items, label } = item;
  const isActive = isActiveSidebarItem(item, activePath);
  const wasActive = usePrevious(isActive); // active categories are always initialized as expanded
  // the default (item.collapsed) is only used for non-active categories

  const [collapsed, setCollapsed] = useState(() => {
    if (!collapsible) {
      return false;
    }

    return isActive ? false : item.collapsed;
  }); // If we navigate to a category, it should automatically expand itself

  useEffect(() => {
    const justBecameActive = isActive && !wasActive;

    if (justBecameActive && collapsed) {
      setCollapsed(false);
    }
  }, [isActive, wasActive, collapsed]);
  const handleItemClick = useCallback(
    (e) => {
      e.preventDefault();
      setCollapsed((state) => !state);
    },
    [setCollapsed],
  );

  if (items.length === 0) {
    return null;
  }

  return (
    <li
      className={clsx('menu__list-item', `level--${level}`, {
        'menu__list-item--collapsed': collapsed,
      })}
      key={label}
    >
      <a
        className={clsx('menu__link', `level--${level}`, {
          'menu__link--sublist': collapsible,
          'menu__link--active': collapsible && isActive,
          menu__link__text: !collapsible,
        })}
        onClick={collapsible ? handleItemClick : undefined}
        href={collapsible ? '#!' : undefined}
        {...props}
      >
        {label}
      </a>
      <ul className={clsx('menu__list', `level--${level}`)}>
        {items.map((childItem) => (
          <SidebarItem
            tabIndex={collapsed ? '-1' : '0'}
            key={childItem.label}
            item={childItem}
            level={level}
            onItemClick={onItemClick}
            collapsible={collapsible}
            activePath={activePath}
          />
        ))}
      </ul>
    </li>
  );
}

function SidebarItemLink({ item, level, onItemClick, activePath, collapsible: _collapsible, ...props }) {
  const { href, label } = item;
  const isActive = isActiveSidebarItem(item, activePath);
  return (
    <li className={clsx('menu__list-item', `level--${level}`)} key={label}>
      <Link
        className={clsx('menu__link', `level--${level}`, {
          'menu__link--active': isActive,
        })}
        to={href}
        {...(isInternalUrl(href)
          ? {
              isNavLink: true,
              exact: true,
              onClick: onItemClick,
            }
          : {
              target: '_blank',
              rel: 'noreferrer noopener',
            })}
        {...props}
      >
        {label}
      </Link>
    </li>
  );
}

function SidebarItem({ item, level = 0, ...rest }) {
  switch (item.type) {
    case 'category':
      return <SidebarItemCategory {...{ item, ...rest, level: level + 1 }} />;

    case 'link':
    default:
      return <SidebarItemLink {...{ item, ...rest, level: level + 1 }} />;
  }
}

function SidebarMenu({ path, sidebar, sidebarCollapsible = true }) {
  const { hideSidebar } = useContext(SidebarContext);

  return (
    <nav className="menu">
      <ul className="menu__list level--0">
        {sidebar.map((item) => (
          <SidebarItem
            key={item.label}
            item={item}
            onItemClick={(e) => {
              e.target.blur();
              hideSidebar();
            }}
            collapsible={sidebarCollapsible}
            activePath={path}
          />
        ))}
      </ul>
    </nav>
  );
}

export function SidebarToggle({ onToggle }) {
  return (
    <div
      aria-label="Sidebar Navigation Toggle"
      className="sidebar-toggle d-block l__d-none mr-s"
      role="button"
      tabIndex={0}
      onClick={onToggle}
      onKeyDown={onToggle}
    >
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="30"
        height="30"
        viewBox="0 0 30 30"
        role="img"
        focusable="false"
      >
        <title>Menu</title>
        <path
          stroke="currentColor"
          strokeLinecap="round"
          strokeMiterlimit="10"
          strokeWidth="2"
          d="M4 7h22M4 15h22M4 23h22"
        />
      </svg>
    </div>
  );
}

function DocSidebar({ path, sidebar, sidebarCollapsible = true }) {
  const docusaurusContext = useDocusaurusContext();
  const {
    siteConfig: { title, tagline, customFields },
  } = docusaurusContext;
  const { sidebarShown, hideSidebar } = useContext(SidebarContext);
  const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);

  /*
  VERSIONs debugging

  const versions = useVersions();
  const latestVersion = useLatestVersion();
  const { activeDoc, activeVersion, alternateDocVersions } = useActiveDocContext();
  if (isClient) {
    console.table(docusaurusContext);
    console.log(...versions);
    console.table({ latestVersion, activeVersion, activeDoc, alternateDocVersions });
    console.table(versionMetadata);
  }
  */

  const { redocPages = [] } = customFields;
  const localSidebar = sidebar.slice();
  if (redocPages.length) {
    localSidebar.push({
      collapsed: true,
      type: 'category',
      label: 'API Spec Pages',
      items: redocPages.map(({ title, slug }) => ({
        type: 'link',
        label: title,
        href: useBaseUrl(slug),
      })),
    });
  }

  return (
    <>
      <div
        role="presentation"
        className={clsx('docpage-sidebar-bg', { open: sidebarShown })}
        onClick={hideSidebar}
      />
      <div aria-expanded={sidebarShown} className="docpage-sidebar sticky-sidebar stack-s py-s">
        <SearchBar handleSearchBarToggle={setIsSearchBarExpanded} isSearchBarExpanded={isSearchBarExpanded} />
        <SidebarMenu sidebar={localSidebar} path={path} sidebarCollapsible={sidebarCollapsible} />
        <header className="docpage-sidebar-banner pt-s pr-xs mr-neg-xs stack-m">
          <VersionDropdown />
          <div className="prose-sans-xs">
            <div className="product-avatar">
              <div className="avatar">
                <img
                  src={useBaseUrl(customFields.productLogo)}
                  alt="Logo of the Rasa Open Source project"
                  className="avatar"
                />
              </div>
              <h2 className="heading f-sans-s">{title}</h2>
            </div>
            <p>{tagline}</p>
          </div>
        </header>
        <footer className="stack-s"></footer>
      </div>
    </>
  );
}

export default DocSidebar;
