import { AxiosResponse } from "axios";
import { useHTTP } from "hooks";
import { pond } from "protobuf-ts/pond";
import { useGlobalState } from "providers/StateContainer";
import { createContext, PropsWithChildren, useContext } from "react";
import { or } from "utils";
import { pondURL } from "./pond";

export interface ISiteAPIContext {
  addSite: (site: pond.SiteSettings, otherTeam?: string) => Promise<any>;
  getSite: (siteID: string, otherTeam?: string) => Promise<any>;
  getSitePage: (siteID: string, otherTeam?: string) => Promise<any>;
  listSites: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => Promise<AxiosResponse<pond.ListSitesResponse>>;
  listSitesPageData: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => Promise<AxiosResponse<pond.ListSitesPageDataResponse>>;
  removeSite: (siteID: string) => Promise<AxiosResponse<pond.RemoveSiteResponse>>;
  updateSite: (
    key: string,
    site: pond.SiteSettings,
    asRoot?: true,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.UpdateSiteResponse>>;
  updateLink: (
    parentKey: string,
    parentType: string,
    objectID: string,
    objectType: string,
    permissions: string[],
    otherTeam?: string
  ) => Promise<any>;
}

export const SiteAPIContext = createContext<ISiteAPIContext>({} as ISiteAPIContext);

interface Props {}

export default function SiteProvider(props: PropsWithChildren<Props>) {
  const { children } = props;
  const { get, del, post, put } = useHTTP();
  const [{ as }] = useGlobalState();

  const getSitePage = (siteID: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return get(pondURL("/sitePage/" + siteID + "?as=" + view));
    return get(pondURL("/sitePage/" + siteID));
  };

  const addSite = (site: pond.SiteSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return post(pondURL("/sites?as=" + view), site);
    return post(pondURL("/sites"), site);
  };

  const getSite = (siteID: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return get(pondURL("/site/" + siteID + "?as=" + view));
    return get(pondURL("/site/" + siteID));
  };

  const removeSite = (key: string) => {
    return del<pond.RemoveSiteResponse>(pondURL("/sites/" + key));
  };

  const listSites = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => {
    const view = otherTeam ? otherTeam : as
    return get<pond.ListSitesResponse>(
      pondURL(
        "/sites" +
          "?limit=" +
          limit +
          "&offset=" +
          offset +
          ("&order=" + or(order, "asc")) +
          ("&by=" + or(orderBy, "key")) +
          (view ? "&as=" + view : "") +
          (asRoot ? "&asRoot=" + asRoot.toString() : "") +
          (search ? "&search=" + search : "")
      )
    );
  };

  const listSitesPageData = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => {
    const view = otherTeam ? otherTeam : as
    return get<pond.ListSitesPageDataResponse>(
      pondURL(
        "/sitesWithData" +
          "?limit=" +
          limit +
          "&offset=" +
          offset +
          ("&order=" + or(order, "asc")) +
          ("&by=" + or(orderBy, "key")) +
          (view ? "&as=" + view : "") +
          (asRoot ? "&asRoot=" + asRoot.toString() : "") +
          (search ? "&search=" + search : "")
      )
    );
  };

  const updateSite = (key: string, site: pond.SiteSettings, asRoot?: boolean, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return put<pond.UpdateSiteResponse>(
        pondURL(
          "/sites/" + key + "?as=" + view + (asRoot ? "&asRoot=" + asRoot.toString() : "")
        ),
        site
      );
    return put<pond.UpdateSiteResponse>(
      pondURL("/sites/" + key + (asRoot ? "?asRoot=" + asRoot.toString() : "")),
      site
    );
  };

  const updateLink = (
    parentID: string,
    parentType: string,
    objectID: string,
    objectType: string,
    permissions: string[],
    otherTeam?: string
  ) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return post(pondURL(`/sites/` + parentID + `/link?as=${view}`), {
        Key: objectID,
        Type: objectType,
        Parent: parentID,
        ParentType: parentType,
        Permissions: permissions
      });
    return post(pondURL(`/sites/` + parentID + `/link`), {
      Key: objectID,
      Type: objectType,
      Parent: parentID,
      ParentType: parentType,
      Permissions: permissions
    });
  };

  return (
    <SiteAPIContext.Provider
      value={{
        addSite,
        getSite,
        listSites,
        listSitesPageData,
        removeSite,
        updateSite,
        updateLink,
        getSitePage//
      }}>
      {children}
    </SiteAPIContext.Provider>
  );
}

export const useSiteAPI = () => useContext(SiteAPIContext);
