/*
 * KLANDESTINO AJAX HANDLER
 */

function getHash() { /* Get hash without # */
	var hash = window.location.hash;
	if (hash.substr(0, 1) == '#') {
		return(hash.substr(1));
	} else {
		return(hash);
	}
}

runKlajaxLoader = false
prevHash = ' ';
nopCycles = 0;
function klajaxCron() {
	if (runKlajaxLoader) {
		nopCycles = 0;
		if (!klajaxLoaderLock) {
			runKlajaxLoader = false;
			klajaxLoader();
		}
	} else {
		nopCycles++;
		if (nopCycles == 2) {
			convertWaitContainer();
			nopCycles = 0;
		}
	}

	if (window.location.hash != prevHash) {
		nopCycles = 0;
		hashChanged(getHash());
	}
	prevHash = window.location.hash;
	setTimeout(function() { klajaxCron(); }, 300);
}

function convertWaitContainer() {
	var max = 3;
	$('*[data_wait_klajax_container]').each(function() {
		max--;
		if (max > 0) {
			$(this).attr('data_klajax_container', $(this).attr('data_wait_klajax_container'));
			$(this).attr('data_klajax_sort', $(this).attr('data_wait_klajax_sort'));
			$(this).removeAttr('data_wait_klajax_container');
			$(this).removeAttr('data_wait_klajax_sort');
			runKlajaxLoader = 1;
		}
	});
}

function showOrHideDependingOnHash($elem, hash) {
	hashes = $elem.attr('data_klajax_hashes');
	if (typeof(hashes) != 'undefined') {
		if (typeof(hash) == 'undefined') {
			hash = window.location.hash;
		}
		if (hash.substr(0, 1) != '#') {
			hash = '#' + hash;
		}
		hashes = hashes.split(' ');
		show = false;
		for (i = 0; i < hashes.length; i++) {
			if (hashes[i] === hash) {
				show = true
				break;
			}
		}
		if ($elem.parent().attr('data_klajax_limit')) {
			if ($elem.prevAll(':visible').length >= parseInt($elem.parent().attr('data_klajax_limit'))) {
				show = false;
			}
		}
		if (show) {
			$elem.show(400);
		} else {
			if ($elem.css('display') != 'none') {
				$elem.css('display', 'none'); // Detta krävs p.g.a. konstig bugg.
				if ($elem.attr('data_klajax_content')) {
					if (typeof(klajaxOnHashHideHooks[$elem.attr('data_klajax_content')]) != 'undefined') {
						contentName = $elem.attr('data_klajax_content');
						for (var ii in klajaxOnHashHideHooks[contentName]) {
							klajaxOnHashHideHooks[contentName][ii]($elem[0]);
						}
					}
				}
			}
		}
	}
}

function hashChanged(hash) {
	$('*[data_klajax_hashes]').each(function() {
		runKlajaxLoader = true;
		showOrHideDependingOnHash($(this), hash);
	});
	$('a[href]').each(function() {
		if ($(this).attr('href') == '#' + hash) {
			$(this).addClass('currenthash');
		} else {
			$(this).removeClass('currenthash');
		}
	});
	for (i = 0; i < klajaxHashChangeHooks.length; i++) {
		klajaxHashChangeHooks[i](hash);
	}
}

function hashizeLinks($scope) {
	$('a', $scope[0]).each(function() {
		href = $(this).attr('href');
		if (href.substr(0, 1) != '#') {
			if (href.substr(0, 1) == '/') {
					$(this).attr('href', '#' + href.substr(1));
			} else {
				if ((href.substr(0, 7) != 'http://') && (href.substr(0, 7) != 'mailto:')) {
					$(this).attr('href', '#' + href);
				}
			}
		}
	});
}

klajaxLoaderLock = false;
klajaxLoaderFailureTime = 0;
klajaxContainerHas = {};
function klajaxLoader() {
	if (klajaxLoaderLock) {
		runKlajaxLoader = true;
		return;
	}
	klajaxLoaderLock = true;
	data = new Object();
	$('*[data_klajax_container]').each(function() {
		containerinfo = '';
		containername = $(this).attr('data_klajax_container');

		if (klajaxContainerHas[containername]) {
			for (var i = 0; i < klajaxContainerHas[containername].length; i++) {
				containerinfo += '-' + klajaxContainerHas[containername][i] + ',';
			}

			data[containername] = containerinfo;
		} else {
			klajaxContainerHas[containername] = [];
			data[containername] = '';
			$(this).children('*[data_klajax_content="' + containername + '"]').each(function() {
				containerinfo += '-' + $(this).attr('data_klajax_content_id') + ',';
				klajaxContainerHas[containername].push($(this).attr('data_klajax_content_id'));

				data[containername] = containerinfo;
			});
		}
	});
	data['request_timestamp'] = Number(new Date());
	data['location.hash'] = window.location.hash;
	if (data['location.hash'].substr(0, 1) != '#') {
		data['location.hash'] = '#' + data['location.hash'];
	}

	$.ajax({
		type: "POST",
		url: "klajax.php",
		async: true,
		data: data,
		dataType: 'html',
		success: function(data) {
			// klajaxLoaderLock = false; /* Vi flyttar in denna i slutet av parseKlajaxData() istället */
			klajaxLoaderFailureTime = 0;
			parseKlajaxData(data);
		},
		error: function(data) {
			klajaxLoaderLock = false;
			if (klajaxLoaderFailureTime == 0) {
				klajaxLoaderFailureTime = 1000;
			} else {
				if (klajaxLoaderFailureTime < 64000) {
					klajaxLoaderFailureTime = klajaxLoaderFailureTime * 2;
				}
			}
			setTimeout(function() { runKlajaxLoader = true; }, klajaxLoaderFailureTime);
		}
	});
}

function clearKlajaxCache(contentname) {
	if (typeof(klajaxContainerHas[contentname]) != 'undefined') {
		delete klajaxContainerHas[contentname];
	}
	if (typeof(klajaxContainers[contentname]) != 'undefined') {
		delete klajaxContainers[contentname];
	}
}


function addElement($new, relation, old) {
	if ($new.attr('id')) {
		$('*[id="' + $new.attr('id') + '"]').each(function() {
			// Remove any element with the same id-attribute as the new element.
			// Elements in html are not supposed to have identical id.
			removeElement(this);
		});
	}
	if ((relation == 'into') || (relation == 'append')) {
		$(old).append($new);
	} else if (relation == 'prepend') {
		$(old).prepend($new);
	} else if (relation == 'before') {
		$(old).before($new);
		$new = $(old).prev();
	} else if (relation == 'after') {
		$(old).after($new);
		$new = $(old).next();
	}
	showOrHideDependingOnHash($new);

	if ($('*[data_klajax_container]', $new).length != 0) {
		runKlajaxLoader = true;
	}

	// cache:a att denna finns, för framtida ajaxrequests...
	contentname = $new.attr('data_klajax_content');
	if (!klajaxContainerHas[contentname]) {
		klajaxContainerHas[contentname] = [];
	}
	klajaxContainerHas[contentname].push($new.attr('data_klajax_content_id'));

	contentNames = [$new.attr('data_klajax_content'), '*'];
	for (i = 0; i < 2; i++) {
		contentName = contentNames[i];
		if (contentName != '') {
			if (typeof(klajaxPostInsertHooks[contentName]) != 'undefined') {
				for (var ii in klajaxPostInsertHooks[contentName]) {
					klajaxPostInsertHooks[contentName][ii]($new[0]);
				}
			}
		}
	}

}

function removeElement(elem) {
	$(elem).remove();
}

klajaxOnHashHideHooks = new Object();
function addKlajaxOnHashHideHook(contentName, func) {
	if (typeof(klajaxOnHashHideHooks[contentName]) == 'undefined') {
		klajaxOnHashHideHooks[contentName] = new Array();
	}
	klajaxOnHashHideHooks[contentName].push(func);
}
klajaxPostChangesHooks = new Object();
function addKlajaxPostChangesHook(contentName, func) {
	if (typeof(klajaxPostChangesHooks[contentName]) == 'undefined') {
		klajaxPostChangesHooks[contentName] = new Array();
	}
	klajaxPostChangesHooks[contentName].push(func);
}
klajaxPostInsertHooks = new Object();
function addKlajaxPostInsertHook(contentName, func) {
	if (typeof(klajaxPostInsertHooks[contentName]) == 'undefined') {
		klajaxPostInsertHooks[contentName] = new Array();
	}
	klajaxPostInsertHooks[contentName].push(func);
}
klajaxHashChangeHooks = new Array();
function addKlajaxHashChangeHook(func) {
	klajaxHashChangeHooks.push(func);
}

klajaxContainers = {}
function parseKlajaxData(data) {
	changedContents = new Array();
	firstAddToContainer = new Array();
	$(data).children().each(function() {

		if (klajaxContainers[$(this).attr('data_klajax_content')]) {
			$container = klajaxContainers[$(this).attr('data_klajax_content')];
		} else {
			$container = $('*[data_klajax_container="' + $(this).attr('data_klajax_content') + '"]');
			klajaxContainers[$(this).attr('data_klajax_content')] = $container;
		}
		if ($container.length == 1) { // The container is found! (And there should only be one.)
			changedContents.push($(this).attr('data_klajax_content'));
			if ($(this).attr('data_klajax_content_id')) {
				$('*[data_klajax_content_id="' + $(this).attr('data_klajax_content_id') + '"]', $container).each(function() {
					$(this).remove();
				});
			}
			if (typeof($container.attr('data_klajax_sort')) == 'undefined') {
				// There should be no sorting, just append!
				addElement($(this), 'into', $container);
			} else if (typeof(firstAddToContainer[$(this).attr('data_klajax_content')]) != 'undefined') {
				addElement($(this), 'into', $container);
			} else {
				if ($container.children().length == 0) { // First entry, no sorting, just put it there!
					addElement($(this), 'into', $container);
					firstAddToContainer[$(this).attr('data_klajax_content')] = true;
				} else {
					$newelem = $(this);
					sortattr = $container.attr('data_klajax_sort');
					newelemattr = $newelem.attr(sortattr);
					nextelem = false;
					sortorder = $container.attr('data_klajax_sortorder');
					if (typeof(sortorder) == 'undefined') sortorder = 'ascending';
					if (sortorder.toUpperCase() == 'DESC') {
						// Baklängessortering
						$container.children().each(function() {
							if (nextelem == false) {
								if (newelemattr > $(this).attr(sortattr)) {
									addElement($newelem, 'before', this);
									nextelem = true;
								}
							}
						});
						if (nextelem == false) {
							addElement($newelem, 'append', $container);
							nextelem = true;
						}
					} else {
						// Framlängessortering
						$container.children().each(function() {
							if (nextelem == false) {
								if (newelemattr < $(this).attr(sortattr)) {
									addElement($newelem, 'before', this);
									nextelem = true;
								}
							}
						});
						if (nextelem == false) {
							addElement($newelem, 'append', $container);
							nextelem = true;
						}
					}
				}
			}
			hashizeLinks($container);
		}
	});
	changedContents = arrayUnique(changedContents);
	for (var i in changedContents) {
		contentName = changedContents[i];
		if (typeof(klajaxPostChangesHooks[contentName]) != 'undefined') {
			for (var ii in klajaxPostChangesHooks[contentName]) {
				klajaxPostChangesHooks[contentName][ii]();
			}
		}
	}
	klajaxLoaderLock = false;
}

function initKlajax() {
	runKlajaxLoader = true;
	klajaxCron();
}

$(document).ready(function() {
	hashizeLinks($('body'));
	/* initKlajax() */
});

