var SlideList = require('libresignage/queue/SlideList');
var APIEndpoints = require('libresignage/api/APIEndpoints');
var Assert = require('assert');
var Slide = require('libresignage/slide/Slide');

/**
* Class representing a slide queue.
*
* @memberof module:libresignage/queue
*/
class Queue {
	/**
	* Construct a Queue object.
	*
	* @param {string} api An initialized APIInterface object.
	*
	* @throws {AssertionError} If api == null.
	*/
	constructor(api) {
		Assert.ok(api != null, "API object can't be null.");
		this.api = api;

		this.name = null;
		this.owner = null;
		this.slidelist = null;
	}

	/**
	* Load a queue and all of its slides via the API.
	*
	* @param {string} name The name of the queue to load.
	*
	* @return {Promise} A Promise that resolves once all the slides are loaded.
	*
	* @throws {AssertionError} If name == null.
	*/
	async load(name) {
		Assert.ok(name != null, "'name' cannot be null.");
		let promises = [];
		let resp = await this.api.call(
			APIEndpoints.QUEUE_GET,
			{'name': name}
		);

		this.name = name;
		this.owner = resp.queue.owner;
		this.slidelist = new SlideList();

		for (let s of resp.queue.slide_ids) {
			let tmp = new Slide(this.api);
			promises.push(tmp.load(s, false, false));
			this.slidelist.add(tmp);
		}

		return Promise.all(promises);
	}

	/**
	* Create a new empty queue via the API.
	*
	* @param {string} name The name of the new queue.
	*
	* @throws {AssertionError} If 'name' == null.
	*/
	async create(name) {
		Assert.ok(name != null, "'name' cannot be null.");
		await this.api.call(
			APIEndpoints.QUEUE_CREATE,
			{ 'name': name }
		);
		await this.load(name);
	}

	/**
	* Remove the loaded queue via the API.
	*
	* @throws {AssertionError} If no queue is loaded.
	*/
	async remove() {
		Assert.ok(this.name != null, "No queue loaded.");
		await this.api.call(
			APIEndpoints.QUEUE_REMOVE,
			{ 'name': this.name }
		);
	}

	/**
	* Refresh the loaded queue data via the API.
	*
	* @throws {AssertionError} If no queue is loaded.
	*/
	async update() {
		Assert.ok(this.name != null, "No queue loaded.");
		await this.load(this.name);
	}

	/**
	* Check whether the loaded queue has a slide.
	*
	* @param {string} id The slide ID to search for.
	*
	* @return {boolean} True if the matching slide exists, false otherwise.
	*
	* @throws {AssertionError} If no queue is loaded.
	*/
	has_slide(id) {
		Assert.ok(this.name != null, "No queue loaded.");
		for (let s of [...this.slidelist]) {
			if (s.get('id') === id) {
				return true;
			}
		}
		return false;
	}

	/**
	* Get the name of a queue.
	*
	* @return {string|null} The name of the queue.
	*/
	get_name() { return this.name; }

	/**
	* Get the owner of a queue.
	*
	* @param {string|null} The owner of the queue.
	*/
	get_owner() { return this.owner; }

	/**
	* Get the internal SlideList object of a queue.
	*
	* @return {SlideList|null} The SlideList object.
	*/
	get_slidelist() { return this.slidelist; }

	/**
	* Get a list of all queue names via the API.
	*
	* @return {string[]} An array of queue names.
	*/
	static async get_queues(api) {
		return (await api.call(APIEndpoints.QUEUE_LIST, null)).queues;
	}
}
module.exports = Queue;
