/*
Script: CiUI.js

Handles iPhone-optimized pages and mimics iPhone UI behavior

License:
	http://clientside.cnet.com/wiki/cnet-libraries#license
*/

(function() {

var bodyEl; // see ciUI.initialize() for details
var buttonForward = "go_forward";
var buttonBackward = "go_back";
var backButtonEl; // see ciUI.initialize() for details
var backButtonTextEl; // see ciUI.initialize() for details
var pageTitleEl; // see ciUI.initialize() for details

var pages = []; // see ciUI.initialize() for details
var pageHistory = []; 

var homePage = location.href;
var hashPrefix = "#__";
var currentHash = location.hash;
var currentPage = 1; // possible values are 1 or -1 (1: from, -1: to)

var animSpeed = 20; // smaller number means slower animation
var navigationCheckInterval = 300;
var navigtionChangeTimer;

window.ciUI = {
	initialize: function() {
		bodyEl = $("iphone_body");
		backButtonEl = $("iphone_backbutton");
		backButtonTextEl = $("iphone_backbutton_text");
		pageTitleEl = $("iphone_title");
		if (pageTitleEl.innerHTML == "") pageTitleEl.innerHTML = document.title;
		this.setupPages();
		this.animating = false;
		setTimeout(scrollTo, 100, 0, 1);
	},
	
	setupPages: function() {
		var page1 = document.createElement('div');
		var page2 = document.createElement('div');
		var home  = document.createElement('div');
		var ascrolltop = document.createElement('a');

		page1.id = "__page1__";
		page1.className = "iphone_page";
		page1.style.left = "0%";
		page1.style.display = "block";
		
		page2.id = "__page2__";
		page2.className = "iphone_page";
		page2.style.left = "100%";
		page2.style.display = "none";
		
		home.id	= "__home__";
		home.style.display = "none";
		ascrolltop.id = "__scroll_top__";
		ascrolltop.name = "";
		
		page1.innerHTML = home.innerHTML = bodyEl.innerHTML;
		bodyEl.innerHTML = "";
		bodyEl.appendChild(page1);
		bodyEl.appendChild(page2);		
		document.body.appendChild(home);
		document.body.insertBefore(ascrolltop, document.body.firstChild);

		this.adjustBodyToEl(page1);
	
		pages[1] = $(page1.id);
		pages[0] = $(home.id);
		pages[-1] = $(page2.id);
	},
	
	goToPage: function(target, backwards) {
		if (backwards === undefined) backwards = false;

		this.slidePages(backwards);
		// BACKWARD
		if (backwards) { 
			currentHash = location.hash;
			pageHistory.splice(pageHistory.indexOf(target)+1, pageHistory.length);
		}
		// FORWARD
		else {
   			pageHistory.push(target);								
		}
		this.updatePage(target);				
	},
	
	updatePage: function(target) {
		var nextHash = hashPrefix + (pageHistory.length);
		backButtonEl.style.display = (pageIndexFromHash(nextHash) == 0 || !target) ? "none" : "block";
		// Update body with new page content
		if (pageIndexFromHash(nextHash) == 0 || !target) {
			pageTitleEl.innerHTML = trim(document.title);
			this.updatePageContent(pages[0].innerHTML); // page[0] is home, no need for AJAX
		}			
		else {
			backButtonTextEl.innerHTML = (pageHistory[pageHistory.length-2]) ? trim(pageHistory[pageHistory.length-2].title, 15) : "Back";
			pageTitleEl.innerHTML = trim(target.title);			
			(new this.ajax(target.href, this.updatePageContent)).run();			
		}
	},
	
	updatePageContent: function(content) {
		var updateTimer = setInterval(update, 0);
			
		function update() {
			if (!ciUI.animating) {
				$("__scroll_top__").name = currentHashName(true);
				pages[currentPage].innerHTML = content;
				pages[-currentPage].innerHTML = "";
				clearInterval(updateTimer);								
				ciUI.adjustBodyToEl(pages[currentPage]);				
				location.href = currentHash = currentHashName();
				if (ciUI.callbackFunct) ciUI.callbackFunct();
			}			
		}		
	},
	
	slidePages: function(backwards) {
		this.animating = true;
		
		var fromPage = pages[currentPage];
		var toPage = pages[-currentPage];
		var progress = 100;
		
		toPage.innerHTML = this.loadingPage();
		toPage.style.display = "block";
		
		if (!backwards) toPage.style.left = "100%";
		
		clearInterval(navigationChangeTimer); // pause the history daemon during animation.
		setTimeout(scrollTo, 100, 0, 1);
		var animTimer = setInterval(animate, 0);
		
		function animate() {
			progress -= animSpeed;
			
			if (progress <= 0) {
				clearInterval(animTimer);				
				navigationChangeTimer = setInterval(navigationChangeAgent, navigationCheckInterval); // restart the history daemon
				currentPage *= -1;
				progress = 0;
				ciUI.animating = false;
			}			
			fromPage.style.left = (backwards ? (100 - progress) : (progress - 100)) + "%";
			toPage.style.left = (backwards ? -progress : progress) + "%";
		}
	},
	
	ajax: function(sourceURL, responseConsumer, responseType) {
		var httpRequest = false;
		
		this.run = function()
		{
			if (responseType === undefined) responseType = "TEXT";
			responseType = responseType.toUpperCase();
			
			if (window.XMLHttpRequest) { 
				httpRequest = new XMLHttpRequest();
				if (httpRequest.overrideMimeType) {
					httpRequest.overrideMimeType('text/xml');
				}
			} 
			else if (window.ActiveXObject) { 
				try {
					httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
				} 
				catch (e) {
					try {
						httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
					} 
					catch (e) {}
				}
			}
			
			if (!httpRequest) {
				console.log('Giving up, cannot create an XMLHTTP instance');
				return false;
			}
	
			httpRequest.open('GET', sourceURL, true);
			httpRequest.onreadystatechange = getResponse;
			httpRequest.send(null);	
		}
		
		function getResponse() {	
			if (httpRequest.readyState == 4)
				if (httpRequest.status == 200) {
					if (responseType == "XML")
						responseConsumer(httpRequest.responseXML);
					else
						responseConsumer(httpRequest.responseText);
				}
				else
					console.log("There was a problem with the request: " + sourceUrl);
		}
	},
	
	submitForm: function(form) {
		var target = new Object();
		target.href = form.actionURL.value + "&query=" + form.query.value;
		target.title= form.title;
		this.goToPage(target);
	},
	
	cancel: function(event) {
		pageHistory = [];
		location.reload(true);
		location.hash = "";
		location.href = homePage;
		return false;
	},
	
	loadingPage: function() {
		return $("iphone_loading_page").innerHTML;
	},
	
	// a dirty hack to move the footer to proper location since iphone_body doesn't expand with content
	adjustBodyToEl: function(el) {
		bodyEl.style.height = el.offsetHeight + "px";
	}	
}

addEventListener("load", function(event) {
	ciUI.initialize();
	navigationChangeTimer = setInterval(navigationChangeAgent, navigationCheckInterval);
}, false);

addEventListener("click", function(event) {
	var a = findParent(event.target, "a");
	// We don't want to prevent defaults by default because there may be actual hrefs going to outside pages
	if (a && a.hasClass(buttonForward)) {
		ciUI.goToPage(a);
		event.preventDefault();
	} else if (a && a.hasClass(buttonBackward)) {
		history.back();	
		event.preventDefault();
	}	
}, true);

function trim(text, maxLength) {
	if (maxLength === undefined) maxLength = 20;
	return (text.length > maxLength) ? text.substring(0, maxLength - 3) + "..." : text;
}

function currentHashName(ommitHashSymbol) {
	return (ommitHashSymbol) ? hashPrefix.substr(1, hashPrefix.length) + (pageHistory.length) : hashPrefix + (pageHistory.length);
}

function navigationChangeAgent() {
	if (currentHash != location.hash) {
		ciUI.goToPage(pageHistory[pageHistory.length-2], true);
	}
}

function pageIndexFromHash(hash) {
	return (hash) ? hash.substr(hash.lastIndexOf("_") + 1, hash.length) : 0;
}


Element.prototype.hasClass = function(name) {
	return this.className.indexOf(name) != -1;
}

// This function is courtesy of iUI
function findParent(node, localName) {
    while (node && (node.nodeType != 1 || node.localName.toLowerCase() != localName))
        node = node.parentNode;
    return node;
}

function $(id) { return document.getElementById(id); }

})();
