/**
 * Általános (böngészőfüggetlen) segédfüggvények
 */

// Függőségek
if ("undefined" == typeof AITIA) {
	alert("AITIA include missing!");
}

// Többszörös include
if ("undefined" != typeof AITIA_UTIL) {
	 alert("AITIA_UTIL multiple insert!");
}

AITIA_UTIL = 1;

Aitia.Util = {};

Aitia.Util.lastDropped = {};

Aitia.Util.dragging = false;

Aitia.Util.treeDrags = new Array();

Aitia.Util.treeDrops = new Array();

Aitia.Util.treePerms = {};

Aitia.Util.timers = {};

/**
 * Decimális számot hexadecimálisra alakít
 */
Aitia.Util.dec2Hex = function(num) {
	var chars = '0123456789ABCDEF';
	if (num > 255) return 'FF';
	return chars.charAt(parseInt(num/16))+chars.charAt(num%16);
} // dec2Hex


/**
 * Balról kiegészíti a számot 0-al
 * @todo: általánosabbra alakítható
 */
Aitia.Util.digit2 = function(num) {
	if (num < 10) {
		return "0"+num;
	}
	return num;
} // digit2


/**
 * Rendezés - Lehetne parametertől függő rendezés is (factory)
 *  cmpFunc(a,b): -1 a < b, 0 a = b, 1 a > b
 */
Aitia.Util.sort = function(arr,cmpFunc) {
	this.quicksort(arr, 0, arr.length - 1, cmpFunc);
} // sort


/**
 * Rendezés - quicksort implementáció
 */
Aitia.Util.quicksort = function(arr,a,b,cmpFunc) {
	var left, right;
	var ref, w;
	var i;

	left = a; right = b;

	ref = arr[parseInt((a+b)/2)];

	while(left <= right) { // csökkenő sorrendben
		// Van komperáló függvény
		if (cmpFunc) {
			while (cmpFunc(arr[left],ref) == 1) { ++left; } // arr[left] > ref
			while (cmpFunc(arr[right],ref) == -1) { --right; } // arr[right] < ref
		}
		// Nincs
		else {
			while (arr[left] > ref) { ++left; }
			while (arr[right] < ref) { --right; }
		}
	
		if (left <= right) { // elemek cseréje
			if (left != right) { //ha egyenlő, akkor nem cserél
				w = arr[left];
				arr[left] = arr[right];
				arr[right] = w;
			}
			++left;
			--right;
		}
	}
	if (a < right) {
		this.quicksort(arr, a, right, cmpFunc);
	}
	if (left < b) {
		this.quicksort(arr, left, b, cmpFunc);
	}
} // quicksort


/**
 * Selection megszüntetése
 */
Aitia.Util.removeSelection = function() {
	if (document.selection) {
		try {
			document.selection.empty();
		} catch(e) {}
	} else if (window.getSelection) {
		window.getSelection().removeAllRanges();
	} else {
		try {
			document.createElement("input").focus();
		} catch(e) {}
	}
} // removeSelection


Aitia.Util.timer = function(fn, id, time) {
	if(this.timers[id]) {
		clearTimeout(this.timers[id]);
		this.timers[id] = null;
	}
	this.timers[id] = setTimeout(fn, time);
}



function arab2rom(number) {
	ones     = new Array('', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX');
	decades  = new Array('', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC');
	hundreds = new Array('', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM');
	tousands = new Array('', 'M', 'MM', 'MMM');
	all = new Array(ones, decades, hundreds, tousands);
	if (number > 3999) {
		//alert('The number is greater than 3999!');
		return '<ERROR>';
	}
	if (number < 1) {
		//alert('The number is not positive!');
		return '<ERROR>';
	}

	numstr = number.toString();
	len = numstr.length;
	romanstr = '';
	// generation
	for (i = 0; i < len; i++) {
		romanstr += all[len - i - 1][numstr.charAt(i)];
	}

	return romanstr;
}


function rom2arab(romanstr) {
	invalid_number_err = 'The string is not a valid roman numeral!';
	//err = 'ERR';
	err = null;

	// maximal characters for a class, e.g. DCCC, XXXV, VIII
	// tousands, hundreds, decades, ones
	max = new Array(3, 4, 4, 4);
	// can a class contain more characters or there must follow
	// next class, i.e. after XC can follow only ones (V, I)
	can_more = new Array(true, true, true, true);
	simple = new Array(false, false, false, false);
	// class chars counter: tousands, hundreds, decades, ones
	counter = new Array(0, 0, 0, 0);

	romanstr = romanstr.toUpperCase();
	len = romanstr.length;
	arab = 0;
	for (i = 0; i < len; i++) {
		switch (romanstr.charAt(i)) {
		case 'M':
			if ( ++counter[0] > max[0] || !can_more[0] ) {
				//alert(invalid_number_err);
				return err;
			}
			arab += 1000;
			break;
		case 'D':
			can_more[0] = false;
			if ( ++counter[1] > max[1] || !can_more[1] || simple[1] ) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M':
				//alert(invalid_number_err);
				return err;
			default:
				arab += 500;
				simple[1] = true;
			}
			break;
		case 'C':
			can_more[0] = false;
			if ( ++counter[1] > max[1] || !can_more[1] || simple[2] ) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M':
				arab += 900;
				i++;
				can_more[1] = false;
				break;
			case 'D':
				arab += 400;
				i++;
				can_more[1] = false;
				break;
			default:
				arab += 100;
				simple[1] = true;
			}
			break;
		case 'L':
			current = 2;
			if ( ++counter[2] > max[2] || !can_more[2] || simple[2]) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M': case 'D': case 'C':
				//alert(invalid_number_err);
				return err;
			default:
				arab += 50;
				simple[2] = true;
			}
			break;
		case 'X':
			current = 2;
			if ( ++counter[2] > max[2] || !can_more[2] || simple[3] ) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M': case 'D':
				//alert(invalid_number_err);
				return err;
			case 'C':
				arab += 90;
				i++;
				can_more[2] = false;
				break;
			case 'L':
				arab += 40;
				i++;
				can_more[2] = false;
				break;
			default:
				arab += 10;
				simple[2] = true;
			}
			break;
		case 'V':
			current = 3;
			if ( ++counter[3] > max[3] || !can_more[3] || simple[3]) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M': case 'D': case 'C': case 'L': case 'X':
				//alert(invalid_number_err);
				return err;
			default:
				arab += 5;
				simple[3] = true;
			}
			break;
		case 'I':
			current = 3;
			if ( ++counter[3] > max[3] || !can_more[3] ) {
				//alert(invalid_number_err);
				return err;
			}
			switch (romanstr.charAt(i+1)) {
			case 'M': case 'D': case 'C': case 'L':
				//alert(invalid_number_err);
				return err;
			case 'X':
				arab += 9;
				i++;
				can_more[3] = false;
				break;
			case 'V':
				arab += 4;
				i++;
				can_more[3] = false;
				break;
			default:
				arab += 1;
				simple[3] = true;
			}
			break;
		default:
			//alert(invalid_number_err);
			return err;
		} // end switch (romanstr.charAt(i))
	} // end for (i = 0; i < len; i++)
	return arab;
}