var dialog_enableDebug = true;

/*
		"Oikeaoppinen" dialogin käyttö:

		js-koodissa kutsutaan dialog_load(requestParams, dialogParams):
			- requestParams on objekti, joka sisältää requestiin menevät datat
			- dialogParams on objekti, jossa on dialogin parameterja (ei pakollinen, name olisi kuitenkin hyvä antaa aina, jotta samaa dialogia ei saa auki useampaan kertaan)

		Alla pari esimerkkiä:

		# ladataan vain dialogi ilman callback-funktiota
		dialog_load({'action':'timo', 'timo-action':'testDialog', 'timo-testParameter':'Hello world'}, {'name':'testDialog'});

		# ladataan dialogi ja kun se on latautunut kutsutaan callback funktiota
		# callback -funktio saa parametrinä dialog-objectin (josta lisää alempana)
		dialog_load({'action':'timo', 'timo-action':'testDialog', 'timo-testParameter':'Hello world'}, {'callback':timo_testDialog_loaded}, {'name':'testDialog'});

		Koodataan dialogin tulostava actioni johonkin. (esimerkin tapauksessa tiedostoon timo.php)
		Defaulttina dialog_load odottaa actionilta JSON-vastausta, eli alla esimerkki:

		---

		function timo_input($params) {
			setLayout('clean');
			return array();
		}

		function timo_output_clean($params, $input) {
			switch($params['action']) {
				case 'testDialog':
					$ret = array();

					$ret['html'] = array('dialog'=>array());
					$dlgContent = $params['testParameter'];
					# dialog_compose() -funktiolle voi antaa erilaisia parametreja, lisää infoa modules/system/php/dialog.php
					$dlg = array('title'=>'testDialog', 'content'=>$dlgContent, 'width'=>'320px', 'padding'=>'10px', 'closeButton'=>true);
					$ret['html']['dialog']['code'] = base64_encode(dialog_compose($dlg));
					$ret['html']['dialog']['base64'] = true;

					print json_encode($ret);
				break;
			}
		}

		---

		dialogin callback-funktio saa parametrinä dialog-objectin,
		joka sisältää monia juttua, tärkeimpänä dialog.request (ja itseasiassa callback-funktion this osoittaa samaan dialog-objektiin)
		dialog.request on wertin oma xmlhttp-request jossa on requestin kaipaamia tietoja sekä tärkeimpänä dialog.request.response -objekti.
		dialog.request.response sisältää kaiken mitä palvelinpäässä oleva php on JSON-muodossa palauttanut

*/

var dialog_list = [];

/**
 *	lataa dialogin, ja avaa sen.
 *
 *	@param mixed joko suoraan url joka halutaan ladata, tai sitten vaan object missä on dialogin parametrit, esimerkki:
 *	{
 *		"action": "structure-lock",
 *		"structure-id": "20"
 *	}
 *
 *	@param params {
 *		name: dialogin nimi (jos samalla nimellä on jo dialogi auki, ei ladata uutta)
 *		callback: funktio jota kutsutaan kun dialogi on valmis,
 *		focusId:	elementti johon laitetaan focus kun dialogi on ladattu
 *		cleanUpFunc: funktio jota kutsutaan kun dialogi sulkeutuu
 *	}
 *
 *
 */
function dialog_load(mixed, params) {
	debugPrint("dialog_load: param="+typeof mixed, "dialog");
	var url = "index.php";
	var data = {};

	if(params && params.name) {
		if(dialog_isOpen(params.name)) {
			debugPrint("dialog_load: nimellä "+params.name+" on jo dialogi auki", "dialog");
			return null;
		}
	}

	var newDialog = {"json": false, "callback": null, 'cleanUpFunc': null};

	if(typeof mixed == "string") {
		var slicePos = mixed.indexOf('?');
		var postData = mixed.substr(slicePos+1);
		url = mixed.substr(0,slicePos);
		var temp = postData.split("&");
		for(var i=0; i < temp.length; i++) {
			var key_value = temp[i].split("=");
			data[key_value[0]] = key_value[1];
		}
	} else if(typeof mixed == "object") {
		data = mixed;
		newDialog.json = true;
	}

	for(var i in params) newDialog[i] = params[i];

	newDialog.center = common_createBoundedWrapper(newDialog, dialog_center);
	newDialog.resizeToContent = common_createBoundedWrapper(newDialog, dialog_resizeToContent);
	newDialog.getSize = common_createBoundedWrapper(newDialog, dialog_getSize);
	newDialog.getClientSize = common_createBoundedWrapper(newDialog, dialog_getClientSize);
	newDialog.close = common_createBoundedWrapper(newDialog, dialog_destroy);
	newDialog.reload = common_createBoundedWrapper(newDialog, dialog_reload);
//	newDialog.cleanUpFunc = null;

	newDialog.request = xmlhttp_request(url, data, "post", common_createBoundedWrapper(newDialog, dialog_loaded), newDialog.json);
	newDialog.request.send();

	// dialogin container pitää luoda ennen kuin lisätään dialogi dialog_listiin, jotta dialog_gc ei siivoa tätä dialogia pois ennen kuin se on latautunut
	newDialog.container = document.createElement("div");
	css_addClass(newDialog.container, 'dialogContainer');
	newDialog.container.style.display = "none";
	document.body.appendChild(newDialog.container);

	dialog_list.push(newDialog);	// dialogit siivotaan automaattisesti pois niiden sulkeuduttua

//	return newDialog;
}

function dialog_reload(mixed, params) {
	debugPrint("dialog_reload: param="+typeof mixed, "dialog");
	var url = "index.php";
	var data = {};

	if(typeof mixed == "string") {
		var slicePos = mixed.indexOf('?');
		var postData = mixed.substr(slicePos+1);
		url = mixed.substr(0,slicePos);
		var temp = postData.split("&");
		for(var i=0; i < temp.length; i++) {
			var key_value = temp[i].split("=");
			data[key_value[0]] = key_value[1];
		}
	} else if(typeof mixed == "object") {
		data = mixed;
	}

	for(var i in params) {
		this[i] = params[i];
	}
	this.request = xmlhttp_request(url, data, "post", common_createBoundedWrapper(this, dialog_loaded), this.json);
	this.request.send();
}

// tarkistaa onko nimetty dialogi auki, ja jos on palauttaa sen dialogi-objektin, muuten null
function dialog_isOpen(name) {
	for(var i = 0; i < dialog_list.length; i++) {
		if(dialog_list[i].container && dialog_list[i].name && dialog_list[i].name == name) {
			return dialog_list[i];
		}
	}
	return null;
}

// sulkee nimetyn dialogin jos se on auki
function dialog_closeByName(name) {
	debugPrint("dialog_closeByName "+name, "dialog");
	var dlg = dialog_isOpen(name);
	if(dlg) dlg.close();
}

// kuinka monta dialogia on auki tällä hetkellä
function dialog_openCount() {
	debugPrint("dialog_openCount()", "dialog");
	var cnt = 0;
	for(var i = 0; i < dialog_list.length; i++) {
		if(dialog_list[i].container) cnt++;
	}
	return cnt;
}

function dialog_loaded(request) {
//	showTextInAWindow(this.request.xmlhttprequest.responseText);
	var dialogHTML = "";
	if(this.request.requireJSON) {
		if(request && request.response && request.response.html && request.response.html.dialog && request.response.html.dialog.code) {
			dialogHTML = request.response.html.dialog.code;
		} else {
			debugPrint("Dialog loaded with requireJSON, but cannot find html.dialog.code in JSON-response");
		}
	} else {
		// parsitaan dialogin koodi responsesta (old school)
		var regString = '<!-- <dialog> -->([^\000]*?)<!-- </dialog> -->';
		var rx = new RegExp(regString, "mig");
		var match = rx.exec(this.request.responseText);
		if(match) {
			debugPrint("dialog_loaded: found dialog innerHTML", "dialog");
			dialogHTML = match[0];
		} else {
			if(confirm("dialog_loaded: can't find dialog-content. do you want to see responseText?")) {
				showTextInAWindow(this.request.responseText);
			}
		}
	}

	if(dialogHTML) {
		if(this.debug) showTextInAWindow(dialogHTML);
		this.container.innerHTML = dialogHTML;
		var frameTable = null;
		if(this.container.hasChildNodes()) for(var i = 0; i < this.container.childNodes.length; i++) {
			if(this.container.childNodes[i].tagName == "TABLE") {
				frameTable =  this.container.childNodes[i];
				break;
			}
		}
		if(frameTable) {
			var pos = null;
			if(this.draggable && this.draggable.position) pos = this.draggable.position;
			this.draggable = frame_setDraggableMode(frameTable, this);
			this.container.style.display = "";
			this.draggable.setPosition(pos);
			if(!this.noFocus) {
				if(this.focusId) {
					debugPrint("this.focusId = "+this.focusId, "dialog");
					var el = dialog_searchChildWithId(this.container, this.focusId);
					if(el) {
						try {
							el.focus();
							el.select();
						} catch(e) {
							// nop
						}
					}
				} else {
					var inputs = this.container.getElementsByTagName("input");
					debugPrint("inputs.length=" + inputs.length, "dialog");
					if(inputs.length) for(var i = 0; i < inputs.length; i++) {
						var inputId = inputs[i].getAttribute("id");
						if(!inputs[i].disabled && (inputs[i].type == "text" || inputs[i].type == "textarea")) {
							try {
								inputs[i].focus();
								inputs[i].select();
							} catch(e) {
								// nop
							}
							break;
						}
					}
				}
			}
			if(this.callback) this.callback(this);
		} else {
			debugPrint("Can't find frameTable in dialog content");
			alert(dialogHTML);
		}
	}
	this.container.style.display = "";
}

// tehdään elementistä element ja sen sisällä olevasta framesta dialogi (ja piilotetaan elementti)
function dialog_elementToDialog(element, params) {
	debugPrint("dialog_elementToDialog() "+element, "dialog");
	var newDialog = {"json": false, "callback": null, 'cleanUpFunc': null};
	for(var i in params) newDialog[i] = params[i];
	newDialog.center = common_createBoundedWrapper(newDialog, dialog_center);
	newDialog.resizeToContent = common_createBoundedWrapper(newDialog, dialog_resizeToContent);
	newDialog.getSize = common_createBoundedWrapper(newDialog, dialog_getSize);
	newDialog.getClientSize = common_createBoundedWrapper(newDialog, dialog_getClientSize);
	newDialog.open = common_createBoundedWrapper(newDialog, dialog_show);
	newDialog.close = common_createBoundedWrapper(newDialog, dialog_hide);
	newDialog.isHidden = common_createBoundedWrapper(newDialog, dialog_isHidden);
//	newDialog.cleanUpFunc = null;

	if(element.parentNode && element.parentNode.tagName && element.parentNode.tagName.toLowerCase() != 'body') {
	// Jos elementtti ei ole bodyn child, irroitetaan elementti dokumentista ja siirretään se bodyn childiksi,
	// koska se saattaa olla jossain semmoisessa paikassa että absolute-position ei olekaan relatiivinen dokumentin yläkulmaan.
		var relocate = element.parentNode.removeChild(element);
		element = document.body.insertBefore(relocate, null);	// bodyn viimeiseksi childiksi
		debugPrint("relocated to body "+element.parentNode, "dialog");
	}
	newDialog.container = element;
	css_addClass(newDialog.container, 'dialogContainer');
	var frameTable = newDialog.container.childNodes[0];
	if(frameTable) {
		newDialog.draggable = frame_setDraggableMode(frameTable, newDialog);
		newDialog.draggable.setPosition(null);	// center
		if(newDialog.callback) newDialog.callback(newDialog);
	}
	dialog_list.push(newDialog);
	return newDialog;
}

function dialog_center() {
	debugPrint("dialog_center this="+this+" this.draggable="+this.draggable, "dialog");
	if(this.draggable) this.draggable.setPosition(null);
}

function dialog_resizeToContent() {
	debugPrint("dialog_resizeToContent "+this, "dialog");
	if(this.draggable) {
		var size = this.draggable.resizeToContent();
//		showProps(size);
		return size;
	}
}

function dialog_getSize() {
	debugPrint("dialog_getSize "+this, "dialog");
	return this.draggable.getSize();
}

function dialog_getClientSize() {
	debugPrint("dialog_getClientSize "+this, "dialog");
	return this.draggable.getClientSize();
}

function dialog_show(disableCentering) {
	debugPrint("dialog_show() "+this, "dialog");
	this.draggable.element.style.display = "";
	if(!disableCentering) this.center();	// center
//	this.draggable.setPosition(null);	// center
}

function dialog_isHidden() {
	debugPrint("dialog_isHidden() "+this, "dialog");
	if(this.draggable.element.style.display == 'none') {
		return true;
	} else {
		return false;
	}
}

// dialog_hide tekee periaatteessa saman kuin dialog_destroy, paitsi että dialog_hide ei poista dialogin container-elementtiä documentista
// (eli käytetään closen tilalla, jos dialogi on tehty olemassaolevasta elementistä, ja sitä ei haluta tuhota)
function dialog_hide() {
	debugPrint("dialog_hide() "+this, "dialog");
	var closedDialogName = '';
	if(this.name) closedDialogName = this.name;
	if(this.cleanUpFunc) this.cleanUpFunc();
	this.draggable.destroy();
	this.draggable.element.style.display = "none";
	this.container = null;
	this.draggable = null;
	window.setTimeout(dialog_gc, 1000);
	return closedDialogName;
}

function dialog_destroy() {
	debugPrint("dialog_destroy() "+this, "dialog");
	var closedDialogName = '';
	if(this.name) closedDialogName = this.name;
	if(this.cleanUpFunc) this.cleanUpFunc();
	this.draggable.destroy();
	this.draggable = null;
	this.container.innerHTML = "";
	document.body.removeChild(this.container);
	this.container = null;
	window.setTimeout(dialog_gc, 1000);
	return closedDialogName;
}

// sulkee sen dialogin missä se elementti on joka kutsui tätä funktiota :D
function dialog_close(e) {
	if(!e) e = window.event;
	debugPrint("dialog_close() ", "dialog");
	var el = e.srcElement ? e.srcElement : e.target;
	if(el) return dialog_closeParent(el);
	return null;
}

// sulkee sen dialogin missä elementti el on
function dialog_closeParent(el) {
	debugPrint("dialog_closeParent("+el+") ", "dialog");
/*
	for(var i=0; i < dialog_list.length; i++) {
		var trace = el;
		while(trace && trace != dialog_list[i].container) {
			debugPrint("search: "+trace+" != "+dialog_list[i].container, "dialog");
			trace = trace.parentNode;
		}
	}
	return;
*/
	var closedDialogName = null;
	var failSafe = 256;
	while(failSafe-- && el) {
//		var rapsa = "el="+el;
//		if(el.id) rapsa += " id="+id;
//		rapsa += " dialog_list.length="+dialog_list.length;
//		debugPrint(rapsa, "dialog");
		for(var i=0; i < dialog_list.length; i++) {
			if(dialog_list[i].container == el) {
				closedDialogName = '';
				if(dialog_list[i].name) closedDialogName = dialog_list[i].name;
				dialog_list[i].close();
				failSafe = 0;
				break;
			}
		}
		el = el.parentNode;
	}
//	debugPrint("failSafe="+failSafe+" closedDialogName="+closedDialogName, "dialog");
	return closedDialogName;
}

// palauttaa sen dialogin jonka sisällä elementti el on, tai null jos elementti ei ole dialogin sisällä
function dialog_getContainingDialog(el) {
	var ret = null;
	var failSafe = 256;
	dance:
	while(failSafe-- && el) {
		for(var i=0; i < dialog_list.length; i++) {
			if(dialog_list[i].container == el) {
				ret = dialog_list[i];
				break dance;
			}
		}
		el = el.parentNode;
	}
	return ret;
}

function dialog_searchChildWithId(el, id) {
	var ret = null;
	if(el.hasChildNodes()) {
		for(var i=0; i<el.childNodes.length; i++) {
			if(el.childNodes[i].id == id) {
				return el.childNodes[i];
			}
			if(ret = dialog_searchChildWithId(el.childNodes[i], id)) {
				break;
			}
		}
	}
	return ret;
}

function dialog_userButtonClick(event) {
	if(!event) event = window.event;
	var ret = false;
	var btn = event.srcElement ? event.srcElement : event.target;
	var dialog = dialog_getContainingDialog(btn);
	debugPrint("dialog_userButtonClick() btn="+btn+" dialog="+dialog, "dialog");
	var userFuncName = btn.getAttribute('user_func');
	if(userFuncName) {
		var userFuncParams = btn.getAttribute('user_params');
		var userFunc = common_createBoundedWrapper(dialog, window[userFuncName]);
		var userFuncCall = "var ret = userFunc(event";
		if(userFuncParams) userFuncCall += ", "+userFuncParams;
		userFuncCall += ");";
		eval(userFuncCall);
	}
	return ret;
}

/*	hakee määrämuotoisia parametreja dialogista
		palauttaa siis dialogin sisällä olevien input, textarea ja select -elementeistä arvot, jos niiden name-attribuuttina on dialogProp
		palautuva array on hash-array, jossa key on aina elementin ID, ja arvo on mitä on
*/
function dialog_getProps(root) {
	var props = new Array();
	if(!root) {
		alert("No root for dialog_getProps");
		return;
	}

	var i;
	var temp;
	var elements = [];

	temp = root.getElementsByTagName("INPUT");
	for(i = 0; i < temp.length; i++) if(temp[i].getAttribute('name') == 'dialogProp') elements.push(temp[i]);
	temp = root.getElementsByTagName("TEXTAREA");
	for(i = 0; i < temp.length; i++) if(temp[i].getAttribute('name') == 'dialogProp') elements.push(temp[i]);
	temp = root.getElementsByTagName("SELECT");
	for(i = 0; i < temp.length; i++) if(temp[i].getAttribute('name') == 'dialogProp') elements.push(temp[i]);

	debugPrint('root='+root+' elements.length='+elements.length, 'dialog');

	if(!elements.length) return props;

	var numTest = /[^0-9]/;

	for(i=0; i<elements.length; i++) {
		var el = elements[i];
		var tagName = el.tagName.toLowerCase();
		var propName = el.getAttribute('id');

		if(tagName == "input") {
			var type = el.getAttribute('type');
			if(type == "checkbox") {
				if(el.value == 'yes' || el.value == 'no') {
					if(el.checked) {
						props[propName] = 'yes';
					} else {
						props[propName] = 'no';
					}
				} else {
					props[propName] = el.checked;
				}
			} else {
				if(el.value!="") {
					props[ propName ] = el.value;
					if(! numTest.test(props[propName])) props[propName] = Math.abs(props[propName]);
				} else {
					props[ propName ] = "";
				}
			}
		}
		if(tagName == "textarea") {
			props[propName] = el.value;
			debugPrint("textarea.value="+el.value,"dialog");
//			props[propName] = props[ propName ].replace(/\n/gi,'\\n');
		}
		if(tagName == "select") {
			if(el.options[el.selectedIndex].value) {
				props[ propName ] = el.options[el.selectedIndex].value;
				if(! numTest.test(props[propName])) props[propName] = Math.abs(props[propName]);
			} else {
				props[ propName ] = "";
			}
		}
	}

	return props;
}


// siivoaa suljettuja dialogeja muistista (ehkä)
function dialog_gc() {
	var beginLenght = dialog_list.length;
	var newList = [];
	for(var i=0; i < dialog_list.length; i++) {
		if(dialog_list[i].container == null) {
			dialog_list[i] = null;
		} else {
			newList.push(dialog_list[i]);
		}
	}
	dialog_list = newList;
	debugPrint("dialog_gc() list cleaned from "+beginLenght+" elements to "+dialog_list.length+" elements", "dialog");
}

