(function ($) {
	$.extend($.fn, {
		h2swf: function (options) {

			var defaults = {
				debug : 0,
				divider : '|',
				width : null, // add checking if this is not set
				height : null, // add checking if this is not set
				swf : "../flash/header.swf",
				wmode : "transparent",
				color : 'ffffff',
				background_color : '000000',
				alpha : .5,
				blocking : [0, 0, 0, 0],
				tracking : 0,
				leading : 0,
				pad_asc : null, // not yet implemented
				pad_desc : 0,
				sharpness : 0, // -400 to 400
				thickness : 0, // -200 to 200
				wordwrap : true, // wraps text if wider than 'width'
				prevent_widow : false, // tries to prevent a single word on the last line.
				width_threshold : 3, // // adjusts blocking width if line width difference < width_threshold
				on_ready_callback : function(){ }
			};

			options = $.extend(defaults, options);
			
			return this.each(function () {
				
				var el = $(this);
				var source = el.hasClass('h2swf') ? el.find('span').html() : el.html();
				
				// read text inside the element.
				var text = source.replace(/\<br\>/g, '<BR>').split('<BR>');
				
				// append the text to span inside the el
				el.html('<span>'+source+'</span>');
				
				el.addClass('h2swf');
				
				// trim whitespace on all pieces
				for(var i = 0; i < text.length; i++){
					text[i] = text[i].replace(/^\s+|\s+$/g, '');
				}
				
				// swap row breaks with divider
				text = text.join('|');
								
				// attach a id to the element.
				var id = 'h2swf'+$.h2swf_id_counter++;
				
				// append our new flash container inside
				el.append('<div id="'+id+'"></div>');
				var container = $('#'+id);
				
				// make the element a block element.
				container.css('display', 'block');
				
				// calculate height and set it to the element.
				if(typeof(options.width) == 'number') {
					container.css('width', options.width);
					max_width = parseInt(options.width);
				}else if(options.wordwrap){
					var n = parseInt(el.css('width'));
					max_width = !n ? el.get(0).offsetWidth : n;
					container.css('width', max_width);
				}else{
					max_width = 0;
				}
				
				if(options.height != 'callback' && options.width != null){
					container.css('height', options.height || el.css('height'));
				};

				// create swf object and set it's flashvars and params.
				var params = {
					wmode: options.wmode
				};
				
				var attributes = {
					id: id
				};
				
				// store down settings for this instance
				// so we can pick it backup from the callback from Flash.
				$.h2swf_callbacks[id] = {
					callback : options.on_ready_callback,
					options: options
				};

				var flashvars = {
					id : id,
					debug : options.debug  ? 1:0,
					render_txt : escape(escape(text)),
					color : options.color ? options.color :  CSSColorToHex(el.css('color')),
					background_color : options.background_color ? options.background_color :  CSSColorToHex(el.css('background-color')),
					alpha : options.alpha,
					line_height : options.line_height,
					font_size : options.font_size,
					tracking : options.tracking,
					leading : options.leading,
					blocking : options.blocking.join('|'),
					pad_asc : options.pad_asc,
					pad_desc : options.pad_desc,
					sharpness : options.sharpness,
					thickness : options.thickness,
					callback : "jQuery.h2swf_callback",
					wordwrap : options.wordwrap ? 1:0,
					max_width : max_width,
					prevent_widow : options.prevent_widow ? 1:0,
					width_threshold : options.width_threshold
				};
				
				el.find('span').hide(); // hide real text. We might want to do this in a more accessible way here.
				el.find('object').remove(); // remove old h2swf's TODO: check for last id here instead of all object tags?
				el.css('background', 'none');
				swfobject.embedSWF(options.swf, id, parseInt(container.css('width')) || 1, parseInt(container.css('height')) || 1, "9.0.0", "expressInstall.swf", flashvars, params, attributes);
			});
		}
	});
	
	// utility functions
	var CSSColorToHex = function (css_str) { var a = css_str.replace(new RegExp(/[^0-9+,]/g), '').split(','); return RGBtoHex(a[0], a[1], a[2]); };
	var RGBtoHex = function (R,G,B) { return toHex(R)+toHex(G)+toHex(B); };
	var toHex = function (N) { if (N==null) return "00"; N=parseInt(N); if (N==0 || isNaN(N)) return "00"; N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N); return "0123456789ABCDEF".charAt((N-N%16)/16) + "0123456789ABCDEF".charAt(N%16); };	
	
	$.h2swf_id_counter = 0;
	$.h2swf_callbacks = [];
	$.h2swf_callback = function (id, width, height) {
		var settings = $.h2swf_callbacks[id];
		settings.callback(id, width, height);
		if(settings.options.width == 'callback'){
			$('#'+id).css('width', parseInt(width));
			$('#'+id).attr('width', parseInt(width));
		}
		if(settings.options.height == 'callback'){
			$('#'+id).css('height', parseInt(height));
			$('#'+id).attr('height', parseInt(height));
		}
	};
	
})(jQuery);

/*
Copyright (c) Copyright (c) 2007, Carl S. Yestrau All rights reserved.
Code licensed under the BSD License: http://www.featureblend.com/license.txt
Version: 1.0.4
*/
var FlashDetect = new function(){
    var self = this;
    self.installed = false;
    self.raw = "";
    self.major = -1;
    self.minor = -1;
    self.revision = -1;
    self.revisionStr = "";
    var activeXDetectRules = [
        {
            "name":"ShockwaveFlash.ShockwaveFlash.7",
            "version":function(obj){
                return getActiveXVersion(obj);
            }
        },
        {
            "name":"ShockwaveFlash.ShockwaveFlash.6",
            "version":function(obj){
                var version = "6,0,21";
                try{
                    obj.AllowScriptAccess = "always";
                    version = getActiveXVersion(obj);
                }catch(err){}
                return version;
            }
        },
        {
            "name":"ShockwaveFlash.ShockwaveFlash",
            "version":function(obj){
                return getActiveXVersion(obj);
            }
        }
    ];
    /**
     * Extract the ActiveX version of the plugin.
     * 
     * @param {Object} The flash ActiveX object.
     * @type String
     */
    var getActiveXVersion = function(activeXObj){
        var version = -1;
        try{
            version = activeXObj.GetVariable("$version");
        }catch(err){}
        return version;
    };
    /**
     * Try and retrieve an ActiveX object having a specified name.
     * 
     * @param {String} name The ActiveX object name lookup.
     * @return One of ActiveX object or a simple object having an attribute of activeXError with a value of true.
     * @type Object
     */
    var getActiveXObject = function(name){
        var obj = -1;
        try{
            obj = new ActiveXObject(name);
        }catch(err){
            obj = {activeXError:true};
        }
        return obj;
    };
    /**
     * Parse an ActiveX $version string into an object.
     * 
     * @param {String} str The ActiveX Object GetVariable($version) return value. 
     * @return An object having raw, major, minor, revision and revisionStr attributes.
     * @type Object
     */
    var parseActiveXVersion = function(str){
        var versionArray = str.split(",");//replace with regex
        return {
            "raw":str,
            "major":parseInt(versionArray[0].split(" ")[1], 10),
            "minor":parseInt(versionArray[1], 10),
            "revision":parseInt(versionArray[2], 10),
            "revisionStr":versionArray[2]
        };
    };
    /**
     * Parse a standard enabledPlugin.description into an object.
     * 
     * @param {String} str The enabledPlugin.description value.
     * @return An object having raw, major, minor, revision and revisionStr attributes.
     * @type Object
     */
    var parseStandardVersion = function(str){
        var descParts = str.split(/ +/);
        var majorMinor = descParts[2].split(/\./);
        var revisionStr = descParts[3];
        return {
            "raw":str,
            "major":parseInt(majorMinor[0], 10),
            "minor":parseInt(majorMinor[1], 10), 
            "revisionStr":revisionStr,
            "revision":parseRevisionStrToInt(revisionStr)
        };
    };
    /**
     * Parse the plugin revision string into an integer.
     * 
     * @param {String} The revision in string format.
     * @type Number
     */
    var parseRevisionStrToInt = function(str){
        return parseInt(str.replace(/[a-zA-Z]/g, ""), 10) || self.revision;
    };
    /**
     * Is the major version greater than or equal to a specified version.
     * 
     * @param {Number} version The minimum required major version.
     * @type Boolean
     */
    self.majorAtLeast = function(version){
        return self.major >= version;
    };
    /**
     * Is the minor version greater than or equal to a specified version.
     * 
     * @param {Number} version The minimum required minor version.
     * @type Boolean
     */
    self.minorAtLeast = function(version){
        return self.minor >= version;
    };
    /**
     * Is the revision version greater than or equal to a specified version.
     * 
     * @param {Number} version The minimum required revision version.
     * @type Boolean
     */
    self.revisionAtLeast = function(version){
        return self.revision >= version;
    };
    /**
     * Is the version greater than or equal to a specified major, minor and revision.
     * 
     * @param {Number} major The minimum required major version.
     * @param {Number} (Optional) minor The minimum required minor version.
     * @param {Number} (Optional) revision The minimum required revision version.
     * @type Boolean
     */
    self.versionAtLeast = function(major){
        var properties = [self.major, self.minor, self.revision];
        var len = Math.min(properties.length, arguments.length);
        for(i=0; i<len; i++){
            if(properties[i]>=arguments[i]){
                if(i+1<len && properties[i]==arguments[i]){
                    continue;
                }else{
                    return true;
                }
            }else{
                return false;
            }
        }
    };
    /**
     * Constructor, sets raw, major, minor, revisionStr, revision and installed public properties.
     */
    self.FlashDetect = function(){
        if(navigator.plugins && navigator.plugins.length>0){
            var type = 'application/x-shockwave-flash';
            var mimeTypes = navigator.mimeTypes;
            if(mimeTypes && mimeTypes[type] && mimeTypes[type].enabledPlugin && mimeTypes[type].enabledPlugin.description){
                var version = mimeTypes[type].enabledPlugin.description;
                var versionObj = parseStandardVersion(version);
                self.raw = versionObj.raw;
                self.major = versionObj.major;
                self.minor = versionObj.minor; 
                self.revisionStr = versionObj.revisionStr;
                self.revision = versionObj.revision;
                self.installed = true;
            }
        }else if(navigator.appVersion.indexOf("Mac")==-1 && window.execScript){
            var version = -1;
            for(var i=0; i<activeXDetectRules.length && version==-1; i++){
                var obj = getActiveXObject(activeXDetectRules[i].name);
                if(!obj.activeXError){
                    self.installed = true;
                    version = activeXDetectRules[i].version(obj);
                    if(version!=-1){
                        var versionObj = parseActiveXVersion(version);
                        self.raw = versionObj.raw;
                        self.major = versionObj.major;
                        self.minor = versionObj.minor; 
                        self.revision = versionObj.revision;
                        self.revisionStr = versionObj.revisionStr;
                    }
                }
            }
        }
    }();
};
FlashDetect.JS_RELEASE = "1.0.4";

