/**
 * Flash detector static class
 */
var FlashDetector = {};

/** @type {Number} Detected flash version, for internal usage only. */
FlashDetector.version 		= -1;

/** @type {Boolean} FlashDetector initialized? for internal usage only. */
FlashDetector.initialized	= false;

/**
 * Initialize. Do detection and assign detected version.
 */
FlashDetector.initialize = function() {
	
	// Having ActiveXObject, try to detect with it
	if( window.ActiveXObject ) {
	
		for( var i = 6; i < 11; i++ ) {
				
			try{
				new window.ActiveXObject( 'ShockwaveFlash.ShockwaveFlash.' + i );
				FlashDetector.version = i;
			} catch( error ) {
				// Error
			}
		}
	
	// If having plugin
	} else if( navigator.plugins && navigator.plugins['Shockwave Flash'] && navigator.plugins['Shockwave Flash'].description ) {
	
		var matches = navigator.plugins['Shockwave Flash'].description.match( /([0-9]+)\.[0-9]+/ );
		
		if( matches[1] && ! isNaN( parseInt( matches[1] ) ) ) {
			FlashDetector.version = parseInt( matches[1] );
		}
	}
}
	
/**
 * Get version of flash player
 *
 * @return {Number} Detected version, -1 if not detected
 */
FlashDetector.getVersion = function () { 
	
	if( ! FlashDetector.initialized ) {
		FlashDetector.initialize();
		FlashDetector.initialized = true;
	}

	return FlashDetector.version;
}

/**
 * Flash tag class
 */
var FlashTag = function() {

	// Initialize if needed
	if( ! FlashTag.initialized ) {
		FlashTag.initialize();
	}

	/** @type {Number} Requred version */
	this.version		= 7;
	
	/** @type {String} Movie source */
	this.src			= null;
	
	/** @type {Number} Width */
	this.width			= 1;
	
	/** @type {Number} Height */
	this.height			= 1;

	/** @type {String} Id, generated automatically */
	this.id				= "flash" + ( Math.random().toString() ).split( "." )[1];
	
	/** @type {Object} Flash vars */
	this.vars			= {};
	
	/** @type {Boolean} Automatically play? */
	this.play			= true;
	
	/** @type {Boolean} Display menu ? */
	this.menu			= false;
	
	/** @type {Boolean} Loop movie? */
	this.loop			= true;
	
	/** @type {String} Quality - one of low, high, autolow, autohigh, best */
	this.quality		= 'high';
	
	/** @type {String} Scaling- one of showall, noborder, exactfit */
	this.scale			= 'noscale';
	
	/** @type {String} Stage align - one of l, t, r, b, tl, tr, bl, br */
	this.salign			= null;
	
	/** @type {String} Window mode - one of window, opaque, transparent */
	this.wmode			= 'window';
	
	/** @type {String} Background color */
	this.bgcolor		= null;
	
	/** @type {String} Movie base url */
	this.base			= null;
	
	/** @type {Boolean} Allow full screen mode */
	this.allowFullScreen = true;
	
	/** @type {Boolean} Browser - based history enabled? */
	this.historyEnabled	= false;
	
	/** @type {Boolean} Browser - based wheel enabled? */
	this.wheelEnabled	= false;
	
	// Add to tags by id pool
	FlashTag.tagsById[this.id] = this;

}

/** @type {Boolean} Flash tag initialized? */
FlashTag.initialized = false;

/**
 * Initialize static properties
 */
FlashTag.initialize = function() {
	
	if( ! FlashTag.initialized ) {
	
		// Some variables
		var userAgent 		= navigator.userAgent.toLowerCase();
		var titleElements 	= document.getElementsByTagName( "title" );
		
		/** @type {Boolean} use <embed>? */
		FlashTag.useEmbed = ( userAgent.indexOf( 'msie' ) == -1 ) && document.embeds;

		/** @type {Boolean} History supported? */
		FlashTag.historySupported = ( userAgent.indexOf( 'opera' ) == -1 ) && ( userAgent.indexOf( 'msie 6.' ) == -1 );
		
		/** @type {Boolean} Wheel supported? Wheel can be used only in gecko-based and ie 7. browsers */
		FlashTag.wheelSupported = ( userAgent.indexOf( 'gecko' ) >= 0 ) || ( userAgent.indexOf( 'msie 7.' ) >= 0 ) || ( userAgent.indexOf( 'msie 6.' ) >= 0 );

		/** @type {String} Document title */
		FlashTag.documentTitle = titleElements[0] ? titleElements[0].innerHTML.replace( /#.*?$/, "" ) : "";

		/** @type {Array} Tags by id, for internal usage only */
		FlashTag.tagsById = [];
		
		// Add listener if can use history
		if( FlashTag.historySupported ) {
			unFocus.History.addEventListener( "historyChange", FlashTag.onHistoryChange );
		}
			
		// Add listener if can use wheel
		if( FlashTag.wheelSupported ) {
				
			if (window.addEventListener) {
				window.addEventListener( 'DOMMouseScroll', FlashTag.onWheel, false );
			}
				
			window.onmousewheel = document.onmousewheel = FlashTag.onWheel;
		}
		
		FlashTag.initialized = true;
	}
}

/**
 * Get flash tag by id
 *
 * @param {String} id Id of flash tag to get
 * @return {FlashTag} FlashTag by id
 */
FlashTag.getById = function( id ) {
		
	var retVal;
	
	if( FlashTag.tagsById[id] ) {
		retVal = FlashTag.tagsById[id];
	}
	
	return retVal;
}

/**
 * On history change listener for unFocus.History
 *
 * @param {String} hash new history hash
 */
FlashTag.onHistoryChange = function( hash ) {
	
	// Restore document title
	document.title = FlashTag.documentTitle;
	
	// Notify all elements
	for( var i in FlashTag.tagsById ) {
		
		if( FlashTag.tagsById[i].historyEnabled ) {
			FlashTag.tagsById[i].onHistoryHash( hash );
		}
	}
}

/**
 * On wheel event handler 
 * 
 * @param {Object} event
 */
FlashTag.onWheel = function( event ) {
	
	event = event || window.event;
	
	var delta = event.wheelDelta ? event.wheelDelta : ( event.detail ? ( - event.detail ) : 0 );
	delta = ( delta > 0 ) ? 1 : ( ( delta < 0 ) ? -1 : 0 );
	
	// If having delta, notify all tags
	if( delta != 0 ) {
		
		for( var i in FlashTag.tagsById ) {
			
			if( FlashTag.tagsById[i].wheelEnabled ) {
				FlashTag.tagsById[i].onWheelDelta( delta );
			}			
		}
	}
}

/**
 * Add new history
 *
 * @param {String} hash history to add
 */
FlashTag.addHistoryHash = function( hash ) {
	
	// History adding is not supported in opera
	if( FlashTag.historySupported ) {
	
		unFocus.History.addHistory( hash );
		
		// Restore document title
		document.title = FlashTag.documentTitle;
	}
}

/**
 * Get flash tag html 
 *
 * @return {String} flash tag html
 */
FlashTag.prototype.getHtml = function() {
	
	// Default values for object, embed and params HTMLs
	var objectHtml 	= 	'<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" align="middle"';
	var paramsHtml	= 	'<param name="allowScriptAccess" value="sameDomain" />';
	var embedHtml 	= 	'<embed swLiveConnect="true" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer"';
	
	// Add size
	var sizeHtml = ' style="width: ' + ( this.width.toString().match( /^[0-9]+$/ ) ? ( this.width + "px" ) : this.width ) + '; height: ' + ( this.height.toString().match( /^[0-9]+$/ ) ? ( this.height + "px" ) : this.height ) + ';"';
	objectHtml += sizeHtml; embedHtml += sizeHtml;
	
	// Add version
	objectHtml += 'codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' + this.version + ',0,0,0"';
		
	// Add src
	if( this.src ) {
		paramsHtml += '<param name="movie" value="' + this.src + '" />';
		embedHtml	+= ' src="' + this.src + '"';
	}
		
	// Id mus be always set!
	objectHtml 	+= '" id="' + this.id + '"';
	embedHtml 	+= ' name="' + this.id + '" id="' + this.id + '"';
		
	// Add bgcolor
	if( this.bgcolor ) {
		paramsHtml += '<param name="bgcolor" value="' + this.bgcolor + '" />';
		embedHtml 	+= ' bgcolor="' + this.bgcolor + '"';
	}
	
	// Add menu settings only if menu is set to false
	if( ! this.menu ) {
		paramsHtml 	+= '<param name="menu" value="false" />';
		embedHtml 	+= ' menu="false"';
	}
	
	// Add scale
	if( this.scale ) {
		paramsHtml += '<param name="scale" value="' + this.scale + '" />';
		embedHtml  += ' scale="' + this.scale + '"';
	}
	
	// Add quality
	if( this.quality ) {
		paramsHtml += '<param name="quality" value="' + this.quality + '" />';
		embedHtml  += ' quality="' + this.quality + '"';
	}

	// Add play only if set to false
	if( ! this.play ) {
		paramsHtml += '<param name="play" value="false" />';
		embedHtml  += ' play="false"';
	}
	
	// Add stage align
	if( this.salign ) {
		paramsHtml += '<param name="salign" value="' + this.salign + '" />';
		embedHtml  += ' salign="' + this.salign + '"';
	}
	
	// Add window mode
	if( this.wmode ) {
		paramsHtml += '<param name="wmode" value="' + this.wmode + '" />';
		embedHtml  += ' wmode="' + this.wmode + '"';
	}

	// Add base
	if( this.base ) {
		paramsHtml += '<param name="base" value="' + this.base + '" />';
		embedHtml  += ' base="' + this.base + '"';
	}
	
	// Add allowFullScreen
	if( this.base ) {
		paramsHtml += '<param name="allowFullScreen" value="true" />';
		embedHtml  += ' allowFullScreen="true"';
	}
	
	// Add flashvars, flash var htmlElementId added automatically
	if( ! this.vars ) {
		this.vars = {};
	}
	
	// Automatically add htmlElementId as flash var
	this.vars.flashTagHtmlElementId = this.id;
	
	// Automatically add browser version
	this.vars.flashTagBrowserVersion = window.navigator.userAgent;
	
	// Automatically add document url
	this.vars.flashTagDocumentUrl = window.location.href;
	
	// Automatically add history enabled, if set to true and available
	if( FlashTag.historySupported && this.historyEnabled ) {
		this.vars.flashTagHistoryEnabled = "true";
	}
	
	// Automatically add useWheel, if set to true and available
	if( FlashTag.wheelSupported && this.wheelEnabled ) {
		this.vars.flashTagWheelEnabled = "true";
	}
	
	// Automatically add first history hash to flash vars
	if( FlashTag.historySupported && this.historyEnabled ) {
		
		if( unFocus.History.getCurrent() ) {
			this.vars.flashTagHistoryHash = unFocus.History.getCurrent();
		}
	}
	
	var varsHtml = [];

	for( var i in this.vars ) {
		varsHtml.push( i + '=' + escape( this.vars[i] ) );
	}
	
	if( varsHtml.length > 0 ) {
		varsHtml = varsHtml.join( '&amp;' );
		paramsHtml 	+= '<param name="flashvars" value="' + varsHtml + '">';
		embedHtml	+= ' flashvars="' + varsHtml + '"';
	}
	
	// Embeds? Return embed html, else - return object html
	return FlashTag.useEmbed ? ( embedHtml + ' />' ) : ( objectHtml + '>' + paramsHtml + '</object>' );

}
	
/**
 * Write to html element
 *
 * @param {String} id Id of element to write to
 * @return {String} flash tag html
 */
FlashTag.prototype.writeToElement = function( id ) {
		
	// Try to write to element, and initialize some stuff
	try {
		document.getElementById( id ).innerHTML = this.getHtml();
	} catch( error ) {
		// Error
	}
}
	
/**
 * Get html element
 *
 * @return {HTMLElement} Flash html element (if exists)
 */
FlashTag.prototype.getElement = function() {
	
	var retVal;
	
	if( FlashTag.useEmbed && document.embeds[this.id] ) {
		retVal = document.embeds[this.id];
	} else if( document[this.id] ) {
		retVal = document[this.id];
	}
	
	return retVal;
}

/**
 * Set height (can also be used when html element exists)
 *
 * @param {String} height Height of flash element, number or percent
 */
FlashTag.prototype.setHeight = function( value ) {
	
	this.height = value;
	
	if( this.getElement() ) {
		
		try {
			this.getElement().style.height = this.height.toString().match( /^[0-9]+$/ ) ? ( this.height + "px" ) : this.height;
		} catch( e ) {
			// Exception
		}
	}
}
	
/**
 * Set width (can also be used when html element exists)
 *
 * @param {String} width Height of flash element, number or percent
 */
FlashTag.prototype.setWidth = function( value ) {
		
	this.width = value;
	
	if( this.getElement() ) {
		
		try {
			this.getElement().style.width = this.width.toString().match( /^[0-9]+$/ ) ? ( this.width + "px" ) : this.width;
		} catch( e ) {
			// Exception
		}
	}
}

/**
 * On history change (called internally from flash tag onHistoryChange)
 * 
 * @param {String} hash history 
 */
FlashTag.prototype.onHistoryHash = function ( hash ) {
	
	try {
		this.getElement().SetVariable( "flashTagHistoryHash", hash );
	} catch( e ) {
		// Exception
	}
}

/**
 * On wheel (called internally from flash tag onWheel)
 * 
 * @param {Number} delta wheel delta 
 */
FlashTag.prototype.onWheelDelta = function ( delta ) {
	
	try {
		this.getElement().SetVariable( "flashTagWheelDelta", delta.toString() );
	} catch( e ) {
		// Exception
	}
}