import fetch, { Headers } from 'node-fetch';
import Util from '../lib/util';
import XmlHelper from '../xml/index';

export interface IUser {
  username: string;
  password: string;
}

export type AcceptableHttpVerbs = 'GET' | 'POST' | 'PUT';
export type HeadersType = Headers | { [header: string]: string };
export type BodyType = { root: string; properties: Object; };

export default class FinesseHttpHelper {
  static get (url: string, user: IUser): Promise<string | null> {
    return this._httpRequest(url, user, 'GET');
  }

  static put (url: string, user: IUser, body: BodyType): Promise<string | null> {
    return this._xmlRequest(url, user, 'PUT', body);
  }

  static post (url: string, user: IUser, body: BodyType): Promise<string | null> {
    return this._xmlRequest(url, user, 'POST', body);
  }

  static _xmlRequest (url: string, user: IUser, method: AcceptableHttpVerbs, body: BodyType) {
    let headers = {
      'Content-Type': 'application/xml',
      'Accept': 'application/xml'
    };

    let processedBody: string = XmlHelper.objToXml(body);

    return this._httpRequest(url, user, method, headers, processedBody);
  }

  static _basicAuthString (user: IUser): string {
    let userPassString = `${user.username}:${user.password}`;
    let base64 = new Buffer(userPassString).toString('base64');

    return `Basic ${base64}`;
  }

  private static async _httpRequest (
    url: string,
    user: IUser,
    method: AcceptableHttpVerbs,
    headers: HeadersType= {},
    body: string= ''
): Promise<string | null> {
    headers['Authorization'] = this._basicAuthString(user);

    try {
      const response = await fetch(url, { method, headers, body });
      return await response.text();
    } catch (e) {
      Util._promiseErrorHandler(e);
    }

    return null;
  }
};
