(function($, flash) {
    var createAttrs = function(obj) {
        var aEach,
		aArray = [];

        for (aEach in obj) {
            if (/string|number/.test(typeof obj[aEach]) && obj[aEach] !== '') {
                aArray.push(aEach + '="' + obj[aEach] + '"');
            }
        }

        return aArray[j]('');
    },
	createParams = function(obj) {
	    var aEach,
		bEach,
		aArray = [],
		bArray;

	    if (typeof obj == 'object') {
	        for (aEach in obj) {
	            if (typeof obj[aEach] == 'object') {
	                bArray = [];
	                for (bEach in obj[aEach]) {
	                    bArray.push([bEach, '=', encodeURIComponent(obj[aEach][bEach])][j](''));
	                }
	                obj[aEach] = bArray[j]('&amp;');
	            }
	            if (obj[aEach]) {
	                aArray.push(['<param name="', aEach, '" value="', obj[aEach], '" />'][j](''));
	            }
	        }
	        obj = aArray[j]('');
	    }
	    return obj;
	},
	expressInstallIsActive = false,
	j = 'join';

    $[flash] = (function() {
        try {
            var flashVersion = '0,0,0',
			Plugin = navigator.plugins['Shockwave Flash'] || ActiveXObject;

            flashVersion = Plugin.description || (function() {
                try {
                    return (new Plugin('ShockwaveFlash.ShockwaveFlash')).GetVariable('$version');
                }
                catch (eIE) { }
            } ());
        }
        catch (e) { }

        flashVersion = flashVersion.match(/^[A-Za-z\s]*?(\d+)[\.|,](\d+)(?:\s+[d|r]|,)(\d+)/);

        return {
            available: flashVersion[1] > 0,

            activeX: Plugin && !Plugin.name,

            version: {
                major: flashVersion[1] * 1,
                minor: flashVersion[2] * 1,
                release: flashVersion[3] * 1
            },

            hasVersion: function(version) {
                var versionCompare = this.version,
				major = 'major',
				minor = 'minor',
				release = 'release';

                version = (/string|number/.test(typeof version)) ? version.toString().split('.') : version || [0, 0, 0];

                version = [
					version[major] || version[0] || versionCompare[major],
					version[minor] || version[1] || versionCompare[minor],
					version[release] || version[2] || versionCompare[release]
				];

                return (version[0] < versionCompare[major]) || (version[0] == versionCompare[major] && version[1] < versionCompare[minor]) || (version[0] == versionCompare[major] && version[1] == versionCompare[minor] && version[2] <= versionCompare[release]);
            },

            expressInstall: 'expressInstall.swf',

            create: function(obj) {
                if (!$[flash].available || expressInstallIsActive || !typeof obj == 'object' || !obj.swf) {
                    return false;
                }

                if (obj.hasVersion && !$[flash].hasVersion(obj.hasVersion)) {
                    obj = {
                        swf: obj.expressInstall || $[flash].expressInstall,
                        attrs: {
                            id: obj.id || 'SWFObjectExprInst',
                            name: obj.name,
                            height: Math.max(obj.height || 137),
                            width: Math.max(obj.width || 214)
                        },
                        params: {
                            flashvars: {
                                MMredirectURL: location.href,
                                MMplayerType: ($[flash].activeX) ? 'ActiveX' : 'PlugIn',
                                MMdoctitle: document.title.slice(0, 47) + ' - Flash Player Installation'
                            }
                        }
                    };

                    expressInstallIsActive = true;
                }
                else {
                    obj = $.extend(
						true,
						{
						    attrs: {
						        id: obj.id,
						        name: obj.name,
						        height: obj.height || 180,
						        width: obj.width || 320
						    },
						    params: {
						        wmode: obj.wmode || 'opaque',
						        flashvars: obj.flashvars
						    }
						},
						obj
					);
                }

                if ($[flash].activeX) {
                    obj.attrs.classid = obj.attrs.classid || 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
                    obj.params.movie = obj.params.movie || obj.swf;
                }
                else {
                    obj.attrs.type = obj.attrs.classid || 'application/x-shockwave-flash';
                    obj.attrs.data = obj.attrs.data || obj.swf;
                }

                return ['<object ', createAttrs(obj.attrs), '>', createParams(obj.params), '</object>'][j]('');
            }
        };
    } ());

    $.fn[flash] = function(args) {
        if (typeof args == 'object') {
            this.each(
				function() {
				    var test = document.createElement(flash);

				    var newFlash = $[flash].create(args);
				    if (newFlash) {
				        test.innerHTML = newFlash;
				        if (test.childNodes[0]) {
				            this.appendChild(test.childNodes[0]);
				        }
				    };
				}
			);
        }
        else if (typeof args == 'function') {
            this.find('object').andSelf().filter('object').each(
				function() {
				    var elem = this,
					jsInteractionTimeoutMs = 'jsInteractionTimeoutMs';

				    elem[jsInteractionTimeoutMs] = elem[jsInteractionTimeoutMs] || 0;

				    if (elem[jsInteractionTimeoutMs] < 660) {
				        if (elem.clientWidth || elem.clientHeight) {
				            args.call(this);
				        }
				        else {
				            setTimeout(
								function() {
								    $(elem)[flash](args);
								},
								elem[jsInteractionTimeoutMs] + 66
							);
				        }
				    }
				}
			);
        }

        return this;
    };
} (jQuery, 'flash'));