import * as React from "react";
import styled from "styled-components";

import { Notice, NoticeComponent } from "./Notice";
import * as EHESS from "./norms/EHESS/EHESS";
import * as APA from "./norms/APA/APA";
import * as MLA from "./norms/MLA/MLA";
import { publicationTypeEquivalent, groupOrder } from "../utils";

const HALGroupsComponent = styled.ul`
  margin: auto;
  padding: 0;
`;

export const HALGroupComponent = styled.ul`
  list-style: none;
  padding: 0;
`;

export const HALNoticeContainer = styled.li`
  &:not(:last-of-type) {
    padding-bottom: 1rem;
  }
  &:last-of-type {
    margin-bottom: 1rem;
  }
`;

export const normRenderedGroups: { [key: string]: string[] } = {
  EHESS: EHESS.renderedGroups,
  APA: APA.renderedGroups,
  MLA: MLA.renderedGroups,
};

export interface HALGroup {
  groupId: string;
  name: string;
  notices: Notice[];
}

const EmptyGroups = () => <span>Aucun groupe de notices présent sur HAL</span>;

export const GroupComponent: React.FunctionComponent<HALGroup> = ({ name, notices }) => {
  const [seeAll, setSeeAll] = React.useState<boolean>(notices.length < 3);

  const noticesToRender = seeAll ? notices : notices.slice(0, 3);

  return (
    <li className="spirhal-group" id={"spirhal-group-id-" + name}>
      <h2 className="spirhal-group-title">{name}</h2>
      <HALGroupComponent className="spirhal-group-list">
        {noticesToRender.map((notice: Notice, i: number) => (
          <HALNoticeContainer key={i} className="spirhal-group-list-element">
            <NoticeComponent {...notice} />
          </HALNoticeContainer>
        ))}
        {!seeAll ? (
          <a
            className="spirhal-see-more"
            href="#"
            onClick={() => {
              setSeeAll(true);
              setTimeout(() => document.getElementById("spirhal-group-id-" + name)!.scrollIntoView(), 100);
            }}
          >
            Voir plus...
          </a>
        ) : (
          seeAll &&
          notices.length > 3 && (
            <a
              className="spirhal-see-more"
              href="#"
              onClick={() => {
                setSeeAll(false);
                setTimeout(() => document.getElementById("spirhal-group-id-" + name)!.scrollIntoView(), 100);
              }}
            >
              Voir moins...
            </a>
          )
        )}
      </HALGroupComponent>
    </li>
  );
};

export function useFilteredHalGroups(groups: HALGroup[]) {
  /* In the HAL Api, notices with the docType_s "OTHER" have an extra parameter
   *  otherType_s which take the following values:
   * - 0 : no type specified
   * - 1 : Article de Blog
   * - 2 : Compte-rendu d'ouvrage et note de lecture
   * - 3 : Notice d'encyclopédie ou de dictionnaire
   * - 4 : Traduction
   */

  const otherTypeConsidered = ["1", "2", "3", "4"];

  const allOtherNotices: Notice[] = groups
    .filter((group) => group.groupId === "OTHER")
    .map((group) => group.notices)
    .flat();
  let newGroups: { [key: string]: HALGroup } = {};
  allOtherNotices.map((notice) => {
    let newGroup = "OTHER";
    if (notice.otherType_s !== undefined && notice.otherType_s in otherTypeConsidered) {
      newGroup = `OTHER${notice.otherType_s}`;
    }

    if (!(newGroup in newGroups)) {
      newGroups[newGroup] = {
        groupId: newGroup,
        name: publicationTypeEquivalent.get(newGroup)!, // We sure it is defined
        notices: [],
      };
    }
    newGroups[newGroup].notices.push(notice);
  });
  return groups
    .filter((group) => group.groupId !== "OTHER")
    .concat(Object.values(newGroups))
    .sort((g1, g2) => groupOrder.indexOf(g1.groupId) - groupOrder.indexOf(g2.groupId));
}

export const HALGroups: React.FC<{ groups: HALGroup[] }> = ({ groups }) => {
  if (groups.length === 0) {
    return <EmptyGroups />;
  }

  const filteredGroups = useFilteredHalGroups(groups);

  return (
    <>
      <HALGroupsComponent className="spirhal-groups">
        {filteredGroups.map((group, i) => (
          <GroupComponent key={i} {...group} />
        ))}
      </HALGroupsComponent>
    </>
  );
};
