import { AxiosResponse } from "axios";
import { useHTTP } from "../http";
import { pond } from "protobuf-ts/pond";
import { useGlobalState } from "../StateContainer";
import React, { createContext, PropsWithChildren, useContext } from "react";
import { or } from "utils";
import { pondURL } from "./pond";
import { permissionToString } from "pbHelpers/Permission";

export interface IFieldAPIContext {
  addField: (field: pond.FieldSettings, otherTeam?: string) => Promise<any>;
  getField: (fieldId: string, otherTeam?: string) => Promise<AxiosResponse<pond.Field>>;
  listFields: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    otherTeam?: string,
    asRoot?: boolean
  ) => Promise<AxiosResponse<pond.ListFieldsResponse>>;
  removeField: (key: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveFieldResponse>>;
  updateField: (
    key: string,
    field: pond.FieldSettings,
    asRoot?: true,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.UpdateFieldResponse>>;
  shareAll: (
    email: string,
    permissions: pond.Permission[],
  ) => Promise<AxiosResponse<any>>
  shareAllByKey: (
    key: string,
    permissions: pond.Permission[]
  ) => Promise<AxiosResponse<any>>
}

export const FieldAPIContext = createContext<IFieldAPIContext>({} as IFieldAPIContext);

interface Props {}

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

  const addField = (field: pond.FieldSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return post<pond.AddFieldResponse>(pondURL("/fields?as=" + view), field);
    return post(pondURL("/fields"), field);
  };

  const getField = (fieldId: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return get<pond.Field>(pondURL("/field/" + fieldId + "?as=" + view));
    return get<pond.Field>(pondURL("/field/" + fieldId));
  };

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

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

  const updateField = (key: string, field: pond.FieldSettings, asRoot?: boolean, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return put<pond.UpdateFieldResponse>(
        pondURL("/fields/" + key + "?as=" + view + (asRoot ? "&asRoot=" + asRoot.toString() : "")),
        field
      );
    return put<pond.UpdateFieldResponse>(
      pondURL("/fields/" + key + (asRoot ? "?asRoot=" + asRoot.toString() : "")),
      field
    );
  };

  const shareAll = (email: string, permissions: pond.Permission[]) => {
    let url = pondURL("/shareAllFields")
    if (as) url = url + "?as=" + as
    return new Promise<AxiosResponse>((resolve, reject) => {
      post(url, {
        email: email,
        permissions: permissions.map(permission => permissionToString(permission))
      }).then(resp => {
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  }
  
  const shareAllByKey = (key: string, permissions: pond.Permission[]) => {
    let url = pondURL("/shareAllFieldsByKey")
    if (as) url = url + "?as=" + as
    return new Promise<AxiosResponse>((resolve, reject) => {
      post(url, {
        key: key,
        permissions: permissions.map(permission => permissionToString(permission))
      }).then(resp => {
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  }

  return (
    <FieldAPIContext.Provider
      value={{
        addField,
        getField,
        listFields,
        removeField,
        updateField,
        shareAll,
        shareAllByKey
      }}>
      {children}
    </FieldAPIContext.Provider>
  );
}

export const useFieldAPI = () => useContext(FieldAPIContext);
