var Assert = require('assert');

/**
* A class represesting an API error.
*
* @memberof module:libresignage/api
*/
class APIError extends Error {
	/**
	* Construct the Error object.
	*
	* @constructor
	*
	* @param {object} request The received API request object.
	*/
	constructor(request) {
		Assert.ok(request instanceof XMLHttpRequest);
		Assert.ok(request.status !== 200);

		super('', 0, 0);
		if (Error.captureStackTrace) {
			Error.captureStackTrace(this, APIError);
		}

		this.request = request;
		if (
			this.request.getResponseHeader('Content-Type') === 'application/json'
			&& this.request.responseText !== ''
		) {
			this.data = JSON.parse(this.request.responseText);
		} else {
			this.data = null;
		}
	}

	/**
	* Check whether the HTTP status code of an APIError matches 'status'.
	*
	* @param {number} status The numerical HTTP status code to compare against.
	*/
	is(status) { return this.request.status === status; }

	/**
	* Get the HTTP status code of an APIError.
	*/
	get_status() { return this.request.status }

	/**
	* Get the error message of an APIError. If the APIError doesn't
	* have an error message, an empty string is returned.
	*/
	get_message() { return (this.data.e_msg != null) ? this.data.e_msg: ''; }

	/**
	* Get a string representation of an APIError.
	*/
	toString() {
		let ret = '';
		if (this.data !== null) {
			ret =  `\nAPI Error (${this.request.status}): ${this.data.e_msg}\n`;
			ret += `\tat ${this.data.thrown_at}\n`;
			ret += 'Server stack trace:\n';
			ret += `\t${this.data.e_trace.replace('\n', '\n\t')}\n\n`;
		} else {
			ret = `\nAPI Error (${this.request.status})\n`;
		}
		return ret;
	}
}
module.exports = APIError;
