dojo.provide("dojo.back");

// NOTE:
//	Slightly hacked version. I didn't see IE working with this and an xdmoain at ALL
//  Just removed the IE specific code for testing the hash and left the timer.
//	Also stripped all the comments since this won't be in a build (?).


(function(){ 
	var back = dojo.back;

	// everyone deals with encoding the hash slightly differently

	function getHash(){ 
		var h = window.location.hash;
		if(h.charAt(0) == "#"){ h = h.substring(1); }
		return dojo.isMozilla ? h : decodeURIComponent(h); 
	}
	
	function setHash(h){
		if(!h){ h = ""; }
		window.location.hash = encodeURIComponent(h);
		historyCounter = history.length;
	}
	
	// if we're in the test for these methods, expose them on dojo.back. ok'd with alex.
	if(dojo.exists("tests.back-hash")){
		back.getHash = getHash;
		back.setHash = setHash;		
	}
	
	var initialHref = (typeof(window) !== "undefined") ? window.location.href : "";
	var initialHash = (typeof(window) !== "undefined") ? getHash() : "";
	var initialState = null;

	var locationTimer = null;
	var bookmarkAnchor = null;
	var historyIframe = null;
	var forwardStack = [];
	var historyStack = [];
	var moveForward = false;
	var changingUrl = false;
	var historyCounter;

	function handleBackButton(){
		var current = historyStack.pop();
		if(!current){ return; }
		var last = historyStack[historyStack.length-1];
		if(!last && historyStack.length == 0){
			last = initialState;
		}
		if(last){
			if(last.kwArgs["back"]){
				last.kwArgs["back"]();
			}else if(last.kwArgs["backButton"]){
				last.kwArgs["backButton"]();
			}else if(last.kwArgs["handle"]){
				last.kwArgs.handle("back");
			}
		}
		forwardStack.push(current);
	}

	back.goBack = handleBackButton;

	function handleForwardButton(){
		var last = forwardStack.pop();
		if(!last){ return; }
		if(last.kwArgs["forward"]){
			last.kwArgs.forward();
		}else if(last.kwArgs["forwardButton"]){
			last.kwArgs.forwardButton();
		}else if(last.kwArgs["handle"]){
			last.kwArgs.handle("forward");
		}
		historyStack.push(last);
	}

	back.goForward = handleForwardButton;

	function createState(url, args, hash){
		return {"url": url, "kwArgs": args, "urlHash": hash};	//Object
	}

	function getUrlQuery(url){
		var segments = url.split("?");
		if(segments.length < 2){
			return null; //null
		}
		else{
			return segments[1]; //String
		}
	}
	
	function loadIframeHistory(){
		var url = (dojo.config["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html")) + "?" + (new Date()).getTime();
		moveForward = true;
        if(historyIframe){
		    dojo.isWebKit ? historyIframe.location = url : window.frames[historyIframe.name].location = url;
        }else{
            //console.warn("dojo.back: Not initialised. You need to call dojo.back.init() from a <script> block that lives inside the <body> tag.");
        }
		return url; //String
	}

	function checkLocation(){
		if(!changingUrl){
			var hsl = historyStack.length;
			
			var hash = getHash();

			if((hash === initialHash||window.location.href == initialHref)&&(hsl == 1)){
				handleBackButton();
				return;
			}
			
			if(forwardStack.length > 0){
				if(forwardStack[forwardStack.length-1].urlHash === hash){
					handleForwardButton();
					return;
				}
			}
			
			if((hsl >= 2)&&(historyStack[hsl-2])){
				if(historyStack[hsl-2].urlHash === hash){
					handleBackButton();
					return;
				}
			}
			
			if(dojo.isSafari && dojo.isSafari < 3){
				var hisLen = history.length;
				if(hisLen > historyCounter) handleForwardButton();
				else if(hisLen < historyCounter) handleBackButton();
			  historyCounter = hisLen;
			}
		}
	};
	
	back.init = function(){
		if(dojo.byId("dj_history")){ return; } // prevent reinit
		var src = dojo.config["dojoIframeHistoryUrl"] || dojo.moduleUrl("dojo", "resources/iframe_history.html");
		document.write('<iframe style="border:0;width:1px;height:1px;position:absolute;visibility:hidden;bottom:0;right:0;" name="dj_history" id="dj_history" src="' + src + '"></iframe>');
	};

	back.setInitialState = function(/*Object*/args){
		initialState = createState(initialHref, args, initialHash);
	};

	back.addToHistory = function(/*dojo.__backArgs*/ args){

		forwardStack = []; 

		var hash = null;
		var url = null;
		if(!historyIframe){
			if(dojo.config["useXDomain"] && !dojo.config["dojoIframeHistoryUrl"]){
				console.warn("dojo.back: When using cross-domain Dojo builds,"
					+ " please save iframe_history.html to your domain and set djConfig.dojoIframeHistoryUrl"
					+ " to the path on your domain to iframe_history.html");
			}
			historyIframe = window.frames["dj_history"];
		}
		if(!bookmarkAnchor){
			bookmarkAnchor = dojo.create("a", {style: {display: "none"}}, dojo.body());
		}
		if(args["changeUrl"]){
			hash = ""+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime());
			if(historyStack.length == 0 && initialState.urlHash == hash){
				initialState = createState(url, args, hash);
				return;
			}else if(historyStack.length > 0 && historyStack[historyStack.length - 1].urlHash == hash){
				historyStack[historyStack.length - 1] = createState(url, args, hash);
				return;
			}

			changingUrl = true;
			setTimeout(function() { 
				setHash(hash); 
				changingUrl = false; 					
			}, 1);
			bookmarkAnchor.href = hash;
			
			// start the timer
			if(!locationTimer){
				locationTimer = setInterval(checkLocation, 200);
			}
			
			
		}else{
			url = loadIframeHistory();
		}

		historyStack.push(createState(url, args, hash));
	};

	back._iframeLoaded = function(evt, ifrLoc){
		var query = getUrlQuery(ifrLoc.href);
		if(query == null){ 
			if(historyStack.length == 1){
				handleBackButton();
			}
			return;
		}
		if(moveForward){
			moveForward = false;
			return;
		}
	
		if(historyStack.length >= 2 && query == getUrlQuery(historyStack[historyStack.length-2].url)){
			handleBackButton();
		}else if(forwardStack.length > 0 && query == getUrlQuery(forwardStack[forwardStack.length-1].url)){
			handleForwardButton();
		}
	};
 })();
