/*
 * ManifestLoader
 * Visit http://createjs.com/ for documentation, updates and examples.
 *
 *
 * Copyright (c) 2012 gskinner.com, inc.
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @module PreloadJS
 */

// namespace:
this.createjs = this.createjs || {};

(function () {
	"use strict";

	// constructor
	/**
	 * A loader for JSON manifests. Items inside the manifest are loaded before the loader completes. To load manifests
	 * using JSONP, specify a {{#crossLink "LoadItem/callback:property"}}{{/crossLink}} as part of the
	 * {{#crossLink "LoadItem"}}{{/crossLink}}.
	 *
	 * The list of files in the manifest must be defined on the top-level JSON object in a `manifest` property. This
	 * example shows a sample manifest definition, as well as how to to include a sub-manifest.
	 *
	 * 		{
	 * 			"path": "assets/",
	 *	 	    "manifest": [
	 *				"image.png",
	 *				{"src": "image2.png", "id":"image2"},
	 *				{"src": "sub-manifest.json", "type":"manifest", "callback":"jsonCallback"}
	 *	 	    ]
	 *	 	}
	 *
	 * When a ManifestLoader has completed loading, the parent loader (usually a {{#crossLink "LoadQueue"}}{{/crossLink}},
	 * but could also be another ManifestLoader) will inherit all the loaded items, so you can access them directly.
	 *
	 * Note that the {{#crossLink "JSONLoader"}}{{/crossLink}} and {{#crossLink "JSONPLoader"}}{{/crossLink}} are
	 * higher priority loaders, so manifests <strong>must</strong> set the {{#crossLink "LoadItem"}}{{/crossLink}}
	 * {{#crossLink "LoadItem/type:property"}}{{/crossLink}} property to {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}.
	 * @class ManifestLoader
	 * @param {LoadItem|Object} loadItem
	 * @extends AbstractLoader
	 * @constructor
	 */
	function ManifestLoader(loadItem) {
		this.AbstractLoader_constructor(loadItem, null, createjs.AbstractLoader.MANIFEST);

		// protected properties
		/**
		 * An internal {{#crossLink "LoadQueue"}}{{/crossLink}} that loads the contents of the manifest.
		 * @property _manifestQueue
		 * @type {LoadQueue}
		 * @private
		 */
		this._manifestQueue = null;
	};

	var p = createjs.extend(ManifestLoader, createjs.AbstractLoader);
	var s = ManifestLoader;

	// static properties
	/**
	 * The amount of progress that the manifest itself takes up.
	 * @property MANIFEST_PROGRESS
	 * @type {number}
	 * @default 0.25 (25%)
	 * @private
	 * @static
	 */
	s.MANIFEST_PROGRESS = 0.25;

	// static methods
	/**
	 * Determines if the loader can load a specific item. This loader can only load items that are of type
	 * {{#crossLink "AbstractLoader/MANIFEST:property"}}{{/crossLink}}
	 * @method canLoadItem
	 * @param {LoadItem|Object} item The LoadItem that a LoadQueue is trying to load.
	 * @returns {Boolean} Whether the loader can load the item.
	 * @static
	 */
	s.canLoadItem = function (item) {
		return item.type == createjs.AbstractLoader.MANIFEST;
	};

	// public methods
	p.load = function () {
		this.AbstractLoader_load();
	};

	// protected methods
	p._createRequest = function() {
		var callback = this._item.callback;
		if (callback != null) {
			this._request = new createjs.JSONPLoader(this._item);
		} else {
			this._request = new createjs.JSONLoader(this._item);
		}
	};

	p.handleEvent = function (event) {
		switch (event.type) {
			case "complete":
				this._rawResult = event.target.getResult(true);
				this._result = event.target.getResult();
				this._sendProgress(s.MANIFEST_PROGRESS);
				this._loadManifest(this._result);
				return;
			case "progress":
				event.loaded *= s.MANIFEST_PROGRESS;
				this.progress = event.loaded / event.total;
				if (isNaN(this.progress) || this.progress == Infinity) { this.progress = 0; }
				this._sendProgress(event);
				return;
		}
		this.AbstractLoader_handleEvent(event);
	};

	p.destroy = function() {
		this.AbstractLoader_destroy();
		this._manifestQueue.close();
	};

	/**
	 * Create and load the manifest items once the actual manifest has been loaded.
	 * @method _loadManifest
	 * @param {Object} json
	 * @private
	 */
	p._loadManifest = function (json) {
		if (json && json.manifest) {
			var queue = this._manifestQueue = new createjs.LoadQueue();
			queue.on("fileload", this._handleManifestFileLoad, this);
			queue.on("progress", this._handleManifestProgress, this);
			queue.on("complete", this._handleManifestComplete, this, true);
			queue.on("error", this._handleManifestError, this, true);
			queue.loadManifest(json);
		} else {
			this._sendComplete();
		}
	};

	/**
	 * An item from the {{#crossLink "_manifestQueue:property"}}{{/crossLink}} has completed.
	 * @method _handleManifestFileLoad
	 * @param {Event} event
	 * @private
	 */
	p._handleManifestFileLoad = function (event) {
		event.target = null;
		this.dispatchEvent(event);
	};

	/**
	 * The manifest has completed loading. This triggers the {{#crossLink "AbstractLoader/complete:event"}}{{/crossLink}}
	 * {{#crossLink "Event"}}{{/crossLink}} from the ManifestLoader.
	 * @method _handleManifestComplete
	 * @param {Event} event
	 * @private
	 */
	p._handleManifestComplete = function (event) {
		this._loadedItems = this._manifestQueue.getItems(true);
		this._sendComplete();
	};

	/**
	 * The manifest has reported progress.
	 * @method _handleManifestProgress
	 * @param {ProgressEvent} event
	 * @private
	 */
	p._handleManifestProgress = function (event) {
		this.progress = event.progress * (1 - s.MANIFEST_PROGRESS) + s.MANIFEST_PROGRESS;
		this._sendProgress(this.progress);
	};

	/**
	 * The manifest has reported an error with one of the files.
	 * @method _handleManifestError
	 * @param {ErrorEvent} event
	 * @private
	 */
	p._handleManifestError = function (event) {
		var newEvent = new createjs.Event("fileerror");
		newEvent.item = event.data;
		this.dispatchEvent(newEvent);
	};

	createjs.ManifestLoader = createjs.promote(ManifestLoader, "AbstractLoader");

}());
