import { useState, useRef, useEffect } from "react";
import PropTypes from "prop-types";

import { setSideNavExpanded, isSideNavExpanded } from "../helpers";
import { LevelOneContent } from "../Content";
import DynamicContent from "./DynamicContent";
import { NavLinkToggle } from "../Links";
import defaultMarkup from "./default-markup";

// TODO: For an SSR version of the SideNavUI we would need to have
// the whole SideNav markup render on the server. Less reliance on
// window and document.
// We can have an API created where we send it certain parameters
// like items. All of the markup is then returned. The SideNav can
// just render the markup provided by the Frontend Server.
// The only code left behind would be triggers to respond to
// toggling the sidenav's expand state
// Things to consider when implmenting an SSR version:
// 1. any buttons will need event listeners to trigger actions.
// 2. we need a feature flag to roll this out since it will be
//    a breaking change.
// 3. we may want to consider creating a web component since they
//    are server friendly. https://css-tricks.com/using-web-components-with-next-or-any-ssr-framework/
// 4. If you do use web components be sure to come up with a
//    strategy to register the web component before React loads
//    the markup on the page. Then the web component renders
//    immediately.
const SideNavUI = ({
  config = {},
  isAltStyle = false,
  isExpanded,
  items = [],
  onCollapsed = () => {},
  onExpanded = () => {},
}) => {
  const isExpandedPropSet = isExpanded !== undefined;
  const [isExpandedState, setIsExpandedState] = useState(() => {
    if (isExpandedPropSet) {
      return isExpanded;
    }
    return isSideNavExpanded(window.document);
  });
  const [sideNavContent, setSideNavContent] = useState("<nav></nav>");

  const collapseRef = useRef(null);

  const expand = () => {
    setSideNavExpanded(window.document, "true");
    setIsExpandedState(true);
    if (onExpanded) {
      onExpanded();
    }
  };

  const collapse = () => {
    setSideNavExpanded(window.document, "false");
    setIsExpandedState(false);
    if (onCollapsed) {
      onCollapsed();
    }
  };

  const toggleExpanded = () => {
    isExpandedState ? collapse() : expand();
  };

  useEffect(() => {
    // some applications use the isExpanded prop instead of reading the cookie
    // this will ensure the application ignores the cookie
    if (isExpandedPropSet) {
      setIsExpandedState(isExpanded);
    } else {
      isSideNavExpanded(window.document);
    }
  }, [isExpanded, isExpandedPropSet]);

  useEffect(() => {
    const path = window.location.pathname;
    document.cookie = `current_path=${path}; Path=/;`;
    isSideNavExpanded(window.document);
    let cancelRequest = false;
    const { origin } = window.location;
    const isRunningLocally = origin.includes("localhost");
    let sideNavMenuItems;

    async function getSideNavConfig() {
      try {
        const response = await fetch(`${origin}/config/side-navigation`);
        const data = await response.json();
        sideNavMenuItems = data.markup;
      } catch (error) {
        if (isRunningLocally) {
          sideNavMenuItems = defaultMarkup;
        } else {
          sideNavMenuItems = "<nav></nav>";
        }
      }
      if (!cancelRequest) {
        setSideNavContent(sideNavMenuItems);
      }
    }
    getSideNavConfig();
    return () => {
      cancelRequest = true;
    };
  }, [location.pathname]);

  const content = !items?.length ? (
    <LevelOneContent
      levelOneContent={sideNavContent}
      isExpanded={isExpandedState}
      config={config}
    />
  ) : (
    <DynamicContent
      contentItems={items}
      className={"sidebar-content" + (isAltStyle ? " alt-style" : "")}
      config={config}
      isExpandedState={isExpandedState}
    />
  );

  return (
    <aside
      id="qppSidebar"
      tabIndex="-1"
      className={`${isExpandedState ? "sidebar" : "sidebar closed"} sidebar-${
        config.navClassName
      }`}
    >
      {content}
      <NavLinkToggle
        isAltStyle={isAltStyle}
        collapseRef={collapseRef}
        isExpanded={isExpandedState}
        onClick={toggleExpanded}
      />
    </aside>
  );
};

SideNavUI.propTypes = {
  config: PropTypes.object,
  isAltStyle: PropTypes.bool,
  isExpanded: PropTypes.bool,
  items: PropTypes.object,
  onCollapsed: PropTypes.func,
  onExpanded: PropTypes.func,
};

export default SideNavUI;
