/**
 * @namespace This contains methods to control and write Flash objects.
 * @author Tom McCourt / Oliver Bishop
 * @version 0.1.2
 * @changeLog Fixed embed method.
 * @changeLog Added callback parameter to the Flash.add method.
 * @changeLog Added Flash version as a parameter.
 * @changeLog Improved the parsing of parameters to reset the Flash parameters if an empty object literal is used.
 */

UKISA.namespace("UKISA.widget.Flash");

/**
 * Create a modal instance.
 *
 * You will need to ensure that this has the following entry in the UKISA locale settings.
 * Flash: {
 *	supports: "8.0.0", // Default supported version.	
 *	width: 512,	// Default width.
 *	height: 288, // Default width.
 *	flashDir: "/web/flash/",
 *	movieDir: "/web/movies/",
 *	params: { // Default params.
 *		"quality": "high",
 *		"scale": "noscale",
 *		"pluginspage": "http://www.macromedia.com/go/getflashplayer",
 *		"wmode": "transparent"
 *	},
 *	vars: { // Default variables.
 *		"MM_ComponentVersion": "1",
 *		"skinName": "/web/flash/Halo_Skin_3",
 *		"autoPlay": "false",
 *		"autoRewind": true
 *	},
 *	skins: {
 *		"Halo_Skin_3": {
 *			top: 11,
 *			right: 11,
 *			bottom: 40,
 *			left: 11
 *		}
 *	},
	attributes: null,
	callback: null
 *
 * This will allow you to change the global settings.
 */
UKISA.widget.Flash = {
	locale: null, // The UKISA l10n settings.
	context: null, // Store the parameters for the current object.
	/**
	 * Create a modal Flash viewer.
	 *
	 * @example <a href="#video-holder" onclick="UKISA.widget.Flash.Modal(event, 'ecosure_overview.flv', {autoPlay: true});">
	 */
	modal: function(ev, file, width, height, vars, params) {
		var container, locale, Event, Dom;

		// Shorthands.
		Event = YAHOO.util.Event;
		Dom = YAHOO.util.Dom;

		// Stop linkage.
		Event.stopEvent(ev);
		Event.preventDefault(ev);
		

		// Setup the parameters and configuration stuff.
		if (!UKISA.widget.Flash.locale) {
			UKISA.widget.Flash.locale = UKISA.locale.get("widget.Flash");
		}

		locale = UKISA.widget.Flash.locale;
		this.configure(file, "ukisa-flash-modal-loading", width, height, vars, params);

		// Create a modal instance.
		container = new UKISA.widget.Modal("ukisa-flash-modal");
		
		// This is to remove the Flash movie to stop it peeking through the modal when it is closed.
		container.hideEvent.subscribe(function() {
			UKISA.widget.Flash.remove("ukisa-flash-modal-loading");
		});	

		Dom.setStyle(container.body, "width", this.context.width + "px");
		Dom.setStyle(container.body, "height", this.context.height + "px");

		container.show();

		// Sort out the Flash.
		if (typeof swfobject !== "undefined") {
			this.embed(file);
		} else {
			container.setBody((function() {
				var a = document.createElement("p");
				a.className = "error";
				a.innerHTML = "Sorry, there was a problem, please try again.";

				return a;
			})());
		}	

		return container;
	},
	/**
	 * For each time the Flash embed method is called, the default configuration parameters must be cloned
	 * and a normal assignment from the config to the context property will be passed by reference not value, so 
	 * the config must be cloned. This gets called twice for the Flash.modal as the width/height is required to
	 * calculate the size of the modal window when it has finished being written out. It's more strung out but it should mean that 
	 * the modal will size itself to the Flash movie dimensions making it easier to develop.
	 *
	 * @param {ObjectLiteral} vars			The Flash vars.
	 * @param {ObjectLiteral} params		The Flash params.
	 */
	configure: function(file, el, width, height, version, vars, params, attributes, callback) {
		var clone, i, count;

		this.context = null;

		// This counts the properties in the vars, params, attributes so that if they are passed
		// in as {} they will reset the objects.
		// If null is passed in it is assumed that it will use the default set in the UKISA locale
		// and will not modify them.

		count = function(o) {
			var i, key;

			i = 0;

			for (key in o) {
				if(o.hasOwnProperty(key)) {
					i++;
				}
			}

			return i;
		};

		clone = function(o) {
			if(typeof(o) != "object") return o;
			if(o == null) return o;

			var newO = new Object();

			for(var i in o) {
				newO[i] = clone(o[i]);
			}
			return newO;
		};

		this.context = new clone(this.locale);

		if (width && typeof width === "number") {
			this.context.width = width;
		}

		if (height && typeof height === "number") {
			this.context.height = height;
		}

		// Do a variable shim incase no width or height properties are set but vars, params are.
		if (typeof width === "object") {
			vars = width;
		}
		if (typeof height === "object") {
			params = height;
		}
		
		// Update the Flash vars.
		if (count(vars)) {
			for (i in vars) {
				if (typeof this.context.vars[i] !== "undefined") {
					this.context.vars[i] = vars[i];
				}
			}
		} else if (typeof vars !== "undefined" && vars !== null) {
			this.context.vars = {};
		}

		// Update the Flash params.
		if (count(params)) {
			for (i in params) {
				if (typeof this.context.params[i] !== "undefined") {
					this.context.params[i] = params[i];
				}
			}
		} else if (params !== null) {
			this.context.params = {};
		}

		// Update the Flash attributes
		if (count(attributes)) {
			for (i in attributes) {
				this.context.attributes[i] = attributes[i];
			}
		} else if (attributes !== null) {
			this.context.attributes = {};
		}

		// Update the Flash callback
		if (callback !== "undefined") {
			this.context.callback = callback;
		}

		// Set the Flash version required.
		if (version) {
			this.context.supports = version;
		}

		if (file.toLowerCase().indexOf(".flv") !== -1) {
			// Update the Flash vars to use the stream name
			this.context.vars.streamName = this.context.movieDir + file.substring(0, file.indexOf("."));

			// Update the size if a player skin is used
			this.size(file, width, height);
		}

		this.context.canvas = el;
	},
	/**
	 * Apply a click event to a placeholder for a flash movie that will replace the placeholder.
	 *
	 * @example 
	 * &ltimg src="/files/media/images/canvas/ecosure/ecosure-landing-start-frame.jpg" id="flasher" width="231" height="127" /&gt;
	 * UKISA.widget.Flash.swap("flash_movie.swf", "flash-placeholder");
	 */
	swap: function(file, el, width, height, version, vars, params, attributes, callback) {
		var canvas, instance;

		canvas = document.getElementById(el);

		if (canvas) {

			// Use existing image width and height attributes if they are specified.
			if (canvas.width && canvas.height) {
				width = canvas.width;
				height = canvas.height;
			}

			instance = this;

			YAHOO.util.Event.addListener(canvas, "click", function() {	
				// Setup the parameters and configuration stuff.
				if (!UKISA.widget.Flash.locale) {
					UKISA.widget.Flash.locale = UKISA.locale.get("widget.Flash");
				}

				locale = UKISA.widget.Flash.locale;

				instance.configure(file, el, width, height, version, vars, params);

				instance.add(file, el, width, height, version, vars, params, attributes, callback);
			});
		}
	},
	/**
	 * Insert a Flash file into the site.
	 */
	add: function(file, el, width, height, version, vars, params, attributes, callback) {
		// Setup the parameters and configuration stuff.
		if (!UKISA.widget.Flash.locale) {
			UKISA.widget.Flash.locale = UKISA.locale.get("widget.Flash");
		}

		locale = UKISA.widget.Flash.locale;
		this.configure(file, el, width, height, version, vars, params, attributes, callback);

		// Pop the file onto the page.
		this.embed(file);
	},
	/**
	 * Embed a either a Flash movie of FLV by specifying the file extension e.g. video.flv.
	 */
	embed: function(file, el, width, height, version, vars, params, attributes, callback) {
		var context = this.context;

		// Setup the parameters and configuration stuff.
		if (!UKISA.widget.Flash.locale) {
			UKISA.widget.Flash.locale = UKISA.locale.get("widget.Flash");
		}
		this.configure(file, el, width, height, version, vars, params, attributes, callback);

		// Detect if this is trying to get a Flash FLV.
		if (file.toLowerCase().indexOf(".flv") !== -1) {
			return this.embedVideo(file);
		} else {
			return this.embedFlash(file);
		}
	},
	/**
	 * Embed a Flash SWF.
	 */
	embedVideo: function(file) {
		var context = this.context;

		swfobject.embedSWF(
			context.flashDir + "player.swf",
			context.canvas, 
			context.width, 
			context.height, 
			context.supports,
			null,
			context.vars,
			context.params,
			context.attributes,
			context.callback
		);
	},
	/**
	 * Embed a Flash SWF.
	 */
	embedFlash: function(file) {
		var context = this.context;

		swfobject.embedSWF(
			context.flashDir + file,
			context.canvas, 
			context.width, 
			context.height, 
			context.supports,
			null,
			context.vars,
			context.params,
			context.attributes,
			context.callback
		);
	},
	/**
	 * Safely removes a Flash movie from the page.
	 * @param {String} el Flash placeholder.
	 */
	remove: function(el) {
		if (typeof swfobject !== "undefined") {
			swfobject.removeSWF(el);
		}
	},
	/**
	 * This is weird but useful. When passing in the FLV dimension, only the actual movie size is required.
	 * If a skin with a border (like the Halo skin) is used then there is additional padding around the FLV
	 * that needs to be taken into account when creating the Flash object. This looks up the skin name that is
	 * stored and adds the additional dimensions to the width and height.
	 *
	 * @param {String} movie				Name of the movie with file extension.
	 * @param {Int} width					Width of the Flash movie.
	 * @param {Int} height					Height of the Flash movie.
	 * @param {ObjectLiteral} options		The options - not sure why or how anymore... :(
	 */
	size: function(movie, width, height) {
		// Strip off the path to get only the skin name.
		var skin = this.context.vars.skinName.split("/").pop();

		if (typeof this.locale.skins[skin] !== "undefined") {
			skin = this.locale.skins[skin];
			this.context.width += skin.left + skin.right;
			this.context.height += skin.top + skin.bottom;
		}
	},
	/**
	 * Log for Firebug debugging.
	 *
	 * @param {String} s Message log.
	 */
	log: function(s) {
		if (window.console) {
			console.log(s);
		}
	}
};