import { getCookieValue } from "@/router/guards";

class FetchError extends Error {
  response: Response;

  constructor(response: Response, message = "HTTP error " + response.status) {
    super(message);
    this.response = response;
  }
}

export const itFetch = (url: RequestInfo, options: RequestInit) => {
  return fetch(url, options).then((response) => {
    if (!response.ok) {
      throw new FetchError(response);
    }

    return response;
  });
};

export const itPost = (url: RequestInfo, data: unknown, options: RequestInit = {}) => {
  options = Object.assign({}, options);

  const headers = Object.assign(
    {
      Accept: "application/json",
      "Content-Type": "application/json;charset=UTF-8",
    },
    options?.headers
  ) as HeadersInit;
  options.headers = headers;

  options = Object.assign(
    {
      method: "POST",
      headers: headers,
      body: JSON.stringify(data),
    },
    options
  );

  if (options.method === undefined) {
    options.method = "POST";
  }

  // @ts-ignore
  options.headers["X-CSRFToken"] = getCookieValue("csrftoken");

  if (["GET", "DELETE"].indexOf(options.method) > -1) {
    delete options.body;
  }

  return itFetch(url, options).then((response) => {
    return response.json().catch(() => {
      return Promise.resolve(null);
    });
  });
};

export const itGet = (url: RequestInfo) => {
  return itPost(url, {}, { method: "GET" });
};

export const itDelete = (url: RequestInfo) => {
  return itPost(url, {}, { method: "DELETE" });
};

const itGetPromiseCache = new Map<string, Promise<any>>();

export function bustItGetCache(key?: string) {
  if (key) {
    itGetPromiseCache.delete(key);
  } else {
    itGetPromiseCache.clear();
  }
}

export const itGetCached = (
  url: RequestInfo,
  options = {
    reload: false,
  }
): Promise<any> => {
  if (!itGetPromiseCache.has(url.toString()) || options.reload) {
    itGetPromiseCache.set(url.toString(), itGet(url));
  }

  return itGetPromiseCache.get(url.toString()) as Promise<any>;
};
