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 INoteAPIContext {
  addNote: (note: pond.NoteSettings, attachments?: string[]) => Promise<any>;
  getNote: (noteID: string) => Promise<AxiosResponse<pond.Note>>;
  updateNote: (note: pond.NoteSettings) => Promise<any>;
  listNotes: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.ListNotesResponse>>;
  listChats: (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string
  ) => Promise<AxiosResponse<pond.ListChatsResponse>>;
  removeNote: (noteID: string) => Promise<AxiosResponse<pond.RemoveBinResponse>>;
}

export const NoteAPIContext = createContext<INoteAPIContext>({} as INoteAPIContext);

interface Props {}

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

  const addNote = (note: pond.NoteSettings, attachments?: string[]) => {
    let url = pondURL("/notes" + (attachments ? "?attachments=" + attachments.toString() : ""))
    return new Promise<AxiosResponse>((resolve, reject) => {
      post(url, note).then(resp => {
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  const getNote = (noteID: string) => {
    return new Promise<AxiosResponse<pond.Note>>((resolve, reject) => {
      get<pond.Note>(pondURL("/notes/" + noteID)).then(resp => {
        resp.data = pond.Note.fromObject(resp.data)
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  const updateNote = (note: pond.NoteSettings) => {
    return new Promise<AxiosResponse>((resolve, reject) => {
      put(pondURL("/notes/"), note).then(resp => {
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  const removeNote = (key: string) => {
    return new Promise<AxiosResponse>((resolve, reject) => {
      del<pond.RemoveNoteResponse>(pondURL("/notes/" + key)).then(resp => {
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  const listNotes = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string
  ) => {
    const view = otherTeam ? otherTeam : as
    let url = pondURL(
      "/notes" +
        "?limit=" +
        limit +
        "&offset=" +
        offset +
        ("&order=" + (order ? order : "asc")) +
        ("&by=" + (orderBy ? orderBy : "key")) +
        (search ? "&search=" + search : "") +
        (asRoot ? "&asRoot=" + asRoot.toString() : "") +
        (view ? "&as=" + view : "")
    )
    return new Promise<AxiosResponse<pond.ListNotesResponse>>((resolve, reject) => {
      get<pond.ListNotesResponse>(url).then(resp => {
        resp.data = pond.ListNotesResponse.fromObject(resp.data)
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  const listChats = (
    limit: number,
    offset: number,
    order?: "asc" | "desc",
    orderBy?: string,
    search?: string,
    asRoot?: boolean,
    otherTeam?: string
  ) => {
    const view = otherTeam ? otherTeam : as
    let url = pondURL(
      "/chats" +
        "?limit=" +
        limit +
        "&offset=" +
        offset +
        ("&order=" + (order ? order : "asc")) +
        ("&by=" + (orderBy ? orderBy : "key")) +
        (search ? "&search=" + search : "") +
        (asRoot ? "&asRoot=" + asRoot.toString() : "") +
        (view ? "&as=" + view : "")
    )
    return new Promise<AxiosResponse<pond.ListChatsResponse>>((resolve, reject) => {
      get<pond.ListChatsResponse>(url).then(resp => {
        resp.data = pond.ListChatsResponse.fromObject(resp.data)
        return resolve(resp)
      }).catch(err => {
        return reject(err)
      })
    })
  };

  return (
    <NoteAPIContext.Provider
      value={{
        addNote,
        getNote,
        updateNote,
        listChats,
        listNotes,
        removeNote
      }}>
      {children}
    </NoteAPIContext.Provider>
  );
}

export const useNoteAPI = () => useContext(NoteAPIContext);
