Source: api-client.js

import { logger } from "./shims";

// Handles HTTP interactions with the Roundware API server, v2.
// NOTE: Every HTTP method except ".get()" will cause most browers to issue a preflight requirements check to the server via the OPTIONS verb, 
// to verify CORS will allow the response to load in the browser. Sometimes this OPTIONS call can get obscured in debugging tools.
// @see http://roundware.org/docs/terminology/index.html
export class ApiClient {
  /** Create a new ApiClient
   * @param {Object} window - representing the context in which we are executing - provides reference to window.jQuery.ajax()
   * @param {String} baseServerUrl - identifies the Roundware server to receive API requests
   * @param {Boolean} [options.fetch = fetch] - for testing purposes, you can inject the fetch mechanism to use for making network requests **/
  constructor(window,baseServerUrl) {
    this._jQuery = window.jQuery;
    this._serverUrl = baseServerUrl;
  }

  /** Make a GET request to the Roundware server
   * @param {String} path - the path for your API request, such as "/streams"
   * @param {Object} options - see the "send" method
   * @see {send} **/
  get(path,data,options = {}) {
    options.method = "GET";
    return this.send(path,data,options);
  }

  /** Make a POST request to the Roundware server
   * @param {String} path - the path for your API request, such as "/streams"
   * @param {Object} options - see the "send" method
   * @see {send} **/
  post(path,data,options = {}) {
    options.method = "POST";
    return this.send(path,data,options);
  }

  /** Make a PATCH request to the Roundware server
   * @param {String} path - the path for your API request, such as "/streams"
   * @param {Object} options - see the "send" method
   * @see {send} **/
  patch(path,data,options = {}) {
    options.method = "PATCH";
    return this.send(path,data,options);
  }

  /** Transmit an Ajax request to the Roundware API. Note that the Roundware Server expects paths to end with a trailing slash: /sessions/ instead of /sessions
   * @param path {string} - identifies the endpoint to receive the request
   * @param data {object} - the payload to send
   * @param options {object} - any additional options to add to the Ajax request 
   * @return {Promise} - will resolve or reject depending on the status of the request
   * @todo might be a good place to implement exponential retry of certain types of errors
   * **/
  send(path,data,options = {}) {
    let method = options.method || "GET";
    let url = this._serverUrl + path;

    if (!options.headers) {
      options.headers = {};
    }

    options.data = data;
    options.mode = "no-cors";

    if (!options.timeout) {
      options.timeout = 30000; // 30 seconds, arbitrary
    }

    let deferred = this._jQuery.Deferred();
    let promise = deferred.promise();

    this._jQuery.ajax(url,options).
      then((data) => deferred.resolve(data)).
      fail((jqXHR,textStatus,errorThrown) => {
        let techMsg = `${textStatus}: ${errorThrown}`;
        let usrMsg = `We were unable to contact the audio server due to a network problem; please try again: '${techMsg}'`;
        logger.error(techMsg,jqXHR);
        deferred.reject(usrMsg);
      });

    return promise;
  }

  /** Set the authorization token to use as the header for future API requests. Most Roundware API calls require an auth token to be set 
   * @param {String} authToken - characters to use in the authorization header **/
  setAuthToken(authToken) {
    this._jQuery.ajaxSetup({
      headers: { "Authorization": `token ${authToken}` }
    });
  }
}