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

import { publicationTypeEquivalent, StructId, buildHALApiUrl } from "../utils";
import { Notice, NoticeComponent } from "./Notice";
import { HALGroups, HALGroup, HALGroupComponent, HALNoticeContainer } from "./Group";
import { Status } from "../common/Status";
import { StatusComponent } from "./common/StatusComponent";

import paramImg from "../images/cog-solid.svg";
import gitlabImg from "../images/gitlab-logo.svg";
import spirhalImg from "../images/SPIRHAL.png";

export const NormContext = React.createContext<string>("default");

export interface SpirhalProps {
  researcherName?: string;
  idHal?: string;
  portal?: string;
  structId: StructId; // Identifiant du labo
  norm: string;
  adminLink?: string;
  noGrouping: boolean;
}

export interface SpirhalStructureProps {
  portal?: string;
  structId: StructId; // Identifiant du labo
  norm: string;
  limit: number;
  adminLink?: string;
  noGrouping: boolean;
}

const SpirHALContainer = styled.div`
  display: flex;
`;
const TooltipText = styled.span`
  visibility: hidden;
  width: 220px;
  background-color: dimgray;
  color: white;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;

  position: absolute;
  z-index: 1;
`;
const Tooltip = styled.div`
  position: relative;
  display: inline-block;

  &:hover ${TooltipText} {
    visibility: visible;
  }
`;

const LeftTooltip = styled(Tooltip)`
  height: 40px;
  ${TooltipText} {
    top: -5px;
    right: 105%;
  }
`;

const TopTooltip = styled(Tooltip)`
  display: flex;
  margin-top: 2em;
  ${TooltipText} {
    bottom: 100%;
    left: 50%;
    margin-left: -110px;
  }
`;
const CenteredLink = styled.a`
  margin: auto;
`;

const FontSize12Paragraph = styled.p`
  font-size: 12px;
`;

export const AdminLinkButton: React.FC<{ adminLink: string | undefined; norm: string }> = ({ adminLink, norm }) => {
  if (adminLink === undefined) {
    return <></>;
  }
  return (
    <LeftTooltip className="spirhal-admin-link">
      <a href={adminLink}>
        <img width="50px" src={paramImg} />
      </a>
      <TooltipText>
        <p>Administration de SpirHAL</p>
        <FontSize12Paragraph>
          Les publications de cette rubriques sont affichées avec la norme {norm}
        </FontSize12Paragraph>
      </TooltipText>
    </LeftTooltip>
  );
};

export const LogoSpirhal: React.FC = () => {
  return (
    <TopTooltip className="spirhal-logo">
      <CenteredLink href="https://framagit.org/Murloc6/Spirhal">
        <img width="120px" src={spirhalImg} />
      </CenteredLink>
      <TooltipText>
        <p>
          Documentation et code source <img width="20px" src={gitlabImg} />
        </p>
      </TooltipText>
    </TopTooltip>
  );
};

export function useHALGroups(
  portal: string,
  structId: StructId,
  limit: number,
  researcherName?: string,
  idHal?: string,
  baseUrl?: string
): [Status, HALGroup[]] {
  const [groups, setGroups] = React.useState<HALGroup[]>([]);
  const [status, setStatus] = React.useState<Status>(Status.LOADING);

  React.useEffect(() => {
    const url = buildHALApiUrl(portal, structId, limit, false, researcherName, idHal, baseUrl);
    setStatus(Status.LOADING);
    fetch(url)
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        if (!("grouped" in data)) {
          throw new Error(`Error while fetching groups: ${data.error.msg}`);
        }

        const groups = [];
        for (const group of data.grouped.docType_s.groups) {
          const name = publicationTypeEquivalent.get(group.groupValue) ?? group.groupValue;
          const notices: Notice[] = [];
          for (const notice of group.doclist.docs) {
            notices.push(notice);
          }
          groups.push({ groupId: group.groupValue, name, notices });
        }
        setGroups(groups);
        setStatus(Status.OK);
      })
      .catch((e) => {
        console.error(e);
        setStatus(Status.ERROR);
      });
  }, [researcherName, idHal, portal, structId]);
  return [status, groups];
}

function useHALNoGroups(
  portal: string,
  structId: StructId,
  limit: number,
  researcherName?: string,
  idHal?: string,
  baseUrl?: string
): [Status, Notice[]] {
  const [notices, setNotices] = React.useState<Notice[]>([]);
  const [status, setStatus] = React.useState<Status>(Status.LOADING);

  React.useEffect(() => {
    const url = buildHALApiUrl(portal, structId, limit, true, researcherName, idHal, baseUrl);
    fetch(url)
      .then((response) => {
        return response.json();
      })
      .then((data) => {
        setNotices(data.response.docs);
        setStatus(Status.OK);
      })
      .catch((e) => {
        console.error(e);
        setStatus(Status.ERROR);
      });
  }, [researcherName, idHal, portal, structId]);
  return [status, notices];
}

const NestedStyle = styled.div`
  & ul li > ul li,
  & ul li {
    list-style: none;
    padding-bottom: 0;
  }
  & ul {
    padding-left: 0;
  }
  & ul li ul li::before {
    content: none;
  }
  & ul li {
    padding-bottom: 1rem;
  }
`;

export const SpirhalGroupNotices: React.FC<{
  norm: string;
  status: Status;
  groups: HALGroup[];
  adminLink?: string;
}> = ({ norm, status, groups, adminLink }) => {
  return (
    <NestedStyle className="spirhal">
      <NormContext.Provider value={norm}>
        <StatusComponent status={status}>
          <SpirHALContainer>
            <HALGroups groups={groups} />
            <AdminLinkButton adminLink={adminLink} norm={norm} />
          </SpirHALContainer>
        </StatusComponent>
        <LogoSpirhal />
      </NormContext.Provider>
    </NestedStyle>
  );
};

export const SpirhalNotices: React.FC<{
  norm: string;
  status: Status;
  notices: Notice[];
  adminLink?: string;
}> = ({ norm, status, notices, adminLink }) => {
  return (
    <NestedStyle className="spirhal">
      <NormContext.Provider value={norm}>
        <StatusComponent status={status}>
          <SpirHALContainer>
            <HALGroupComponent className="spirhal-group-list">
              {notices.map((notice) => (
                <HALNoticeContainer key={notice.docid} className="spirhal-group-list-element">
                  <NoticeComponent {...notice} />
                </HALNoticeContainer>
              ))}
            </HALGroupComponent>
            <AdminLinkButton adminLink={adminLink} norm={norm} />
          </SpirHALContainer>
        </StatusComponent>
        <LogoSpirhal />
      </NormContext.Provider>
    </NestedStyle>
  );
};

export const SpirhalPersonWithGroups: React.FC<SpirhalProps> = ({
  researcherName,
  idHal,
  portal,
  structId,
  norm,
  adminLink,
}) => {
  const [status, groups] = useHALGroups(portal ?? "", structId, 10000, researcherName, idHal);
  return <SpirhalGroupNotices norm={norm} status={status} groups={groups} adminLink={adminLink} />;
};

export const SpirhalStructureWithGroups: React.FC<SpirhalStructureProps> = ({
  portal,
  structId,
  norm,
  limit,
  adminLink,
}) => {
  const [status, groups] = useHALGroups(portal ?? "", structId, limit);
  return <SpirhalGroupNotices norm={norm} status={status} groups={groups} adminLink={adminLink} />;
};

export const SpirhalPersonNoGroups: React.FC<SpirhalProps> = ({
  researcherName,
  idHal,
  portal,
  structId,
  norm,
  adminLink,
}) => {
  const [status, notices] = useHALNoGroups(portal ?? "", structId, 10000, researcherName, idHal);
  return <SpirhalNotices norm={norm} status={status} notices={notices} adminLink={adminLink} />;
};

export const SpirhalStructureNoGroups: React.FC<SpirhalStructureProps> = ({
  portal,
  structId,
  norm,
  limit,
  adminLink,
}) => {
  const [status, notices] = useHALNoGroups(portal ?? "", structId, limit);
  return <SpirhalNotices norm={norm} status={status} notices={notices} adminLink={adminLink} />;
};

export const Spirhal: React.FC<SpirhalProps> = (props) => {
  if (props.noGrouping) {
    return <SpirhalPersonNoGroups {...props} />;
  }
  return <SpirhalPersonWithGroups {...props} />;
};

export const SpirhalStructure: React.FC<SpirhalStructureProps> = (props) => {
  if (props.noGrouping) {
    return <SpirhalStructureNoGroups {...props} />;
  }
  return <SpirhalStructureWithGroups {...props} />;
};
