var _HistoryCurrentToken 	= null;
var _HistoryIframe 			= null;
var _HistoryCurrentURL 		= '';
var _HistoryInterval		= null;

function GetHash()
{
	var href 	= location.href;
	var i 		= href.indexOf("#");
	
	if (i >= 0)
	{
		return href.substr(i + 1);
	}
	else
	{
		return '';
	}
}

/*
returns true if the histroy frame is needed, internet explorer 6 and 7 needs to use the iframe for navigation, other browsers don't
*/
function NeedsHistoryIframe()
{
	if (Ext.isIE7 || Ext.isIE6)
	{
		return true;
	}
	
	return false;
}

/*
creates the histroy iframe if needed, then starts the loops thay will check de url for changes
*/
function InitHistory()
{
	if (NeedsHistoryIframe())
	{
		//ie6 and ie7 have problems with the conventional way of doing history, we need to create an iframe, then check the iframe
		var iframeHistory = document.getElementById('x-history-frame');
		
		if (iframeHistory == undefined)
		{
			frmHistory = document.getElementById('history-form');
			
			if (frmHistory)
			{
				frmHistory.innerHTML += '<iframe id="x-history-frame" src="/historyblank.html"></iframe>';
			}
		}
		
		_HistoryIframe = Ext.getDom('x-history-frame');
		
		CheckIFrame();
	}
	else
	{
		//the conventional way of doing history
		CheckURL();
	}
}

/*
adds a new hash to the history
*/
function AddHash(hash)
{
	if (NeedsHistoryIframe())
	{
		//adds the hash to the iframe for ie6/ie7
		hash = RemoveSharp(hash);
		
		return UpdateIFrame(hash);
	}
	else
	{
		//changes the hash for other browsers
		location.hash = hash;
	}
}

function RemoveSharp(hash)
{
	if (hash.indexOf('#') === 0)
	{
		hash = hash.substr(1, hash.length);
	}
	
	return hash;
}

/*
This function is in charge of checking changes on the iframe, when the user clicked a link or clicked the back/next browser buttons
When a change is detected PageChanged is called
*/
function CheckIFrame()
{
	/*checks if the iframe already exists (it should ;D)*/
    if (!_HistoryIframe.contentWindow || !_HistoryIframe.contentWindow.document)
    {
        setTimeout(CheckIFrame, 10);
        return;
    }

    var doc 	= _HistoryIframe.contentWindow.document;
    var elem 	= doc.getElementById("state");
    var token 	= elem ? elem.innerText : '';
    var hash 	= GetHash();

    /*
    here is the loop, everytime a page is changed (clicked on a link, or clicked back/next) the "state" div inside the iframe is changed.
    if state is different than the actual state (token) we know that the user requested a new page, so que call PageChanged
    */
    _HistoryInterval = setInterval(function ()
    {
        doc 	= _HistoryIframe.contentWindow.document;
        elem 	= doc.getElementById("state");
		
        var newtoken 	= elem ? elem.innerText : '';
        var newHash 	= GetHash();
		
        hash = token;
        
        if (newtoken !== token)
        {
            token 					= newtoken;
            location.hash 			= token;
            hash 					= token;
            _HistoryCurrentToken	= token;
            
            UpdateHash(token);
            PageChanged(token);
        }
        else if (newHash !== hash)
        {
            hash = newHash;
            
            UpdateIFrame(newHash);
        }
    }, 50);
}

/*
we change the hash to show the user a new url everytime que changed the page, so he can bookmark or send a link (only used with iframe)
*/
function UpdateHash(token)
{
	if (token == null)
	{
		location.hash = '';
	}
	else
	{
		location.hash = token;
	}
}

/*
updates the status inside the iframe when a new page is clicked (this change will be detected by CheckFrame)
*/
function UpdateIFrame(token)
{
	var html = ['<html><head></head><body><div id="state">',token,'</div></body></html>'].join('');
	
	try
	{
		var doc = _HistoryIframe.contentWindow.document;
		
		doc.open();
		doc.write(html);
		doc.close();
		
		return true;
	}
	
	catch (e)
	{
		return false;
	}
}

function CheckURL()
{
	/*
	here is the loop that will check if the url has changed, this means that the user clicked a link or a back/next button
	please note that this function is not used on ie6 or ie7 because history does not work like we need to.
	For those browsers check CheckIFrame function
	*/
	_HistoryInterval = setInterval(function ()
	{
		var hash = GetHash();
			
		if (_HistoryCurrentURL != hash)
		{
			PageChanged(hash);
			
			_HistoryCurrentURL = hash;
		}
	}, 50);
}

/*
this function is called everytime a page has changed
*/
function PageChanged(hash)
{
	if (hash != '')
	{
		var onCompleteFn 	= undefined;
		var parts 			= hash.split('?');
		var	url				= parts[0];
		
		if (typeof parts[1] != 'undefined')
		{
			var params		= parts[1].split('&');
			var ajaxParams 	= {};
			var te			= '';
			
			for (var i = 0; i < params.length; i++)
			{
				var param 	= params[i].split('=');
				var param0 	= decodeURIComponent(param[0]);
				var param1 	= decodeURIComponent(param[1]);
				
				if ((param0 != 'h_te') && (param0 != 'h_cf'))
				{
					ajaxParams[param0] = param1;
				}
				else
				{
					if (param0 == 'h_te')
					{
						te = decode64(param1);
					}
					else if (param0 == 'h_cf')
					{
						onCompleteFn = decode64(param1);
					}
				}
			}

			loadAjaxPage(url, te, {ajaxParams: ajaxParams, onCompleteFn: onCompleteFn});
		}
	}
	else
	{
		var url 		= location.href;
		var sharpPos 	= url.indexOf('#');
		var te 			= 'ajaxBodyContainer';
		
		if (sharpPos != -1)
		{
			url = url.substr(0, sharpPos);
		}
		
		loadAjaxPage(url, te, {ajaxParams: ajaxParams});
	}
}

/*
Function used by the javascript function LoadAjaxPage
(please note that history added with this won't be able to be opened on a new tab)
*/
function AddHistory(url, elementId, params, onCompleteFn)
{
	hash = BuildHash(url, elementId, params, onCompleteFn);
	
	AddHash(hash);
}

function BuildHash(url, elementId, params, onCompleteFn)
{
	if (typeof(params) == 'undefined')
	{
		params = {};
	}
	
	params['h_te'] = encode64(elementId);
	
	var h_te = params['h_te'];
	
	if (typeof(onCompleteFn) != 'undefined')
	{
		params['h_cf'] = encode64(onCompleteFn);
	}
	
	params = PrepareParamsForHistory(params);
	
	var hash = url + '?' + params;
	
	return hash;
}

function PrepareParamsForHistory(params)
{
	param = [];
	
	for (elemento in params)
	{
		param.push(encodeURIComponent(elemento) + '=' + encodeURIComponent(params[elemento]));
	}
	
	return param.join('&');
}

/*
changes the actual url and makes believe the url checker that it never changed, this way the page won't reload and will be inserted in the navigators history
*/
function MockURL(url)
{
	FreezeHistoryInterval();
	
	AddHash(url);
	
	_HistoryCurrentURL = url;
	
	UnFreezeHistoryInterval();
}

function FreezeHistoryInterval()
{
	clearInterval(_HistoryInterval);
}

function UnFreezeHistoryInterval()
{
	InitHistory();
}

/*
Adds a Js Script to actual page
*/
function AddScript(path, force, callback)
{
	var isLoaded = ScriptIsLoaded(path);

	if ((typeof(isLoaded) == 'object') && (force == true))
	{
		isLoaded.parentNode.removeChild(isLoaded);
		
		isLoaded = false;
	}
	
	if (!isLoaded)
	{
		var scriptTag = document.createElement('script');
		scriptTag.setAttribute('type', 'text/javascript');
		scriptTag.setAttribute('src', path);

		var headLoc = document.getElementsByTagName('head').item(0);
		
		var done = false;
		
		scriptTag.onload = scriptTag.onreadystatechange = function()
		{
			if ( !done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") )
			{
				done = true;
				
				if (typeof(callback) == 'function')
				{
					callback();
				}
				
				/* handle memory leak in IE */
				scriptTag.onload = scriptTag.onreadystatechange = null;
			}
		};
		
		headLoc.appendChild(scriptTag);
	}
	else
	{
		if (typeof(callback) == 'function')
		{
			callback();
		}
	}
}

function ScriptIsLoaded(path)
{
	scripts = document.getElementsByTagName('script');
	
	for (x = 0; x < scripts.length; x++)
	{
		src = scripts[x].getAttribute('src');
		
		if (src != undefined)
		{
			if (src == path)
			{
				return scripts[x];
			}
		}
	}
	
	return false;
}

/*
Adds a CSS Stylesheet to actual page
*/

function AddStyleSheet(path)
{
	isLoaded = StyleSheetIsLoaded(path);
	
	if (!isLoaded)
	{
		styleSheetTag = document.createElement('link');
		styleSheetTag.setAttribute('rel', 'stylesheet');
		styleSheetTag.setAttribute('type', 'text/css');
		styleSheetTag.setAttribute('href', path);
		
		headLoc = document.getElementsByTagName('head').item(0);
		headLoc.appendChild(styleSheetTag);
	}
}

function StyleSheetIsLoaded(path)
{
	styleSheets = document.getElementsByTagName('link');
	
	for (x = 0; x < styleSheets.length; x++)
	{
		src = styleSheets[x].getAttribute('href');
		
		if (src != undefined)
		{
			if (src == path)
			{
				return true;
			}
		}
	}
	
	return false;
}
