/*
Differences with SWFObject:
FlashReplaces allows you to define a flash replacement for multiple objects,
essentially you create a 'class' that gets used for similar content.

You can sepcify a wider range of objects for the target content, instead of just an ID.
'target' takes the form of a single DOM node, or an Array of them:

Additional optional paramaters, sendMode, insertionPoint
	- sendMode sends the original source as either the 'URL' (with ID provided if there is one) or 'HTML'
	- insertionPoint defines where the flash object gets added; 'replace', 'before', 'after', 'append', 'prepend'

*/

// outerXHTML addon to innerXHTML
function outerXHTML($source) {
	if (typeof($source) === 'string') {
		$source = document.getElementById($source);
	}
	if (!($source.nodeType === 1) && !($source.nodeType === 3)) {
		return false;
	}

	var container = document.createElement('DIV');
	$source.parentNode.insertBefore(container, $source);
	container.appendChild($source);

	var output = innerXHTML(container);

	container.parentNode.insertBefore($source, container);
	container.parentNode.removeChild(container);

	return output;
}

function debug(message) {
	if (!window.console) {
		alert(message);
	} else {
		console.log(message);
	}
}

// swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, attributes)
function FlashReplace(swfUrl, target, width, height, version, sendMode, insertionPoint, expressInstallSwfurl, flashvars, params, attributes, installNoteInsertionPoint) {

	var FlashReplacePub = {};

// ------------ Public Variables ------------
	//debug(swfUrl+", "+target+", "+width+", "+height+", "+version+", "+sendMode+", "+insertionPoint+", "+expressInstallSwfurl+", "+flashvars+", "+params+", "+attributes)

	// Required
	/*
	swfUrl
	width
	height
	version
	target */

	// Optional
	FlashReplacePub.sendMode = sendMode || false; // false, 'URL', 'HTML'
	if (insertionPoint) {
		FlashReplacePub.insertionPoint = insertionPoint;
		FlashReplacePub.insertionPoint.position = insertionPoint.position || "replace"; // 'replace', 'before', 'after', 'append', 'prepend'
		FlashReplacePub.insertionPoint.element = insertionPoint.element || false; // false, DOM node refrence
	} else {
		FlashReplacePub.insertionPoint = insertionPoint || {"position": "replace", "element": false};
	}

	FlashReplacePub.expressInstallSwfurl = expressInstallSwfurl || false;
	FlashReplacePub.flashvars = flashvars || false;
	FlashReplacePub.params = params || false;
	FlashReplacePub.attributes = attributes || false;

	if (installNoteInsertionPoint) {
		FlashReplacePub.installNoteInsertionPoint = installNoteInsertionPoint;
		if (installNoteInsertionPoint.element) {
			FlashReplacePub.installNoteInsertionPoint.element = installNoteInsertionPoint.element;
			FlashReplacePub.installNoteInsertionPoint.position = "append";
		} else {
			FlashReplacePub.installNoteInsertionPoint.element = false; // false, DOM node refrence
			FlashReplacePub.installNoteInsertionPoint.position = "after"; // 'replace', 'before', 'after', 'append', 'prepend'
		}		
	} else {
		FlashReplacePub.installNoteInsertionPoint = insertionPoint || {"position": "after", "element": false};
	}

	// Events
	FlashReplacePub.ready = function () {};
	FlashReplacePub.embedded = function () {};

	// Properties
	if (!FlashReplace.flashObjects) {
		FlashReplace.flashObjects = []; // Global flashObjects (all)
	}
	var flashObjects = []; // Local flashObjects (specific to subclass)


// ------------ Private Variables ------------

	FlashReplace.DynamicIdCount = 0;

	var setupDone = false;

	var installHtml = '<p class="flash-info">Installing the latest <a href="http://www.adobe.com/go/getflashplayer">Adobe Flash plugin</a> will enhance this content.</p>';
// ------------ Public Methods ------------

	FlashReplacePub.setup = function () {
/*
		if (!swfUrl) {
			debug("Please specify the location of your swf with 'swfUrl'");
		}
		if (!width) {
			debug("Please specify a 'width'");
		}
		if (!height) {
			debug("Please specify a 'height'");
		}
		if (!version) {
			debug("Please specify the required version of your swf with 'version'");
		}
		if (!target) {
			debug("Please specify a 'target'");
		}
*/

		var FO;
		if (typeof target === "object") {
			// Array
			for (var i in target) if (target.hasOwnProperty(i)) {
				FO = new FlashReplacePub.FlashObject(target[i]);
				flashObjects.push(FO);
				FlashReplace.flashObjects.push(FO);
			}
		} else {
			// DOM Node
			FO = new FlashReplacePub.FlashObject(target);
			flashObjects.push(FO);
			FlashReplace.flashObjects.push(FO);
		}

		setupDone = true;
		FlashReplacePub.ready();
	};


	FlashReplace.FlashObjectJavaScriptFunction = function (functionName, objectId, params) {
		// Split the functionName if it's namespaced
		var functionArray = functionName.split(".");

		for (var i = 0; i < FlashReplace.flashObjects.length; i++) {
			if (FlashReplace.flashObjects[i].id === objectId) {

				// Add each element of namespaced function
				var functionToCall = FlashReplace.flashObjects[i];
				for (var i = 0; i < functionArray.length; i++) {
					functionToCall = functionToCall[functionArray[i]];
				}

				return functionToCall(params);
			}
		}
	};

	FlashReplacePub.flashObjects = function (func) {
		for (var i = 0; i < flashObjects.length; i++) {
			func(flashObjects[i]);
		}
	};

	FlashReplacePub.embed = function () {
		if (!setupDone) {
			FlashReplacePub.setup();
		}

		for (var i = 0; i < flashObjects.length; i++) {
			flashObjects[i].embed();
		}

		FlashReplacePub.embedded();
	};

	FlashReplacePub.FlashObject = function (targetNode) {

		var FlashObjectPub = {};

		// Get params from source object
		FlashObjectPub.swfUrl = swfUrl;
		FlashObjectPub.width = width;
		FlashObjectPub.height = height;
		FlashObjectPub.version = version;

		FlashObjectPub.flashvars = (typeof FlashReplacePub.flashvars === "object") ? new FlashReplace.cloneObject(FlashReplacePub.flashvars) : FlashReplacePub.flashvars;
		FlashObjectPub.params = (typeof FlashReplacePub.params === "object") ? new FlashReplace.cloneObject(FlashReplacePub.params) : FlashReplacePub.params;
		FlashObjectPub.attributes = (typeof FlashReplacePub.attributes === "object") ? new FlashReplace.cloneObject(FlashReplacePub.attributes) : FlashReplacePub.attributes;
		FlashObjectPub.sendMode = FlashReplacePub.sendMode;
		FlashObjectPub.insertionPoint = (typeof FlashReplacePub.insertionPoint === "object") ? new FlashReplace.cloneObject(FlashReplacePub.insertionPoint) : FlashReplacePub.insertionPoint;

		FlashObjectPub.targetNode = targetNode;

		var id = targetNode.getAttribute("id");

		// Events
		FlashObjectPub.embedded = function () {};

		// Methods
		FlashObjectPub.embed = function () {

			if (swfobject.hasFlashPlayerVersion(this.version)) {
				// Setup sendMode flashvars
				switch (FlashObjectPub.sendMode) {
				case "URL":
					this.addFlashVars("FlashReplacePageLocation", encodeURIComponent(window.location));
					if (id) {
						this.addFlashVars("FlashReplaceTargetObjectId", encodeURIComponent(id));
					}
					break;
				case "HTML":
					this.addFlashVars("FlashReplaceHtmlContent", encodeURIComponent(outerXHTML(this.targetNode)));
					break;
				}

				var insertionElement;

				if (this.insertionPoint.element) {
					insertionElement = this.insertionPoint.element;
				} else {
					insertionElement = this.targetNode;
				}

				// swfobject replaces an element, so position the insertion point (and set ID) where the flash object is to be added
				var insersionPointId;				

				if (this.insertionPoint.position === "replace") {
					// Replace, give the 'insertionElement' then replacing ID
					if (!insertionElement.getAttribute("id")) {
						insertionElement.setAttribute("id", FlashReplace.dynamicId());
					}
					insersionPointId = insertionElement.getAttribute("id");

				} else {
					// Don't replace, put around the 'insertionElement'
					var replaceElement = document.createElement("div");
					insersionPointId = FlashReplace.dynamicId();
					replaceElement.setAttribute("id", insersionPointId);

					switch (this.insertionPoint.position) {
					case 'before':
						insertionElement.parentNode.insertBefore(replaceElement, insertionElement);
						break;
					case 'after':
						if (insertionElement.nextSibling) {
							insertionElement.parentNode.insertBefore(replaceElement, insertionElement.nextSibling);
						} else {
							insertionElement.parentNode.appendChild(replaceElement);
						}
						break;
					case 'append':
						insertionElement.appendChild(replaceElement);
						break;
					case 'prepend':
						insertionElement.insertBefore(replaceElement, insertionElement.firstChild);
						break;
					}
				}

				this.addFlashVars("FlashReplaceObjectId", insersionPointId);
				//debug(this.swfUrl+", "+insersionPointId+", "+this.width+", "+this.height+", "+this.version+", "+FlashReplacePub.expressInstallSwfurl+", "+this.flashvars+", "+this.params+", "+this.attributes)

				// embed flash in the appropriate place
				swfobject.embedSWF(this.swfUrl, insersionPointId, this.width, this.height, this.version, FlashReplacePub.expressInstallSwfurl, this.flashvars, this.params, this.attributes);

				// Have to use swfobject's domLoaded function as this is used by swfobject.embedSWF
				swfobject.addDomLoadEvent(function () {
					FlashObjectPub.id = insersionPointId;
					FlashObjectPub.element = document.getElementById(insersionPointId);
					FlashObjectPub.embedded();
				});
				
			} else if (swfobject.getFlashPlayerVersion().major !== 0) {
				var insertionElement = FlashReplacePub.installNoteInsertionPoint.element || this.targetNode;
				
				switch (FlashReplacePub.installNoteInsertionPoint.position) {
				case 'before':
					innerXHTML(insertionElement.parentNode, installHtml, insertionElement);
					break;
				case 'after':
					if (insertionElement.nextSibling) {
						innerXHTML(insertionElement.parentNode, installHtml, insertionElement.nextSibling);
					} else {
						innerXHTML(insertionElement.parentNode, installHtml, true);
					}
					break;
				case 'append':
					innerXHTML(insertionElement, installHtml, true);
					break;
				case 'prepend':
					if (insertionElement.hasChildNodes()) {
						innerXHTML(insertionElement, installHtml, insertionElement.firstChild);
					} else {
						innerXHTML(insertionElement, installHtml, true);
					}
					break;
				}
			}
		};


		// Private
		FlashObjectPub.addFlashVars = function (name, value) {
			if (!this.flashvars) {
				this.flashvars = {};
			}
			this.flashvars[name] = value;
		};

		return FlashObjectPub;
	};


// ------------ Internal Methods ------------

	FlashReplace.cloneObject = function (what) {
	    for (var i in what) {
	        this[i] = what[i];
	    }
	};

	FlashReplace.dynamicId = function () {
		return ("flashreplace" + FlashReplace.DynamicIdCount++);
	};

	return FlashReplacePub;
}