/*
* @	WST - Web Standards Tools v 1.1
* @ http://wstframework.org
* @ Diego de Andrade Pereira - contact@wstframework.org
* @ Released on 13/10/2008 10:07
* @ See GPL LICENSE.txt for the license usage
*/

(function(){
	var flash = function()
	{
		// @wstFnID [wst.flash]
		var args = arguments;
		
		if(wst.is.object(args[0]) ? true : args[0].indexOf('#') == 0)
		{
			return wst.flash.get(args[0]);
		}
		else
		{
			var src, width, height, params;
			
			if(args.length <= 2)
			{
				src = args[0];
				width = null;
				height = null;
				params = args[1] || null;
			}
			else
			{
				src = args[0];
				width = args[1];
				height = args[2];
				params = args[3] || null;
			}
			
			return wst.flash
				.get(wst.apply(wst.flash.__build, [src, width, height, params], this));
			
			//return wst.flash.get(wst.flash.__build(src, width, height, params));
		}
	};
	
	wst.extend(flash, {
		uid : 0,
		targetVersion : '8.0.0',
		version : null,
		hasFlash : false,
		useExpressInstall : true, // to do
		defaults : {
			'bgcolor' : '#ffffff',
			'wmode' : (wst.browser.ie ? 'opaque' : 'window'), // FF BUG: values 'transparent' and 'opaque' generates a bug. So we start in FF with de default value set to 'window'.
			'allowscriptaccess' : 'sameDomain',
			'loop' : 'false',
			'menu' : 'false',
			'quality' : 'best',
			'scale' : 'exactfit',
			'salign' : 'lt',
			'align' : 'middle'
		},
		props : {
			'_x' : 0,
			'_y' : 1,
			'_xscale' : 2,
			'_yscale' : 3,
			'_currentframe' : 4,
			'_totalframes' : 5,
			'_alpha' : 6,
			'_visible' : 7,
			'_width' : 8,
			'_height' : 9,
			'_rotation' : 10,
			'_target' : 11,
			'_framesloaded' : 12,
			'_name' : 13,
			'_droptarget' : 14,
			'_url' : 15
		},
		get : function(id)
		{
			// @wstFnID [wst.flash.get]
			var movieName, movie;
			var wstObject = new wst;
			
			if(wst.is.object(id))
			{
				movie = id;
			}
			else
			{
				movieName = id.indexOf('#') == 0 ? id.slice(1) : id;
				movie = window[movieName] ? 
					window[movieName] : 
					document[movieName] ? document[movieName] : wst.get(id).E[0];
			}
			
			wstObject.total = (wstObject.E = [movie]).length;
			wst.extend(wstObject, wst.flash.prototype);
			
			return wstObject;
		},
		/*
		* Originally based on the Flash Satay method of Drew McLellan in A List Apart
		* http://www.alistapart.com/articles/flashsatay/
		*/
		__build : function(movieSrc, movieWidth, movieHeight, params)
		{
			// @wstFnID [wst.flash.__build]
			var objectStr = '', prop;
			var defaults = wst.flash.defaults;
			var id, version, autoDetectDimensions = false;
			var useStrictMethod = wst.browser.gecko ? (wst.core.mode == 'strict') : true;
			
			if(this.flash.hasFlash)
			{
				if(this.flash.hasSupportedVersion())
				{
					if(params == null)
					{
						params = defaults;
					}
					else
					{
						for(prop in defaults)
							params[prop] = !wst.ok(params[prop]) ? defaults[prop] : params[prop];
					}
					
					// movie id
					if(!wst.ok(params.id))
						id = 'flashMovie' + (wst.flash.uid++);
					else
						id = params.id, delete params.id;
					
					// movie dimensions
					if(!wst.ok(movieHeight) && !wst.ok(movieWidth))
					{
						autoDetectDimensions = true;
						movieWidth = 1;
						movieHeight = 1;
					}
					
					if(!wst.browser.ie)
					{
						if(useStrictMethod && (wst.browser.gecko) || !wst.browser.gecko)
						{
							objectStr = '<object type="application/x-shockwave-flash" '
										+ 'data="' + movieSrc + '" '
										+ 'height="' + movieHeight + '" '
										+ 'width="' + movieWidth + '" '
										+ 'align="' + params.align + '" '
										+ 'id="' + id + '">';
						}
						else
						{
							objectStr = '<embed id="' + id + '" src="' + movieSrc + '" width="' + movieWidth + '" height="' + movieHeight + '" align="' + params.align + '" ';
						}
					}
					else
					{
						var pluginVersion = this.flash.targetVersion.replace(wst.regex({expr:'\\.', flags:'g'}), ',') + ',0';
						
						objectStr = '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" '
									+ 'codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + pluginVersion + '" '
									+ 'height="' + movieHeight + '" '
									+ 'width="' + movieWidth + '" '
									+ 'align="' + params.align + '" '
									+ 'id="' + id + '">'
									+ '<param name="movie" value="' + movieSrc + '" />';
					}
					
					for(prop in params)
					{
						if(useStrictMethod)
							objectStr += '<param name="' + prop + '" value="' + params[prop] + '" />';
						else
							objectStr += prop + '="' + params[prop] + '" ';
					}
					
					if(useStrictMethod)
						objectStr += '</object>';
					else
						objectStr += '/>';
					
					if(!wst.documentLoaded && this.total == 0)
					{
						if(wst.ok(this.expr))
							this.flash.__insertMovie(this, objectStr);
						else
							document.write(objectStr);
					}
					else
					{
						this.flash.__insertMovie(this, objectStr);
					}
					
					if(autoDetectDimensions)
					{
						wst.get(document).ready(function(){
							wst.get('#' + id).loaded(function(){
								var movie = wst.flash('#' + id);
								
								wst.timeout(function(){
									var newWidth = movie.variable('Stage:width') || movie._width();
									var newHeight = movie.variable('Stage:height') || movie._height();
									
									if((newWidth == 0) && (newHeight == 0))
										wst.timeout(arguments.callee, 10, movie);
									else
										movie.attr({'width' : newWidth, 'height' : newHeight});
								}, 10, movie);
							});
						});
					}
					
					return id;
				}
				// version is unsupported, needs update
				else if(this.flash.useExpressInstall)
				{
					// to do
				}
			}
			// there is no flash installed
			else
			{
				// to do
			}
			
			return '';
		},
		__insertMovie : function(movie, objectStr)
		{
			// @wstFnID [wst.flash.__insertMovie]
		
			// IE BUG: IE currently don't support the use of DOM methods with the object element.
			// So we must to use the non standard innerHTML property to create the object... the ugly way.
			if(wst.browser.ie)
			{
				// IE BUG "Operation aborted": IE crashes when the script tries to add content to an element that is not completly loaded.
				// So we must to verify if the target element is ready (closed) to append content.
				// IMPORTANT NOTE: NEVER APPEND CONTENT FROM A CHILD TO A PARENT ELEMENT DURING THE DOCUMENT LOAD!!
				movie.loop(function(){
					if(/complete|loaded/.test(this.readyState))
					{
						this.innerHTML = objectStr;
					}
					else
					{
						wst.get(this).ready(function(){
							this.innerHTML = objectStr;
						});
					}
				});
			}
			else
			{
				movie.content(objectStr);
			}
		},
		buildDuringLoad : function(expr)
		{
			// @wstFnID [wst.flash.buildDuringLoad]
			var elements = wst.get(expr);
			var newMovies = [];
			
			elements.loaded(function(){
				var element = wst.get(this);
				var newMovie = element.clone().E[0];
				
				element.replace(newMovie);
				newMovies.push(newMovie);
			});
			
			return wst.get(newMovies);
		},
		/*
		* Originally based on the ArticleDetectFlash
		* http://code.google.com/p/doctype/wiki/ArticleDetectFlash
		* and the Flash Detection Kit by Adobe
		*/
		detect : function()
		{
			// @wstFnID [wst.flash.detect]
			var pluginsVersion = ['ShockwaveFlash.ShockwaveFlash.7', 'ShockwaveFlash.ShockwaveFlash.6', 'ShockwaveFlash.ShockwaveFlash.3', 'ShockwaveFlash.ShockwaveFlash'];
			var i = -1;
			var plugin = null, mimeType = null, aXo = null;
			var currentVersion = null;
			var version = '';
			var correctVersion = -1;
			
			// check for installed plugins
			if(navigator.plugins && navigator.plugins.length)
			{
				plugin = navigator.plugins['Shockwave Flash'] || navigator.plugins['Shockwave Flash 2.0'];
				version = plugin ? plugin.description : -1;
			}
			else
			{
				// check for supported mimeTypes
				if(navigator.mimeTypes && navigator.mimeTypes.length)
				{
					mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
					version = (mimeType && mimeType.enabledPlugin) ? mimeType.enabledPlugin.description : -1;
				}
				// check for ActiveX objects
				else
				{
					while((currentVersion = pluginsVersion[++i]) && !version)
					{
						try{
							aXo = new ActiveXObject(currentVersion);
							version = aXo.GetVariable('$version');
							break;
						}
						catch(err){
							switch(currentVersion)
							{
								case 'ShockwaveFlash.ShockwaveFlash.6':
									try{
										version = '6,0,21';
										aXo.AllowScriptAccess = 'always';
									}
									catch(err){};
									break;
								case 'ShockwaveFlash.ShockwaveFlash.3':
									version = '3,0,18';
									break;
								case 'ShockwaveFlash.ShockwaveFlash':
									try{
										aXo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
										version = '2,0,0';
									}
									catch(err){
										version = -1;
									};
									break;
								default:
									version = -1;
									break;
							}
						};
					}
				}
			}
			
			if(version != -1)
			{
				correctVersion = version.match(wst.regex({expr:'\\d+', flags:'g'}));
				correctVersion = correctVersion.slice(0, 3).join('.');
				this.version = correctVersion;
				this.hasFlash = true;
			}
			
			return correctVersion;
		},
		hasSupportedVersion : function(targetVersion)
		{
			// @wstFnID [wst.flash.hasSupportedVersion]
			var flashVersion = null;
			var isSupportedVersion = false;
			
			if(this.hasFlash)
			{
				targetVersion = (targetVersion || this.targetVersion).split('.');
				flashVersion = this.version.split('.');
				var v1 = parseInt(flashVersion[0]) > parseInt(targetVersion[0]);
				var v1_1 = parseInt(flashVersion[0]) == parseInt(targetVersion[0]);
				var v2 = parseInt(flashVersion[1]) > parseInt(targetVersion[1]);
				var v2_2 = parseInt(flashVersion[1]) == parseInt(targetVersion[1]);
				var v3 = parseInt(flashVersion[2]) >= parseInt(targetVersion[2]);
				
				isSupportedVersion = v1 ?
					true
					: v1_1 ?
						v2 ?
							true
							: v2_2 ?
								v3
								: false
						: false;
			}
			
			return isSupportedVersion;
		}
	});
	
	// PROTOTYPE
	wst.extend(flash.prototype, {
		property : function(name, value, target)
		{
			// @wstFnID [wst.flash.property]
			var movies = this.E;
			
			if(arguments.length < 3)
			{
				target = value || '/';
				return movies[0].TGetProperty(target, wst.flash.props[name]) || 0;
			}
			else
			{
				movies.loop(function(){
					this.TSetProperty(target, wst.flash.props[name], value);
				});
				return this;
			}
		},
		variable : function(name, value)
		{
			// @wstFnID [wst.flash.variable]
			var movies = this.E;
			
			if(arguments.length == 1)
			{
				return movies[0].GetVariable(name);
			}
			else
			{
				movies.loop(function(){
					this.SetVariable(name, value);
				});
				return this;
			}
		},
		_width : function(target)
		{
			// @wstFnID [wst.flash.width]
			
			return this.property('_width', target);
		},
		_height : function(target)
		{
			// @wstFnID [wst.flash.height]
			
			return this.property('_height', target);
		},
		play : function(target)
		{
			// @wstFnID [wst.flash.play]
			var movies = this.E;
			target = target || '/';
			
			movies.loop(function(){
				this.TPlay(target);
			});
			return this;
		},
		stop : function(target)
		{
			// @wstFnID [wst.flash.stop]
			var movies = this.E;
			target = target || '/';
			
			movies.loop(function(){
				this.TStopPlay(target);
			});
			return this;
		},
		goTo : function(index, target)
		{
			// @wstFnID [wst.flash.goto]
			var movies = this.E;
			target = target || '/';
			
			movies.loop(function(){
				!isNaN(parseInt(index)) ? this.TGotoFrame(target, (index - 1)) : this.TGotoLabel(target, index);
			});
			return this;
		}
	});
	
	wst.extend([wst, wst.proto], { flash : flash });
	
	wst.flash.detect();
	wst.flash.hasSupportedVersion();
	
	// IE BUG: prevent memory leak in IE when the window unload event is dispatched
	if(wst.browser.ie && !wst.core.unloadBugFix)
	{
		wst.core.unloadBugFix = true;
		wst.get(window).on('unload', function(){
			wst.get('object, applet')
				.loop(function(){
					for(var prop in this)
					{
						try{
							if(wst.is.fn(this[prop]))
								this[prop] = function(){};
						}
						catch(err){};
					}
				})
				.remove();
		});
	}
	
})();