var Assert = require('assert');
var SlideListIterator = require('libresignage/queue/SlideListIterator');

/**
* Callback for filtering SlideLists. The callback definition
* is equal to the one Array.prototype.filter() uses.
*
* @callback SlideList_filter_callback
*
* @param {mixed}  element The current element being processed.
* @param {number} index   The index of the current element.
* @param {array}  array   The array being filtered.
*
* @return {boolean} True to keep the element, false to remove it.
*/

/**
* Class representing a list of slides. Implements the Iterable interface.
*
* @memberof module:libresignage/queue
*/
class SlideList {
	/**
	* Construct a new SlideList object.
	*/
	constructor() {
		this.slides = [];
	}

	/**
	* Iterable interface compliant @@iterator function.
	*
	* @see {@link https://www.ecma-international.org/ecma-262/6.0/#sec-iterable-interface}
	*/
	[Symbol.iterator](wrap = false, step = 1, start_at = 0) {
		return new SlideListIterator(this, wrap, step, start_at);
	}

	/**
	* A wrapper for Array.prototype.filter() to filter a SlideList object.
	*
	* @param {SlideList_filter_callback} callback The filter callback function.
	*
	* @return {SlideList} The filtered SlideList object.
	*/
	filter(callback, thisArg) {
		let sl = new SlideList();
		sl.slides = this.slides.filter(callback, thisArg);
		return sl;
	}

	/**
	* Filter a SlideList against a dictionary.
	* 
	* If all of the key-value pairs in the supplied dictionary also exist in
	* a slide's data, the slide is preserved. Otherwise it's filtered out.
	*
	* @param {object} dict The dictionary to compare against.
	*
	* @param {SlideList} The filtered SlideList object.
	*/
	filter_dict(dict) {
		return this.filter(
			function(slide) {
				for (let key in dict) {
					if (!slide.has(key) || slide.get(key) !== dict[key]) {
						return false;
					}
				}
				return true;
			}
		);
	}

	/**
	* Add a Slide to a SlideList.
	*
	* @param {Slide} s The Slide object to add.
	*/
	add(s) { this.slides.push(s); }
}
module.exports = SlideList;
