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

export interface ITaskAPIContext {
  addTask: (task: pond.TaskSettings, otherTeam?: string) => Promise<AxiosResponse<pond.AddTaskResponse>>;
  getTask: (taskID: string, otherTeam?: string) => Promise<AxiosResponse<pond.Task>>;
  listTasks: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string,
    from?: string,
    to?: string
  ) => Promise<AxiosResponse<pond.ListTasksResponse>>;
  removeTask: (taskID: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveTaskResponse>>;
  updateTask: (
    key: string,
    task: pond.TaskSettings,
    asRoot?: true,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.UpdateTaskResponse>>;
  getMultiTasks: (objectKeys: string[], otherTeam?: string) => Promise<AxiosResponse<pond.GetMultiTasksResponse>>;
}

export const TaskAPIContext = createContext<ITaskAPIContext>({} as ITaskAPIContext);

interface Props {}

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

  const addTask = (task: pond.TaskSettings, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return post<pond.AddTaskResponse>(pondURL("/tasks?as=" + view), task);
    return post<pond.AddTaskResponse>(pondURL("/tasks"), task);
  };

  const getTask = (taskID: string, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view) return get<pond.Task>(pondURL("/task/" + taskID + "?as=" + view));
    return get<pond.Task>(pondURL("/task/" + taskID));
  };

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

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

  const updateTask = (key: string, task: pond.TaskSettings, asRoot?: boolean, otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return put<pond.UpdateTaskResponse>(
        pondURL("/tasks/" + key + "?as=" + view + (asRoot ? "&asRoot=" + asRoot.toString() : "")),
        task
      );
    return put<pond.UpdateTaskResponse>(
      pondURL("/tasks/" + key + (asRoot ? "?asRoot=" + asRoot.toString() : "")),
      task
    );
  };

  const getMultiTasks = (objectKeys: string[], otherTeam?: string) => {
    const view = otherTeam ? otherTeam : as
    if (view)
      return get<pond.GetMultiTasksResponse>(
        pondURL("/multitasks?objectKeys=" + objectKeys.join(",") + "&as=" + view)
      );
    return get<pond.GetMultiTasksResponse>(
      pondURL("/multitasks?objectKeys=" + objectKeys.join(","))
    );
  };

  return (
    <TaskAPIContext.Provider
      value={{
        addTask,
        getTask,
        listTasks,
        removeTask,
        updateTask,
        getMultiTasks
      }}>
      {children}
    </TaskAPIContext.Provider>
  );
}

export const useTaskAPI = () => useContext(TaskAPIContext);
