import { CookieJar } from 'jsdom';
import nodeFetch, { RequestInit, Response } from 'node-fetch';
import { Errors, RenaiError } from '../../types/error';
import { throwError } from './error';
import { load, save, StoreKeys } from './store';

export let cookieJar: CookieJar = new CookieJar();

let initialized = false;

function init(): Promise<void> {
  if (!initialized) {
    return load(StoreKeys.COOKIES).then((cookies: any) => {
      if (cookies !== undefined) {
        cookieJar = CookieJar.deserializeSync(cookies);
      }
      initialized = true;
    });
  } else {
    return Promise.resolve();
  }
}

export function fetch(url: string, requestInit: RequestInit = {}): Promise<Response> {
  return init().then(() => {
    const cookiedInit = {
      ...requestInit,
      ...{
        headers: {
          ...requestInit.headers,
          ...{
            Cookie: cookieJar.getCookieStringSync(url),
          },
        },
      },
    };
    return nodeFetch(url, cookiedInit).then((res: Response) => {
      setCookies(res.headers.raw()['set-cookie'], url).catch();
      return res;
    });
  });
}

function setCookies(header: string[], url: string): Promise<void> {
  if (header) {
    header.forEach((cookie: string) => {
      cookieJar.setCookieSync(cookie, url);
    });
    return save(StoreKeys.COOKIES, cookieJar.serializeSync()).catch((reason: any) => {
      throwError(new RenaiError(Errors.ECOOKIESAVEFAIL, reason));
    });
  }
  return Promise.resolve();
}
