text: /** filepreviews 2.1.0 **/
  ;(function () {
  
    var object = typeof exports != 'undefined' ? exports : this; // #8: web workers
    var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
  
    function InvalidCharacterError(message) {
      this.message = message;
    }
    InvalidCharacterError.prototype = new Error;
    InvalidCharacterError.prototype.name = 'InvalidCharacterError';
  
    // encoder
    // [https://gist.github.com/999166] by [https://github.com/nignag]
    object.btoa || (
    object.btoa = function (input) {
      var str = String(input);
      for (
        // initialize result and counter
        var block, charCode, idx = 0, map = chars, output = '';
        // if the next str index does not exist:
        //   change the mapping table to "="
        //   check if d has no fractional digits
        str.charAt(idx | 0) || (map = '=', idx % 1);
        // "8 - idx % 1 * 8" generates the sequence 2, 4, 6, 8
        output += map.charAt(63 & block >> 8 - idx % 1 * 8)
      ) {
        charCode = str.charCodeAt(idx += 3/4);
        if (charCode > 0xFF) {
          throw new InvalidCharacterError("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
        }
        block = block << 8 | charCode;
      }
      return output;
    });
  
    // decoder
    // [https://gist.github.com/1020396] by [https://github.com/atk]
    object.atob || (
    object.atob = function (input) {
      var str = String(input).replace(/=+$/, '');
      if (str.length % 4 == 1) {
        throw new InvalidCharacterError("'atob' failed: The string to be decoded is not correctly encoded.");
      }
      for (
        // initialize result and counters
        var bc = 0, bs, buffer, idx = 0, output = '';
        // get next character
        buffer = str.charAt(idx++);
        // character found in table? initialize bit storage and add its ascii value;
        ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
          // and if not first of each 4 characters,
          // convert the first 8 bits to one ascii character
          bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
      ) {
        // try to find character in table (0-63, not found => -1)
        buffer = chars.indexOf(buffer);
      }
      return output;
    });
  
  }());
  
  /**
  * XMLHttpRequest.js Copyright (C) 2011 Sergey Ilinsky (http://www.ilinsky.com)
  *
  * This work is free software; you can redistribute it and/or modify
  * it under the terms of the GNU Lesser General Public License as published by
  * the Free Software Foundation; either version 2.1 of the License, or
  * (at your option) any later version.
  *
  * This work is distributed in the hope that it will be useful,
  * but without any warranty; without even the implied warranty of
  * merchantability or fitness for a particular purpose. See the
  * GNU Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public License
  * along with this library; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
  
  (function () {
  
  	// Save reference to earlier defined object implementation (if any)
  	var oXMLHttpRequest = window.XMLHttpRequest;
  	
  	// Define on browser type
  	var bGecko  = !!window.controllers;
  	var bIE     = !!window.document.namespaces;
  	var bIE7    = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
  
  	// Enables "XMLHttpRequest()" call next to "new XMLHttpRequest()"
  	function fXMLHttpRequest() {
  		if (!window.XMLHttpRequest || bIE7) {
  			this._object = new window.ActiveXObject("Microsoft.XMLHTTP");
  		} // only use initial XHR object internally if current reference to XHR is our normalized replacement 
  		else if (window.XMLHttpRequest.isNormalizedObject) {
  			this._object = new oXMLHttpRequest();
  		} // otherwise use whatever is currently referenced by XMLHttpRequest
  		else {
  			this._object = new window.XMLHttpRequest();		
  		}
  		this._listeners = [];
  	}
  
  	// Constructor
  	function cXMLHttpRequest() {
  		return new fXMLHttpRequest;
  	}
  	cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
  
  	// BUGFIX: Firefox with Firebug installed would break pages if not executed
  	if (bGecko && oXMLHttpRequest.wrapped) {
  		cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
  	}
  	
  	// Marker to be able to easily identify our object
  	cXMLHttpRequest.isNormalizedObject = true;
  
  	// Constants
  	cXMLHttpRequest.UNSENT            = 0;
  	cXMLHttpRequest.OPENED            = 1;
  	cXMLHttpRequest.HEADERS_RECEIVED  = 2;
  	cXMLHttpRequest.LOADING           = 3;
  	cXMLHttpRequest.DONE              = 4;
  
  	// Interface level constants
  	cXMLHttpRequest.prototype.UNSENT            = cXMLHttpRequest.UNSENT;
  	cXMLHttpRequest.prototype.OPENED            = cXMLHttpRequest.OPENED;
  	cXMLHttpRequest.prototype.HEADERS_RECEIVED  = cXMLHttpRequest.HEADERS_RECEIVED;
  	cXMLHttpRequest.prototype.LOADING           = cXMLHttpRequest.LOADING;
  	cXMLHttpRequest.prototype.DONE              = cXMLHttpRequest.DONE;
  
  	// Public Properties
  	cXMLHttpRequest.prototype.readyState    = cXMLHttpRequest.UNSENT;
  	cXMLHttpRequest.prototype.responseText  = '';
  	cXMLHttpRequest.prototype.responseXML   = null;
  	cXMLHttpRequest.prototype.status        = 0;
  	cXMLHttpRequest.prototype.statusText    = '';
  
  	// Priority proposal
  	cXMLHttpRequest.prototype.priority    = "NORMAL";
  
  	// Instance-level Events Handlers
  	cXMLHttpRequest.prototype.onreadystatechange  = null;
  
  	// Class-level Events Handlers
  	cXMLHttpRequest.onreadystatechange  = null;
  	cXMLHttpRequest.onopen              = null;
  	cXMLHttpRequest.onsend              = null;
  	cXMLHttpRequest.onabort             = null;
  
  	// Public Methods
  	cXMLHttpRequest.prototype.open  = function(sMethod, sUrl, bAsync, sUser, sPassword) {
  		// http://www.w3.org/TR/XMLHttpRequest/#the-open-method
  		var sLowerCaseMethod = sMethod.toLowerCase();
  		if (sLowerCaseMethod == "connect" || sLowerCaseMethod == "trace" || sLowerCaseMethod == "track") {
  			// Using a generic error and an int - not too sure all browsers support correctly
  			// http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#securityerror, so, this is safer
  			// XXX should do better than that, but this is OT to XHR.
  			throw new Error(18);
  		}
  
  		// Delete headers, required when object is reused
  		delete this._headers;
  
  		// When bAsync parameter value is omitted, use true as default
  		if (arguments.length < 3) {
  			bAsync  = true;
  		}
  
  		// Save async parameter for fixing Gecko bug with missing readystatechange in synchronous requests
  		this._async   = bAsync;
  
  		// Set the onreadystatechange handler
  		var oRequest  = this;
  		var nState    = this.readyState;
  		var fOnUnload = null;
  
  		// BUGFIX: IE - memory leak on page unload (inter-page leak)
  		if (bIE && bAsync) {
  			fOnUnload = function() {
  				if (nState != cXMLHttpRequest.DONE) {
  					fCleanTransport(oRequest);
  					// Safe to abort here since onreadystatechange handler removed
  					oRequest.abort();
  				}
  			};
  			window.attachEvent("onunload", fOnUnload);
  		}
  
  		// Add method sniffer
  		if (cXMLHttpRequest.onopen) {
  			cXMLHttpRequest.onopen.apply(this, arguments);
  		}
  
  		if (arguments.length > 4) {
  			this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
  		} else if (arguments.length > 3) {
  			this._object.open(sMethod, sUrl, bAsync, sUser);
  		} else {
  			this._object.open(sMethod, sUrl, bAsync);
  		}
  
  		this.readyState = cXMLHttpRequest.OPENED;
  		fReadyStateChange(this);
  
  		this._object.onreadystatechange = function() {
  			if (bGecko && !bAsync) {
  				return;
  			}
  
  			// Synchronize state
  			oRequest.readyState   = oRequest._object.readyState;
  			fSynchronizeValues(oRequest);
  
  			// BUGFIX: Firefox fires unnecessary DONE when aborting
  			if (oRequest._aborted) {
  				// Reset readyState to UNSENT
  				oRequest.readyState = cXMLHttpRequest.UNSENT;
  
  				// Return now
  				return;
  			}
  
  			if (oRequest.readyState == cXMLHttpRequest.DONE) {
  				// Free up queue
  				delete oRequest._data;
  
  				// Uncomment these lines for bAsync
  				/**
  				 * if (bAsync) {
  				 * 	fQueue_remove(oRequest);
  				 * }
  				 */
  
  				fCleanTransport(oRequest);
  
  				// Uncomment this block if you need a fix for IE cache
  				/**
  				 * // BUGFIX: IE - cache issue
  				 * if (!oRequest._object.getResponseHeader("Date")) {
  				 * 	// Save object to cache
  				 * 	oRequest._cached  = oRequest._object;
  				 *
  				 * 	// Instantiate a new transport object
  				 * 	cXMLHttpRequest.call(oRequest);
  				 *
  				 * 	// Re-send request
  				 * 	if (sUser) {
  				 * 		if (sPassword) {
  				 * 			oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
  				 * 		} else {
  				 * 			oRequest._object.open(sMethod, sUrl, bAsync);
  				 * 		}
  				 *
  				 * 		oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified") || new window.Date(0));
  				 * 		// Copy headers set
  				 * 		if (oRequest._headers) {
  				 * 			for (var sHeader in oRequest._headers) {
  				 * 				// Some frameworks prototype objects with functions
  				 * 				if (typeof oRequest._headers[sHeader] == "string") {
  				 * 					oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
  				 * 				}
  				 * 			}
  				 * 		}
  				 * 		oRequest._object.onreadystatechange = function() {
  				 * 			// Synchronize state
  				 * 			oRequest.readyState   = oRequest._object.readyState;
  				 *
  				 * 			if (oRequest._aborted) {
  				 * 				//
  				 * 				oRequest.readyState = cXMLHttpRequest.UNSENT;
  				 *
  				 * 				// Return
  				 * 				return;
  				 * 			}
  				 *
  				 * 			if (oRequest.readyState == cXMLHttpRequest.DONE) {
  				 * 				// Clean Object
  				 * 				fCleanTransport(oRequest);
  				 *
  				 * 				// get cached request
  				 * 				if (oRequest.status == 304) {
  				 * 					oRequest._object  = oRequest._cached;
  				 * 				}
  				 *
  				 * 				//
  				 * 				delete oRequest._cached;
  				 *
  				 * 				//
  				 * 				fSynchronizeValues(oRequest);
  				 *
  				 * 				//
  				 * 				fReadyStateChange(oRequest);
  				 *
  				 * 				// BUGFIX: IE - memory leak in interrupted
  				 * 				if (bIE && bAsync) {
  				 * 					window.detachEvent("onunload", fOnUnload);
  				 * 				}
  				 *
  				 * 			}
  				 * 		};
  				 * 		oRequest._object.send(null);
  				 *
  				 * 		// Return now - wait until re-sent request is finished
  				 * 		return;
  				 * 	};
  				 */
  
  				// BUGFIX: IE - memory leak in interrupted
  				if (bIE && bAsync) {
  					window.detachEvent("onunload", fOnUnload);
  				}
  
  				// BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
  				if (nState != oRequest.readyState) {
  					fReadyStateChange(oRequest);
  				}
  
  				nState  = oRequest.readyState;
  			}
  		};
  	};
  
  	cXMLHttpRequest.prototype.send = function(vData) {
  		// Add method sniffer
  		if (cXMLHttpRequest.onsend) {
  			cXMLHttpRequest.onsend.apply(this, arguments);
  		}
  
  		if (!arguments.length) {
  			vData = null;
  		}
  
  		// BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit serialization required
  		// BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
  		// BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
  		if (vData && vData.nodeType) {
  			vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
  			if (!this._headers["Content-Type"]) {
  				this._object.setRequestHeader("Content-Type", "application/xml");
  			}
  		}
  
  		this._data = vData;
  
  		/**
  		 * // Add to queue
  		 * if (this._async) {
  		 * 	fQueue_add(this);
  		 * } else { */
  		fXMLHttpRequest_send(this);
  		 /**
  		 * }
  		 */
  	};
  
  	cXMLHttpRequest.prototype.abort = function() {
  		// Add method sniffer
  		if (cXMLHttpRequest.onabort) {
  			cXMLHttpRequest.onabort.apply(this, arguments);
  		}
  
  		// BUGFIX: Gecko - unnecessary DONE when aborting
  		if (this.readyState > cXMLHttpRequest.UNSENT) {
  			this._aborted = true;
  		}
  
  		this._object.abort();
  
  		// BUGFIX: IE - memory leak
  		fCleanTransport(this);
  
  		this.readyState = cXMLHttpRequest.UNSENT;
  
  		delete this._data;
  
  		/* if (this._async) {
  	 	* 	fQueue_remove(this);
  	 	* }
  	 	*/
  	};
  
  	cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
  		return this._object.getAllResponseHeaders();
  	};
  
  	cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
  		return this._object.getResponseHeader(sName);
  	};
  
  	cXMLHttpRequest.prototype.setRequestHeader  = function(sName, sValue) {
  		// BUGFIX: IE - cache issue
  		if (!this._headers) {
  			this._headers = {};
  		}
  
  		this._headers[sName]  = sValue;
  
  		return this._object.setRequestHeader(sName, sValue);
  	};
  
  	// EventTarget interface implementation
  	cXMLHttpRequest.prototype.addEventListener  = function(sName, fHandler, bUseCapture) {
  		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
  			if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) {
  				return;
  			}
  		}
  
  		// Add listener
  		this._listeners.push([sName, fHandler, bUseCapture]);
  	};
  
  	cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
  		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
  			if (oListener[0] == sName && oListener[1] == fHandler && oListener[2] == bUseCapture) {
  				break;
  			}
  		}
  
  		// Remove listener
  		if (oListener) {
  			this._listeners.splice(nIndex, 1);
  		}
  	};
  
  	cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
  		var oEventPseudo  = {
  			'type':             oEvent.type,
  			'target':           this,
  			'currentTarget':    this,
  			'eventPhase':       2,
  			'bubbles':          oEvent.bubbles,
  			'cancelable':       oEvent.cancelable,
  			'timeStamp':        oEvent.timeStamp,
  			'stopPropagation':  function() {},  // There is no flow
  			'preventDefault':   function() {},  // There is no default action
  			'initEvent':        function() {}   // Original event object should be initialized
  		};
  
  		// Execute onreadystatechange
  		if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) {
  			(this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
  		}
  
  
  		// Execute listeners
  		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
  			if (oListener[0] == oEventPseudo.type && !oListener[2]) {
  				(oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
  			}
  		}
  
  	};
  
  	//
  	cXMLHttpRequest.prototype.toString  = function() {
  		return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
  	};
  
  	cXMLHttpRequest.toString  = function() {
  		return '[' + "XMLHttpRequest" + ']';
  	};
  
  	/**
  	 * // Queue manager
  	 * var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
  	 * aQueueRunning = [];
  	 * function fQueue_add(oRequest) {
  	 * 	oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
  	 * 	//
  	 * 	setTimeout(fQueue_process);
  	 * };
  	 *
  	 * function fQueue_remove(oRequest) {
  	 * 	for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
  	 * 	if (bFound) {
  	 * 		aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
  	 * 	} else {
  	 * 		if (aQueueRunning[nIndex] == oRequest) {
  	 * 			bFound  = true;
  	 * 		}
  	 * }
  	 *
  	 * 	if (bFound) {
  	 * 		aQueueRunning.length--;
  	 * 	}
  	 *
  	 *
  	 * 	//
  	 * 	setTimeout(fQueue_process);
  	 * };
  	 *
  	 * function fQueue_process() {
  	 * if (aQueueRunning.length < 6) {
  	 * for (var sPriority in oQueuePending) {
  	 * if (oQueuePending[sPriority].length) {
  	 * var oRequest  = oQueuePending[sPriority][0];
  	 * oQueuePending[sPriority]  = oQueuePending[sPriority].slice(1);
  	 * //
  	 * aQueueRunning.push(oRequest);
  	 * // Send request
  	 * fXMLHttpRequest_send(oRequest);
  	 * break;
  	 * }
  	 * }
  	 * }
  	 * };
  	 */
  
  	// Helper function
  	function fXMLHttpRequest_send(oRequest) {
  		oRequest._object.send(oRequest._data);
  
  		// BUGFIX: Gecko - missing readystatechange calls in synchronous requests
  		if (bGecko && !oRequest._async) {
  			oRequest.readyState = cXMLHttpRequest.OPENED;
  
  			// Synchronize state
  			fSynchronizeValues(oRequest);
  
  			// Simulate missing states
  			while (oRequest.readyState < cXMLHttpRequest.DONE) {
  				oRequest.readyState++;
  				fReadyStateChange(oRequest);
  				// Check if we are aborted
  				if (oRequest._aborted) {
  					return;
  				}
  			}
  		}
  	}
  
  	function fReadyStateChange(oRequest) {
  		// Sniffing code
  		if (cXMLHttpRequest.onreadystatechange){
  			cXMLHttpRequest.onreadystatechange.apply(oRequest);
  		}
  
  
  		// Fake event
  		oRequest.dispatchEvent({
  			'type':       "readystatechange",
  			'bubbles':    false,
  			'cancelable': false,
  			'timeStamp':  new Date().getTime()
  		});
  	}
  
  	function fGetDocument(oRequest) {
  		var oDocument = oRequest.responseXML;
  		var sResponse = oRequest.responseText;
  		// Try parsing responseText
  		if (bIE && sResponse && oDocument && !oDocument.documentElement && oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
  			oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
  			oDocument.async       = false;
  			oDocument.validateOnParse = false;
  			oDocument.loadXML(sResponse);
  		}
  
  		// Check if there is no error in document
  		if (oDocument){
  			if ((bIE && oDocument.parseError != 0) || !oDocument.documentElement || (oDocument.documentElement && oDocument.documentElement.tagName == "parsererror")) {
  				return null;
  			}
  		}
  		return oDocument;
  	}
  
  	function fSynchronizeValues(oRequest) {
  		try { oRequest.responseText = oRequest._object.responseText;  } catch (e) {}
  		try { oRequest.responseXML  = fGetDocument(oRequest._object); } catch (e) {}
  		try { oRequest.status       = oRequest._object.status;        } catch (e) {}
  		try { oRequest.statusText   = oRequest._object.statusText;    } catch (e) {}
  	}
  
  	function fCleanTransport(oRequest) {
  		// BUGFIX: IE - memory leak (on-page leak)
  		oRequest._object.onreadystatechange = new window.Function;
  	}
  
  	// Internet Explorer 5.0 (missing apply)
  	if (!window.Function.prototype.apply) {
  		window.Function.prototype.apply = function(oRequest, oArguments) {
  			if (!oArguments) {
  				oArguments  = [];
  			}
  			oRequest.__func = this;
  			oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
  			delete oRequest.__func;
  		};
  	}
  
  	// Register new object with window
  	window.XMLHttpRequest = cXMLHttpRequest;
  
  })();
  
  /**
  * xhr-ajax.js Copyright (C) 2013 Craig Roberts (http://craig0990.co.uk)
  *
  * Licensed under the MIT License (http://mit-license.org) 
  */
  (function (root, factory) {
      if (typeof exports === 'object') {
          // Node. Does not work with strict CommonJS, but
          // only CommonJS-like enviroments that support module.exports,
          // like Node.
          module.exports = factory();
      } else if (typeof define === 'function' && define.amd) {
          // AMD. Register as an anonymous module.
          define(factory);
      } else {
          // Browser globals (root is window)
          root.ajax = factory();
    }
  }(this, function () {
      function ajax(url, options) {
          options = options || {};
          options.method = options.method || 'GET';
          options.headers = options.headers || {};
          options.success = options.success || function() {};
          options.error = options.error || function() {};
          options.async = typeof options.async === 'undefined' ? true : options.async;
  
          var client = new XMLHttpRequest();
          client.open(options.method, url);
  
          for (var i in options.headers) {
              if (options.headers.hasOwnProperty(i)) {
                  client.setRequestHeader(i, options.headers[i]);
              }
          }
  
          client.send(options.data);
          client.onreadystatechange = function() {
              if (this.readyState == 4 && this.status == 200) {
                  options.success(this.responseText, this);
              } else if (this.readyState == 4) {
                  options.error(this.status, this.statusText, this);
              }
          };
  
          return client;
      }
      
      return ajax;
  }));
  
  /* global ajax */
  
  'use strict';
  
  var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
  
  var FilePreviews = (function () {
    function FilePreviews(options) {
      _classCallCheck(this, FilePreviews);
  
      var API_URL = 'https://api.filepreviews.io/v2';
      var opts = options || {};
  
      this.apiUrl = opts.apiUrl || API_URL;
      this.apiKey = opts.apiKey;
      this.debug = opts.debug || false;
      this._ajax = ajax;
  
      if (!opts.apiKey) {
        throw new Error('Missing required apiKey.');
      }
    }
  
    _createClass(FilePreviews, [{
      key: 'log',
      value: function log(msg) {
        if (this.debug) {
          console.log(msg);
        }
      }
    }, {
      key: 'generate',
      value: function generate(url, options, callback) {
        if (arguments.length === 2) {
          if (Object.prototype.toString.call(options) === '[object Function]') {
            callback = options;
          }
        } else if (arguments.length === 1) {
          options = {};
        }
  
        this.request(this.apiUrl + '/previews/', {
          method: 'POST',
          data: JSON.stringify(this.getAPIRequestData(url, options))
        }, function (err, result) {
          if (callback) {
            callback(err, result);
          }
        });
      }
    }, {
      key: 'retrieve',
      value: function retrieve(previewId, callback) {
        this.request(this.apiUrl + '/previews/' + previewId + '/', {
          method: 'GET'
        }, function (err, result) {
          if (callback) {
            callback(err, result);
          }
        });
      }
    }, {
      key: 'request',
      value: function request(url, options, callback) {
        var _this = this;
  
        var data = undefined;
        var _options = options || {};
  
        var onSuccess = function onSuccess(response, xhr) {
          _this.log('API request success: ' + xhr.status + ' ' + xhr.statusText);
  
          data = JSON.parse(response);
          _this.log('API request response: ' + response);
  
          callback(null, data);
        };
  
        var onError = function onError(status, message, xhr) {
          try {
            data = JSON.parse(xhr.responseText);
          } catch (e) {
            data = xhr.responseText;
          }
  
          if (status === 201) {
            onSuccess(xhr.responseText, xhr);
          } else {
            _this.log('API request error: ' + status);
            callback(data);
          }
        };
  
        var requestOptions = {
          headers: this.getAPIRequestHeaders(),
          method: _options.method || 'GET',
          success: onSuccess,
          error: onError
        };
  
        if (_options.data) {
          requestOptions.data = _options.data;
        }
  
        this.log('API request to: ' + url);
  
        this._ajax(url, requestOptions);
      }
    }, {
      key: 'getAPIRequestHeaders',
      value: function getAPIRequestHeaders() {
        return {
          Accept: 'application/json',
          'Content-Type': 'application/json',
          Authorization: 'Basic ' + btoa(this.apiKey) + ':'
        };
      }
    }, {
      key: 'getAPIRequestData',
      value: function getAPIRequestData(url, options) {
        var size = undefined;
  
        if (arguments.length === 2) {
          if (Object.prototype.toString.call(options) === '[object Function]') {
            options = {};
          }
        } else if (arguments.length === 1) {
          options = {};
        }
  
        if (options) {
          options.url = url;
  
          if (options.size) {
            size = '';
  
            if (options.size.width) {
              size = options.size.width;
            }
  
            if (options.size.height) {
              size = size + 'x' + options.size.height;
            }
  
            options.sizes = [size];
          }
        }
  
        return options;
      }
    }]);
  
    return FilePreviews;
  })();