function Flurl()
{
	/**
	 * Browser
	 */
	var ua 				    = navigator.userAgent.toLowerCase(); 
	var isGecko           	= (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1);
	var isAppleWebKit       = (ua.indexOf('applewebkit') != -1);
	var isSafari      	    = (ua.indexOf('safari') != - 1);
	var isOpera             = (ua.indexOf('opera') != -1); 
	var isIE          	    = (ua.indexOf('msie') != -1 && !isOpera && (ua.indexOf('webtv') == -1)); 
	var isMozilla           = (isGecko && ua.indexOf('gecko/') + 14 == ua.length);
	var isFirefox           = (ua.indexOf('firefox/') != -1 || ua.indexOf('firebird/') != -1);
	var browserVersion	 	= parseFloat(navigator.appVersion);
	
	/**
	 * Browser Version
	 */
	if (isGecko && !isMozilla)  	    	{browserVersion = parseFloat(ua.substring(ua.indexOf('/', ua.indexOf('gecko/') + 6) + 1));}
	else if (isMozilla)         	  	    {browserVersion = parseFloat(ua.substring(ua.indexOf('rv:') + 3));}
	else if (isIE && browserVersion >= 4) 	{browserVersion = parseFloat(ua.substring(ua.indexOf('msie ') + 5));}
	else if (isSafari)               		{browserVersion = parseFloat(ua.substring(ua.lastIndexOf('version/') + 8));}
	else if (isOpera)                		{browserVersion = parseFloat(ua.substring(ua.indexOf('opera') + 6));}
	
	/**
	 * We only need the major version
	 */
	var browserVersion = parseInt(browserVersion); 
	
	/**
	 * Flurl Vars
	 */
	var version      	   = 1.7;
	var currentURL         = "";
	var currentTitle 	   = document.title;
	var swf          	   = null;
	var callbackMethods    = Array();
	var minWidth		   = 0;
	var minHeight		   = 0;
	var f       		   = null;
	var l                  = location;
	
	/**
	 * PRIVATE
	 */
	
	var getHash = function()
	{
		return decodeURI(l.href).split('#')[1] || ''; 
	};
	
	var urlIsValid = function(u)
	{
		return ((u != null) && (u.length > 0) && (u != "/") && (u != "#"))
	};
	
	var checkForHashChange = function()
	{
	    var s = getHash();
	    if(s != currentURL)
	    {
	        currentURL = s;
	        for (var i = callbackMethods.length - 1; i >= 0; i--)
	        {
	            eval("swf."+callbackMethods[i]+"('"+currentURL+"')");
	        }
	    }
	
	    setTimeout(checkForHashChange, 250);
	};
	
	var iFrameLoad = function(u)
	{
		doc = document.getElementById("flurlFrame").contentWindow.document;
        doc.open("javascript:'<html></html>'");
        doc.write("<html><head><title>"+currentTitle+"</title><scri" + "pt type=\"text/javascript\">parent.flurl.iFrameLoaded('"+u+"');</scri" + "pt></head><body></body></html>");
        doc.close();
	};
	
	var updateMinSize = function()
	{
		if(minWidth > 0 && swf != null)
		{
			if(isIE) 
				swf.style.width = document.body.clientWidth < minWidth ? minWidth+"px" : "100%";
			else 
				swf.style.minWidth = minWidth+"px";
		}
		
		if(minHeight > 0 && swf != null)
		{
			if(isIE) 
				swf.style.height = document.body.clientHeight < minHeight ? minHeight+"px" : "100%";
			else 
				swf.style.minHeight = minHeight+"px";
		}
	};
	
	/**
	 * PUBLIC
	 */
	 
	this.init = function()
	{	        	
	    currentURL = getHash();
	    
	    if(isIE)
	    {
	        iframeHTML = '<iframe id="flurlFrame" src="javascript:false" style="display:none"></iframe>';
	        document.write(iframeHTML);
	        f = document.getElementById("flurlFrame");
			iFrameLoad(currentURL);
			window.attachEvent('onload', function(){ document.title = currentTitle; });
	    }
	    
	    window.onresize = function(){ updateMinSize(); };
	    
	    checkForHashChange();
	};
	 
	this.iFrameLoaded = function(hash)
	{
	    l.hash = hash;
		document.title = currentTitle;
	};
	
	this.setSwf = function(id)
	{
	    swf = document.getElementById(id);
	    updateMinSize();

	    return (swf != null);
	};
	
	this.getSwf = function(id)
	{
	    return swf;
	};
	
	this.addCallback = function(listener)
	{
	    if(callbackMethods[listener] != null)
	    return;
	
	    callbackMethods.push(listener);
	};
	
	this.removeCallback = function(listener)
	{
		callbackMethods.splice(callbackMethods.indexOf(listener),1);
	};
	
	this.setURL = function(urlString, append)
	{
	    if(!urlIsValid(urlString)) urlString = "";
	    
	    if(urlString == currentURL)
	    return;
	    
	    if(append)
	    	currentURL += String(urlString);
	    else
	    	currentURL = String(urlString);
	        
	    if(isSafari)
	    {
	        evt = document.createEvent("MouseEvents");
	        evt.initEvent("click",true,true);
	        lnk = document.createElement("a");
	        lnk.href="#"+currentURL;
	        lnk.dispatchEvent(evt);
	    }
	    else if(isIE)
	    {
	    	iFrameLoad(currentURL);
	    }
	    else 
	    {
	    	l.hash = "#"+currentURL;
	    }
	};
	
	this.getURL = function()
	{
	    return currentURL;
	};
	
	this.setPageTitle = function(title, append)
	{       
	    if(title == null) title = "";
	    
	    if(append)
	    	currentTitle += String(title);
	    else
	    	currentTitle = String(title);
	
	 	document.title = currentTitle;
	};
	
	this.getPageTitle = function()
	{
	    return currentTitle;
	};
	
	this.setMinWidth = function(w)
	{
		minWidth = w;
		updateMinSize();
	};

	this.getMinWidth = function()
	{
		return minWidth;
	};
	
	this.setMinHeight = function(h)
	{
		minHeight = h;
		updateMinSize();
	};
	
	this.getMinHeight = function()
	{
		return minHeight;
	};
	
	this.flurlStatus = function()
	{
	    var fs = "Flurl Version: "+version+"\n" +
	    "Main swf loaded: "+(swf != null)+"\n" +
	    "Number of Callback Methods: "+callbackMethods.length+"\n" +
	    "Using iFrame: "+(f!=null)+"\n" +
	    "Browser Version: "+browserVersion+"\n" +
	    "Current URL: "+currentURL+"\n" +
	    "Current Title: "+currentTitle;
	    alert(fs);
	};
	
	this.getFlurlVersion = function()
	{
	    return version;
	};
}

var flurl = new Flurl();
flurl.init();