/*
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

// Most of the code comes from the Ikiwiki project <http://ikiwiki.info/>



// CHTML creates real elements from HTML code contained in comments of the form "<!--(CHTML) ... -->".
// This allows for conditional HTML to be defined outside of JS code.

var CHTML = {
	callbacks: [],
	parse: function() {
		comments = document.evaluate('//comment()', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
		for(i = 0; i < comments.snapshotLength; i++) {
			comment = comments.snapshotItem(i);
			
			// Check it is a CHTML comment
			if(comment.nodeValue.substring(0,7) != '(CHTML)') continue;
			
			// Create the elements
			temp = document.createElement('div');
			temp.innerHTML = comment.nodeValue.substring(7);
			
			// Callbacks
			r = null;
			for(j = 0; j < this.callbacks.length; j++) {
				r = this.callbacks[j](temp);
				if(r == false) break;
				if(r instanceof Element) temp = r;
			}
			if(r == false) continue;
			
			// Replace the comment by the elements
			for(k = 0; k < temp.childNodes.length; k++) {
				comment.parentNode.insertBefore(temp.childNodes[k], comment);
			}
			comment.parentNode.removeChild(comment);
		}
	}
};



// cookies class
var Cookies = {
	get: function(key) {
		var o = new RegExp("(?:^|; ?)" + escape(key) + "=([^;]+)").exec(document.cookie);
		return o && unescape(o[1]);
	},
	
	set: function(key, value, days) {
		var expires = "";
		if(days) expires = "; expires=" + new Date(new Date().getTime() + days*24*60*60*1000).toGMTString();
		document.cookie = escape(key) + "=" + escape(value) + expires + "; path=/";
	},
	
	erase: function(name) {
		this.set(name, "", -1);
	}
};



// call CHTML if admin cookie is set
if(Cookies.get('admin')) document.addEventListener('DOMContentLoaded', function(){CHTML.parse()}, false);



// Causes html elements in the 'relativedate' class to be displayed
// as relative dates. The date is parsed from the title attribute, or from
// the element content.

var dateElements;

document.addEventListener("DOMContentLoaded", getDates, false);

function getDates() {
	dateElements = document.getElementsByClassName('relativedate');
	for (var i = 0; i < dateElements.length; i++) {
		var elt = dateElements[i];
		var title = elt.attributes.title;
		var d = new Date(title ? title.value : elt.innerHTML);
		if (! isNaN(d)) {
			dateElements[i].date=d;
			elt.title=elt.innerHTML;
		}
	}

	showDates();
}

function showDates() {
	for (var i = 0; i < dateElements.length; i++) {
		var elt = dateElements[i];
		var d = elt.date;
		if (! isNaN(d)) {
			elt.innerHTML=relativeDate(d);
		}
	}
	setTimeout(showDates,30000); // keep updating every 30s
}

var timeUnits = new Array;
timeUnits['minute'] = 60;
timeUnits['hour'] = timeUnits['minute'] * 60;
timeUnits['day'] = timeUnits['hour'] * 24;
timeUnits['month'] = timeUnits['day'] * 30;
timeUnits['year'] = timeUnits['day'] * 364;
var timeUnitOrder = ['year', 'month', 'day', 'hour', 'minute'];

function relativeDate(date) {
	var now = new Date();
	var offset = date.getTime() - now.getTime();
	var seconds = Math.round(Math.abs(offset) / 1000);

	// hack to avoid reading just in the future if there is a minor
	// amount of clock slip
	if (offset >= 0 && seconds < 30 * timeUnits['minute']) {
		return "just now";
	}

	var ret = "";
	var shown = 0;
	for (i = 0; i < timeUnitOrder.length; i++) {
		var unit = timeUnitOrder[i];
		if (seconds >= timeUnits[unit]) {
			var num = Math.floor(seconds / timeUnits[unit]);
			seconds -= num * timeUnits[unit];
			if (ret)
				ret += "and ";
			ret += num + " " + unit + (num > 1 ? "s" : "") + " ";

			if (++shown == 2)
				break;
		}
		else if (shown)
			break;
	}

	if (! ret)
		ret = "less than a minute "

	return ret + (offset < 0 ? "ago" : "from now");
}



// Uses CSS to hide toggleables, to avoid any flashing on page load. The
// CSS is only emitted after it tests that it's going to be able
// to show the toggleables.
if (document.getElementById && document.getElementsByTagName && document.createTextNode) {
	document.write('<style type="text/css">div.toggleable { display: none; }</style>');
	document.addEventListener("DOMContentLoaded", inittoggle, false);
}

function inittoggle() {
	var as = document.getElementsByClassName('toggle');
	for (var i = 0; i < as.length; i++) {
		var id = as[i].href.match(/#(\w.+)/)[1];
		if (document.getElementById(id).className == "toggleable")
			document.getElementById(id).style.display = "none";
		as[i].onclick = function() {
			toggle(this);
			return false;
		}
	}
}

function toggle(s) {
	var id = s.href.match(/#(\w.+)/)[1];
	style = document.getElementById(id).style;
	if (style.display == "none")
		style.display = "block";
	else
		style.display = "none";
}



