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

export interface IObjectHeaterAPIContext {
  addObjectHeater: (
    name: string,
    heater: pond.ObjectHeaterSettings,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.AddObjectHeaterResponse>>;
  getObjectHeater: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.GetObjectHeaterResponse>>;
  listObjectHeaters: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string,
    keys?: string[],
    types?: string[],
    numerical?: boolean
  ) => Promise<AxiosResponse<pond.ListObjectHeatersResponse>>;
  removeObjectHeater: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveObjectHeaterResponse>>;
  updateObjectHeater: (
    key: string,
    name: string,
    settings: pond.ObjectHeaterSettings,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.UpdateObjectHeaterResponse>>;
  updateLink: (
    parentKey: string,
    parentType: string,
    objectID: string,
    objectType: string,
    permissions: string[],
    otherTeam?: string
  ) => Promise<any>;
  listObjectHeatersPageData: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => Promise<AxiosResponse<pond.ListObjectHeatersPageDataResponse>>;
}

export const ObjectHeaterAPIContext = createContext<IObjectHeaterAPIContext>(
  {} as IObjectHeaterAPIContext
);

interface Props {}

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

  const addObjectHeater = (name: string, settings: pond.ObjectHeaterSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return post<pond.AddObjectHeaterResponse>(
        pondURL("/objectHeaters?name=" + name + "&as=" + view),
        settings
      );
    return post<pond.AddObjectHeaterResponse>(pondURL("/objectHeaters?name=" + name), settings);
  };

  const getObjectHeater = (key: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return get<pond.GetObjectHeaterResponse>(pondURL("/objectHeaters/" + key + "?as=" + view));
    }
    return get<pond.GetObjectHeaterResponse>(pondURL("/objectHeaters/" + key));
  };

  const removeObjectHeater = (key: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return del<pond.RemoveObjectHeaterResponse>(pondURL("/objectHeaters/" + key + "?as=" + view));
    return del<pond.RemoveObjectHeaterResponse>(pondURL("/objectHeaters/" + key));
  };

  const listObjectHeaters = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string,
    keys?: string[],
    types?: string[],
    numerical?: boolean
  ) => {
    const view = otherTeam ? otherTeam : as
    return get<pond.ListObjectHeatersResponse>(
      pondURL(
        "/objectHeaters" +
          "?limit=" +
          limit +
          "&offset=" +
          offset +
          ("&order=" + (order ? order : "asc")) +
          ("&by=" + (orderBy ? orderBy : "key")) +
          (search ? "&search=" + search : "") +
          (numerical ? "&numerical=true" : "") +
          (asRoot ? "&asRoot=" + asRoot.toString() : "") +
          (view ? "&as=" + view : "") +
          (keys ? "&keys=" + keys.toString() : "") +
          (types ? "&types=" + types.toString() : "")
      )
    );
  };

  const updateObjectHeater = (key: string, name: string, settings: pond.ObjectHeaterSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) {
      return put<pond.UpdateObjectHeaterResponse>(
        pondURL("/objectHeaters/" + key + "?as=" + view + "&name=" + name),
        settings
      );
    }
    return put<pond.UpdateObjectHeaterResponse>(
      pondURL("/objectHeaters/" + key + "?name=" + name),
      settings
    );
  };

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

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

  return (
    <ObjectHeaterAPIContext.Provider
      value={{
        addObjectHeater,
        getObjectHeater,
        listObjectHeaters,
        removeObjectHeater,
        updateObjectHeater,
        updateLink,
        listObjectHeatersPageData
      }}>
      {children}
    </ObjectHeaterAPIContext.Provider>
  );
}

export const useObjectHeaterAPI = () => useContext(ObjectHeaterAPIContext);
