//** REQUEST TYPES **//
export const REQUEST_TYPE_POST = "POST";
export const REQUEST_TYPE_GET = "GET";
export const REQUEST_TYPE_PUT = "PUT";
export const REQUEST_TYPE_DELETE = "DELETE";

//** POST CONTENT TYPES **//
export const CONTENT_TYPE_JSON = "json";
export const CONTENT_TYPE_FORM = "x-www-form-urlencoded";

//** API URLS **//
export const API_GET_PAGES = "/api/v1/page/published";
export const API_GET_FEATURED = "/api/v1/page/featured";
export const API_GET_PAGE = "/api/v1/page/single";
export const API_GET_MENU = "/api/v1/page/menu";
export const API_GET_TAGS = "/api/v1/page/tags";

//** API TASKS **//
export const TASK_GET_CONTENT = "retrieveContent";

/**
 * A bag of methods for getting content from an install.
 */
class FipamoContentAPI {
  /**
   * @constructor
   * @param {string} baseURL - url of install, defaults to local
   * @param {string} key - user api key found in Settings
   * @author Ro
   */
  constructor(baseURL = null, key = null) {
    this.baseURL = null;
    this.key = null;
    if (key) this.key = key;
    if (baseURL) this.baseURL = baseURL;
  }

  /**
   * *Promise method for retrieving page data*\
   * **GET**`/api/v1/page/:type`
   * @param {string} type - type of pages (`published | menu | featured`) being retrieved; null value defaults to `published`
   * @example
   * api.pages('published').then(pages=>{
   *    console.log("Pages Object", pages);
   * })
   * @returns {object} json object that contains pages of requested type
   *
   * *pages object example*
   * ```
    {
      "pages":
      [
        {
          "id":1,
          "uuid":"uuid-for-entry",
          "title":"Entry Title",
          "feature":"/path/to/image.jpg",
          "path":"2020/09",
          "layout":"page",
          "tags":"these, are, tags",
          "author":"your-name",
          "created":"2020 Sep Tue 01",
          "updated":"2020 Sep Tue 01",
          "deleted":false,
          "menu":false,
          "featured":false,
          "published":true,
          "slug":"entry-title",
          "content":"Premium Content"
        },
        {
          "id":2,
          "uuid":"uuid-for-entry",
          "title":"Another Title",
          "feature":"/path/to/image.jpg",
          "path":"2020/09",
          "layout":"page",
          "tags":"these, are, tags",
          "author":"your-name",
          "created":"2020 Sep Tue 01",
          "updated":"2020 Sep Tue 01",
          "deleted":false,
          "menu":false,
          "featured":false,
          "published":true,
          "slug":"another-title",
          "content":"Premium Content"
        }
      ],
    "totalItems":2
    }
   * ```
   *
   */
  pages(type = null) {
    //set url based on request type
    let requestURL = "";
    switch (type) {
      default:
      case "published":
        requestURL = API_GET_PAGES + "?key=" + this.key;
        break;
      case "featured":
        requestURL = API_GET_FEATURED + "?key=" + this.key;
        break;
      case "menu":
        requestURL = API_GET_MENU + "?key=" + this.key;
        break;
    }
    return new Promise((resolve, reject) => {
      this._request(
        this.baseURL ? this.baseURL + requestURL : requestURL,
        TASK_GET_CONTENT
      )
        .then((result) => {
          resolve(result);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }
  /**
   * *Promise method for retrieving single page*\
   * **GET** `/api/v1/page/single/:id`
   * @param {string} id - uuid of desired page
   * @example
   * api.page("a-uuid-for-a-page").then(page=>{
        console.log("Page Object", page);
   * })
   * @returns {object} json object that contains data for requested page
   *
   * *page object example*
   * ```
     {
       "id":1,
       "uuid":"uuid-for-entry",
       "title":"Entry Title",
       "feature":"/path/to/image.jpg",
       "path":"2020/09",
       "layout":"page",
       "tags":"these, are, tags",
       "author":"your-name",
       "created":"2020 Sep Tue 01",
       "updated":"2020 Sep Tue 01",
       "deleted":false,
       "menu":false,
       "featured":false,
       "published":true,
       "slug":"entry-title",
       "content":"Premium Content"
     }
   * ```
   */
  page(id) {
    return new Promise((resolve, reject) => {
      this._request(
        this.baseURL
          ? this.baseURL + API_GET_PAGE + "/" + id + "?key=" + this.key
          : API_GET_PAGE + "/" + id + "?key=" + this.key,
        TASK_GET_CONTENT,
        REQUEST_TYPE_GET
      )
        .then((result) => {
          resolve(result);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }

  /**
   * *Promise method for retrieving all tags used by pages*\
   * **GET** `/api/v1/page/tags`
   * @example
   * api.tags().then(tags=>{
       console.log("Tags Object", tags);
   * })
   * @returns {object} json object that contains site tags and page stubs associated with said tag
   *
   * *tags object example*
   * ```
      [
        {
          "tag_name":"this is a tag",
          "slug":"this-is-a-tag",
          "pages":
            [
              {
                "title":"This is a title",
                "slug":"this-is-a-title",
                "path":"2021/04"
              },
              
              {
                "title":"This is another title",
                "slug":"this-is-another-title",
                "path":"2020/10"
              }
            ]
        },
        {
          "tag_name":"this is another tag",
          "slug":"this-is-another-tag",
          "pages":
            [
              {
                "title":"This is a title",
                "slug":"this-is-a-title",
                "path":"2021/04"
              },
              
              {
                "title":"This is another title",
                "slug":"this-is-another-title",
                "path":"2020/10"
              }
            ]
        }
      ]  
   * ```
   */
  tags() {
    return new Promise((resolve, reject) => {
      this._request(
        this.baseURL
          ? this.baseURL + API_GET_TAGS + "?key=" + this.key
          : API_GET_TAGS + "?key=" + this.key,
        TASK_GET_CONTENT,
        REQUEST_TYPE_GET
      )
        .then((result) => {
          resolve(result);
        })
        .catch((err) => {
          reject(err);
        });
    });
  }

  //--------------------------
  // private
  //--------------------------
  _request(
    requestURL,
    eventType,
    requestType = REQUEST_TYPE_GET,
    contentType = CONTENT_TYPE_JSON,
    requestData = null
  ) {
    var self = this;
    return new Promise(function (resolve, reject) {
      var request = new XMLHttpRequest();
      request.upload.onprogress = self.handleLoadProgress;
      request.open(requestType, requestURL, true);
      request.onload = () => {
        if (request.status == 200) {
          let response = JSON.parse(request["response"]);
          resolve(response);
        } else {
          let error = JSON.parse(request["response"]);
          reject(error);
        }
      };
      if (requestType == REQUEST_TYPE_PUT || requestType == REQUEST_TYPE_POST) {
        switch (contentType) {
          case CONTENT_TYPE_JSON:
            request.setRequestHeader(
              "Content-type",
              "application/" + contentType
            );
            request.send(JSON.stringify(requestData));
            break;
          case CONTENT_TYPE_FORM:
            request.send(requestData);
            break;
        }
      } else {
        request.send();
      }
    });
  }

  //--------------------------
  // event handlers
  //--------------------------
  handleLoadProgress(e) {
    this.percentComplete = Math.ceil((e.loaded / e.total) * 100);
    //pass element to display request progress
  }
}

export { FipamoContentAPI as default };
