var HistoryFile='history.js';
var HistoryTime;

BrowserHistory =
(
	function()
	{
		// if setDefaultURL has been called, our first clue
		// that the SWF is ready and listening
		//var swfReady = false;

		// the URL we'll send to the SWF once it is ready
		//var pendingURL = '';

		// Default app state URL to use when no fragment ID present
		var defaultHash = '';

		// Last-known app state URL
		var currentHref = document.location.href;

		// Initial URL (used only by IE)
		var initialHref = document.location.href;

		// Initial URL (used only by IE)
		var initialHash = document.location.hash;

		// History frame source URL prefix (used only by IE)
		var historyFrameSourcePrefix = '_s/flash/history/historyFrame.html?';

		// History maintenance (used only by Safari)
		var currentHistoryLength = -1;

		var historyHash = [];

		var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);

		var backStack = [];
		var forwardStack = [];

		var currentObjectId = null;

		if ( $.browser.msie == true && $.browser.version == 7 )
		{
			window["_ie_firstload"] = false;
		}

		// Accessor functions for obtaining specific elements of the page.
		function getHistoryFrame()
		{
			return $('#ie_historyFrame');
		}

		function getAnchorElement()
		{
			return $('#firefox_anchorDiv');
		}

		function getFormElement()
		{
			return $('#safari_formDiv');
		}

		function getRememberElement()
		{
			return $("#safari_remember_field");
		}

		/* Get the Flash player object for performing ExternalInterface callbacks. */
		function getPlayer()
		{
			player = $('#flashPlayer');
        
			return player;
		}

		function getIframeHash()
		{
			var doc = getHistoryFrame().get(0).contentWindow.document;
			var hash = doc.location.search;
			
			if ( hash.length == 1 && hash.charAt(0) == "?" )
			{
				hash = "";
			}
			else if ( hash.length >= 2 && hash.charAt(0) == "?" )
			{
				hash = hash.substring(1);
			}
			
			return hash;
		}

		/* Get the current location hash excluding the '#' symbol. */
		function getHash()
		{
			var idx = document.location.href.indexOf('#');
			
			return (idx >= 0) ? document.location.href.substr(idx+1) : '';
		}

		/* Get the current location hash excluding the '#' symbol. */
		function setHash(hash)
		{
			if (hash == '')
			{
				hash = '#';
			}
			
			document.location.hash = hash;
		}

		function createState(baseUrl, newUrl, flexAppUrl)
		{
			var result =
			{
				'baseUrl' : baseUrl,
				'newUrl' : newUrl,
				'flexAppUrl' : flexAppUrl,
				'title' : null 
			};
			
			return result; 
		}

		/* Add a history entry to the browser.
		 *   baseUrl: the portion of the location prior to the '#'
		 *   newUrl: the entire new URL, including '#' and following fragment
		 *   flexAppUrl: the portion of the location following the '#' only
		 */
		function addHistoryEntry(baseUrl, newUrl, flexAppUrl)
		{
			//delete all the history entries
			forwardStack = [];

			if ( $.browser.msie )
			{
				//Check to see if we are being asked to do a navigate for the first
				//history entry, and if so ignore, because it's coming from the creation
				//of the history iframe
				if ( flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload'] )
				{
					currentHref = initialHref;
					return;
				}
				
				if ( (!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload'] )
				{
					newUrl = baseUrl + '#' + defaultHash;
					flexAppUrl = defaultHash;
				}
				else
				{
					// for IE, tell the history frame to go somewhere without a '#'
					// in order to get this entry into the browser history.
					getHistoryFrame().attr({ 'src' : historyFrameSourcePrefix + flexAppUrl });
				}
				setHash(flexAppUrl);
			}
			else
			{
				if ( backStack.length == 0 && initialState.flexAppUrl == flexAppUrl )
				{
					initialState = createState(baseUrl, newUrl, flexAppUrl);
				}
				else if ( backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl )
				{
					backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
				}

				if ( $.browser.safari )
				{
					//for Safari, submit a form whose action points to the desired URL
					if ( $.browser.version <= 419.3 )
					{
						var file = window.location.pathname.toString();
							file = file.substring(file.lastIndexOf("/")+1);
							getFormElement().html('<form name="historyForm" id="historyForm" action="'+file+'#' + flexAppUrl + '" method="get"></form>');
							//get the current elements and add them to the form
							var qs = window.location.search.substring(1);
							var qs_arr = qs.split("&");
							for (var i = 0; i < qs_arr.length; i++)
							{
								var tmp = qs_arr[i].split("=");
								var elem = $("<input>").attr({ 'type' : 'hidden', 'name' : tmp[0], 'value' : tmp[1] });

								$('#historyForm').append(elem);
							}
							$('#historyForm').submit();
					}
					else
					{
						top.location.hash = flexAppUrl;
					}
					//We also have to maintain the history by hand for Safari
					historyHash[history.length] = flexAppUrl;
					_storeStates();
				}
				else
				{
					// Otherwise, write an anchor into the page and tell the browser to go there
					addAnchor(flexAppUrl);
					setHash(flexAppUrl);
				}
			}
			backStack.push(createState(baseUrl, newUrl, flexAppUrl));
		}

		function _storeStates()
		{
			if ( $.browser.safari )
			{
				getRememberElement().val(historyHash.join(","));
			}
		}

		function handleBackButton()
		{
			//The "current" page is always at the top of the history stack.
			var current = backStack.pop();
			if (!current)
			{
				return;
			}
			var last = backStack[backStack.length - 1];
			if (!last && backStack.length == 0)
			{
				last = initialState;
			}
			forwardStack.push(current);
		}

		function handleForwardButton()
		{
			//summary: private method. Do not call this directly.

			var last = forwardStack.pop();
			if (!last)
			{
				return;
			}
			backStack.push(last);
		}

		function handleArbitraryUrl()
		{
			//delete all the history entries
			forwardStack = [];
		}

		/* Called periodically to poll to see if we need to detect navigation that has occurred */
		function checkForUrlChange()
		{

			if ( $.browser.msie )
			{
				if ( currentHref != document.location.href && currentHref + '#' != document.location.href )
				{
					//This occurs when the user has navigated to a specific URL
					//within the app, and didn't use browser back/forward
					//IE seems to have a bug where it stops updating the URL it
					//shows the end-user at this point, but programatically it
					//appears to be correct.  Do a full app reload to get around
					//this issue.
					if ( $.browser.version < 7 )
					{
						currentHref = document.location.href;
						document.location.reload();
					}
					else
					{
						if ( getHash() != getIframeHash() )
						{
							// this.iframe.src = this.blankURL + hash;
							var sourceToSet = historyFrameSourcePrefix + getHash();
							getHistoryFrame().attr({ 'src' : sourceToSet });
						}
					}
				}
			}

			if ( $.browser.safari )
			{
				// For Safari, we have to check to see if history.length changed.
				if ( currentHistoryLength >= 0 && history.length != currentHistoryLength )
				{
					//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
					// If it did change, then we have to look the old state up
					// in our hand-maintained array since document.location.hash
					// won't have changed, then call back into BrowserManager.
					currentHistoryLength = history.length;
					var flexAppUrl = historyHash[currentHistoryLength];
					if ( !flexAppUrl )
					{
						flexAppUrl = window.location.hash.replace('#','');
					}
					getPlayer().get(0).browserURLChange(flexAppUrl);
					_storeStates();
				}
			}
			
			if ( $.browser.mozilla || $.browser.opera )
			{
				if ( currentHref != document.location.href )
				{
					var bsl = backStack.length;

					var urlActions =
					{
						back : false,
						forward : false,
						set : false
					};

					if ( (window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1) )
					{
						urlActions.back = true;
						handleBackButton();
					}

					// first check to see if we could have gone forward. We always halt on
					//a no-hash item.
					if ( forwardStack.length > 0 )
					{
						if (forwardStack[forwardStack.length-1].flexAppUrl == getHash())
						{
							urlActions.forward = true;
							handleForwardButton();
						}
					}

					// ok, that didn't work, try someplace back in the history stack
					if ( bsl >= 2 && backStack[bsl - 2] )
					{
						if (backStack[bsl - 2].flexAppUrl == getHash())
						{
							urlActions.back = true;
							handleBackButton();
						}
					}

					if ( !urlActions.back && !urlActions.forward )
					{
						var foundInStacks =
						{
								back : -1,
								forward : -1
						};

						for ( var i = 0; i < backStack.length; i++ )
						{
							if ( backStack[i].flexAppUrl == getHash() && i != (bsl - 2) )
							{
								arbitraryUrl = true;
								foundInStacks.back = i;
							}
						}
						
						for ( var i = 0; i < forwardStack.length; i++ )
						{
							if ( forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2) )
							{
								arbitraryUrl = true;
								foundInStacks.forward = i;
							}
						}
						handleArbitraryUrl();
					}

					// Firefox changed; do a callback into BrowserManager to tell it.
					currentHref = document.location.href;
					var flexAppUrl = getHash();

					getPlayer().get(0).browserURLChange(flexAppUrl);
				}
			}
		}

		/* Write an anchor into the page to legitimize it as a URL for Firefox et al. */
		function addAnchor(flexAppUrl)
		{
			var anchor = $('<a>').attr({ 'name' : flexAppUrl }).text(flexAppUrl);
			getAnchorElement().empty();
			getAnchorElement().append(anchor);
		}
		
		var _initialize = function ()
		{
			if ($.browser.msie)
			{
				$('script').each
				(
					function()
					{
						var source = $(this).attr('src');
						
						if( source && source.indexOf(HistoryFile) > -1 )
						{
							iframe_location = source.replace(HistoryFile, "historyFrame.html");
						}
					}
				);
            
				historyFrameSourcePrefix = iframe_location + "?";
            
				var iframe = $("<iframe>").attr({ 'id' : 'ie_historyFrame', 'name' : 'ie_historyFrame' });
				$('body').append(iframe);
			}

			if ($.browser.safari)
			{
				var rememberDiv = $("<div>").attr({ 'id' : 'safari_rememberDiv' });
				var input = $("<input>").attr({ "type" : "text", "id" : "safari_remember_field" });
				$('body').prepend(rememberDiv);
				rememberDiv.append(input);
				var formDiv = $("<div>").attr({ 'id' : 'safari_formDiv' });
				$('body').append(formDiv);
				var reloader_content = $('<div>').attr({ 'id' : 'safarireloader' });
				$('script').each
				(
					function()
					{
						var source = $(this).attr('src');
						
						if( source && source.indexOf(HistoryFile) > -1 )
						{
							html = source.replace(".js", ".html");
						}
					}
				);
            
				var reloader_content = $('<iframe>').attr({ "id" : "safarireloader-iframe", "src" : "about:blank", "frameborder" : "no", "scrolling" : "no"});
				$('body').append(reloader_content);
				reloader_content.css({ 'position' : 'absolute', 'left' : '-9999px' }) ;
				iframe = reloader_content;

				if ($("#safari_remember_field").val() != "" )
				{
					historyHash = $("#safari_remember_field").val().split(",");
				}
			}

			if ($.browser.mozilla || $.browser.opera)
			{
				var anchorDiv = $("<div>").attr({ 'id' : 'firefox_anchorDiv' });
				$('body').prepend(anchorDiv);
			}
		};

		var result = 
		{
			historyHash : historyHash,
			backStack : function()
			{
				return backStack;
			},
			forwardStack : function()
			{
				return forwardStack;
			},
			getPlayer : getPlayer,
			initialize : function(src)
			{
				_initialize(src);
			},
			setURL : function(url)
			{
				document.location.href = url;
			},
			getURL : function()
			{
				return document.location.href;
			},
			getTitle : function()
			{
				return document.title;
			},
			setTitle : function(title)
			{
				try
				{
					if(backStack && backStack.length)
					{
						backStack[backStack.length - 1].title = title;
					}
				}
				catch(e)
				{
					
				}
				//if on safari, set the title to be the empty string.
				if ( $.browser.safari )
				{
					if ( title == "" )
					{
						try
						{
							var tmp = window.location.href.toString();
							title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
						}
						catch(e)
						{
							title = "";
						}
					}
				}
			},
			setDefaultURL : function( def )
			{
				defaultHash = def;
				def = getHash();
				//trailing ? is important else an extra frame gets added to the history
				//when navigating back to the first page.  Alternatively could check
				//in history frame navigation to compare # and ?.
				if ( $.browser.msie )
				{
					window['_ie_firstload'] = true;
					var sourceToSet = historyFrameSourcePrefix + def;
                
					var func = function()
					{
						if( getHistoryFrame().get(0) )
						{
							getHistoryFrame().attr({ 'src' : sourceToSet });
							window.location.replace("#" + def);
							setInterval(checkForUrlChange, 1500);
						}
						else
						{
							HistoryTime=window.setTimeout
							(
								function()
								{
									func();
								},
								1000
							);	
						}
					};
					try
					{
						func();
					}
					catch(e)
					{
						HistoryTime = window.setTimeout
						(
							function()
							{
								func();
							},
							1000
						);
					}
				}

				if ( $.browser.safari )
				{
					currentHistoryLength = history.length;
					if (historyHash.length == 0)
					{
						historyHash[currentHistoryLength] = def;
						var newloc = "#" + def;
						window.location.replace(newloc);
						setInterval(checkForUrlChange, 500);
					}
				}

				if ( $.browser.mozilla )
				{
					var reg = new RegExp("#" + def + "$");
					if (window.location.toString().match(reg))
					{
					}
					else
					{
						var newloc ="#" + def;
						window.location.replace(newloc);
					}
					setInterval(checkForUrlChange, 50);
				}
				
				if ( $.browser.opera )
				{
					var reg = new RegExp("#" + def + "$");
					if (window.location.toString().match(reg))
					{
					}
					else
					{
						var newloc ="#" + def;
						window.location.replace(newloc);
					}
					setInterval(checkForUrlChange, 500);
				}
			},

			/* Set the current browser URL; called from inside BrowserManager to propagate
			 * the application state out to the container.
			 */
			setBrowserURL : function(flexAppUrl, objectId)
			{	
				if ( $.browser.msie && typeof objectId != "undefined" )
				{
					currentObjectId = objectId;
				}
				
				var pos = document.location.href.indexOf('#');
				var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
				var newUrl = baseUrl + '#' + flexAppUrl;

				if (document.location.href != newUrl && document.location.href + '#' != newUrl)
				{
					currentHref = newUrl;
					addHistoryEntry(baseUrl, newUrl, flexAppUrl);
					currentHistoryLength = history.length;
				}
				
				return false;
			},

			browserURLChange: function(flexAppUrl)
			{
				var objectId = null;
				if ( $.browser.msie && currentObjectId != null )
				{
					objectId = currentObjectId;
				}
				pendingURL = '';

				getPlayer(objectId).get(0).browserURLChange(flexAppUrl);

				currentObjectId = null;
			}
		};
		
		return result;
	}
)();

// Initialization

// Automated unit testing and other diagnostics

function setURL(url)
{
	document.location.href = url;
}

function backButton()
{
	history.back();
}

function forwardButton()
{
	history.forward();
}

function goForwardOrBackInHistory(step)
{
	history.go(step);
}

(function(i) {
	$(document).ready
	(
		function()
		{
			i();
		}
	);
})( function() { BrowserHistory.initialize(); } );
