/* main page

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // create a script DOM node
    script.src = url;  // set its src to the provided URL
   
    document.head.appendChild(script);  // add it to the end of the head section of the page (could change 'head' to 'body' to add it to the end of the body section instead)

 */

// Groessenangaben in DialogBaseUnits (1unit = 2px)
var metrics = { 
	title: "Form",
	unitWidth: 2,
	headerSpace: 12, 
	toolSpace: 21, 
	toolSpaceDefault: 21, 
	gridVisible: 1, 
	minGridHeight: 80,
	tabHeight: 12, 
	tabItemWidth: 60,
	subFormNames: "",
	subFormVisible: 1, 
	subFormHeight: 122,
	minSubFormHeight: 122, 
	gridControl_toolSpaceWidth: 12,
	editControl_enabled: "#FCFCFC",
	editControl_disable: "#CCCCCC"
};
var spaceAreas = { };

var mousePos = {  
	x: 0, 
	y: 0,
	capture: function(e) { mousePos.x = e.pageX; mousePos.y = e.pageY; }
};
document.addEventListener('mousemove', function(event) { mousePos.capture(event); }, false);
document.addEventListener('mouseenter', function(event) { mousePos.capture(event); }, false);

function raiseControlEvent(msgObject)
{
	return notifyHost(msgObject);
}

function handleUnknownMessage(event)
{
	var txt = "\r\nfrom: " + event.origin.toString() + " (" + event.source.toString() + ")"
			+ "\r\ndata: " + event.data.toString();
	alert("unhandledMessage:\r\n\r\n" + txt);
}

function updateFormLayout(jsonParameters)
{
	var updateTabs = false;
	var updateTitle = false;
	
	// 1. parse parameters
	if (jsonParameters)
	{
		var P = JSON.parse(jsonParameters);
		
		if (typeof P.toolSpace != 'undefined')
			metrics.toolSpace = parseIntEx(P.toolSpace);
		if (metrics.toolSpace == -1)
			metrics.toolSpace = metrics.toolSpaceDefault;

		if (typeof P.subFormHeight != 'undefined')
			metrics.subFormHeight = parseIntEx(P.subFormHeight);

		if (typeof P.tabHeight != 'undefined')
			metrics.tabHeight = parseIntEx(P.tabHeight);

		if (typeof P.gridVisible != 'undefined')
			metrics.gridVisible = parseIntEx(P.gridVisible);

		if (typeof P.subFormVisible != 'undefined')
			metrics.subFormVisible = parseIntEx(P.subFormVisible);
		
		if ((typeof P.subFormNames != 'undefined') && (metrics.subFormNames != P.subFormNames)) 
		{
			metrics.subFormNames = P.subFormNames;
			updateTabs = true;
		}

		if (typeof P.title != 'undefined')
		{
			metrics.title = P.title;
			updateTitle = true;
		}
	}

	// 2. create controls if not exist
	if (! spaceAreas.space4header)
	{
		spaceAreas.space4header = createControl(JSON.stringify(
			{ parentId: "bodyContent", typeName: "space4header", id: "bodySpace4header" }));
		spaceAreas.space4header.onAfterResize = function(elem) { resizeChilds(elem); };
	}
	if (! spaceAreas.space4toolBar)
	{
		spaceAreas.space4toolBar = createControl(JSON.stringify(
			{ parentId: "bodyContent", typeName: "space4toolBar", id: "bodySpace4toolBar" }));
		spaceAreas.space4toolBar.onAfterResize = function(elem) { resizeChilds(elem); };
	}
	if (! spaceAreas.space4grid)
	{
		spaceAreas.space4grid = createControl(JSON.stringify(
			{ parentId: "bodyContent", typeName: "space4grid", id: "bodySpace4grid" }));
		spaceAreas.space4grid.onAfterResize = function(elem) { resizeChilds(elem); };
	}
	if (! spaceAreas.space4tabs)
	{
		spaceAreas.space4tabs = createControl(JSON.stringify(
			{ parentId: "bodyContent", typeName: "space4tabs", id: "bodySpace4tabs" }));
		spaceAreas.space4tabs.onAfterResize = function(elem) { tabControl_onResize(elem); };
	}
	if (! spaceAreas.space4subForm)
	{
		spaceAreas.space4subForm = createControl(JSON.stringify(
			{ parentId: "bodyContent", typeName: "space4subForm", id: "bodySpace4subForm" }));
		spaceAreas.space4subForm.onAfterResize = function(elem) { resizeChilds(elem); };
	}
	
	// 3. tabs
	if (updateTabs)
	{
		tabControl_update(spaceAreas.space4tabs);
	}

	// 4. title
	if (updateTitle)
	{
		updateHeader();
	}

	// 5. resize all
	resizeBodyContent();
}

function updateHeader()
{
	var hdrText = document.getElementById("space4header_text");
	if (! hdrText)
	{
		hdrText = createControl(JSON.stringify(
			{ parentId: "bodySpace4header", typeName: "space4header_text", id: "space4header_text", 
			  position: { x: 2, y: 1, cx: -16, cy: -1 }}));
	}
	hdrText.innerText = metrics.title;

	var hdrClose = document.getElementById("space4header_close");
	if (! hdrClose)
	{
		hdrClose = createControl(JSON.stringify(
			{ parentId: "bodySpace4header", typeName: "space4header_close", id: "space4header_close", 
			  position: { x: -18, y: 1, cx: 14, cy: -1 }}));
   	    hdrClose.onclick = function() { notifyHost({ msg: "closeRequested" }); }
	}
	hdrClose.innerHTML = "&times;";
}

function resizeAll()
{
	resizeBodyContent();
	resizeModalContent();
}

function resizeBodyContent()
{
	//var cxBody = parseInt(document.body.offsetWidth);
	//var cyBody = parseInt(document.body.offsetHeight);
	var cxBody = window.innerWidth;
	var cyBody = window.innerHeight;
	var bodyContent = document.getElementById("bodyContent");

	var gridVisible    = metrics.gridVisible;
	var subFormVisible = metrics.subFormVisible;

	var unitWidth = metrics.unitWidth;
	var cyHeader  = metrics.headerSpace * unitWidth;
	var cyToolBar = metrics.toolSpace * unitWidth;
	var cyTabs    = subFormVisible ? metrics.tabHeight * unitWidth : 0;
	var cySubForm = subFormVisible ? metrics.subFormHeight * unitWidth : 0;
	var cyGrid    = gridVisible ? cyBody - (cyHeader + cyToolBar + cySubForm + cyTabs) : 0;

	// calculate best usage of space
	
	if (metrics.gridVisible)
	{
		// hide subForm if grid is to small
		if (cyGrid < (metrics.minGridHeight * unitWidth))
			subFormVisible = false;
		if (!subFormVisible)
			cyGrid = cyBody - (cyHeader + cyToolBar);
	}		
	else if (metrics.subFormVisible)
	{
		cySubForm = cyBody - (cyHeader + cyToolBar + cyTabs);
	}
	else
	{
		cyToolBar = cyBody - cyHeader;
	}

	// update positions and visiblility
	var yHeader = 0;
	if (cyHeader > 0)
	{
		spaceAreas.space4header.requiredPosition = { x: 0, y: yHeader, cx: 0, cy: cyHeader };
		spaceAreas.space4header.style.display = "initial";
	}
	else
	{
		spaceAreas.space4header.style.display = "none";
	}

	var yToolBar = yHeader + cyHeader;
	if (cyToolBar > 0)
	{
		spaceAreas.space4toolBar.requiredPosition = { x: 0, y: yToolBar, cx: 0, cy: cyToolBar };
		spaceAreas.space4toolBar.style.display = "initial";
	}
	else
	{
		spaceAreas.space4toolBar.style.display = "none";
	}

	var yGrid    = yToolBar + cyToolBar;
	if (gridVisible)
	{ 
		spaceAreas.space4grid.requiredPosition = { x: 0, y: yGrid, cx: 0, cy: cyGrid };
		spaceAreas.space4grid.style.display = "initial";
	}
	else
	{
		spaceAreas.space4grid.style.display = "none";
	}

	var yTabs    = yGrid + cyGrid;
	if (subFormVisible)
	{
		spaceAreas.space4tabs.requiredPosition = { x: 0, y: yTabs, cx: 0, cy: cyTabs };
		spaceAreas.space4tabs.style.display = "initial";
	}
	else
	{
		spaceAreas.space4tabs.style.display = "none";
	}

	var ySubForm = yTabs + cyTabs;
	if (subFormVisible)
	{
		spaceAreas.space4subForm.requiredPosition = { x: 0, y: ySubForm, cx: 0, cy: cySubForm };
		spaceAreas.space4subForm.style.display = "initial";
	}
	else
	{
		spaceAreas.space4subForm.style.display = "none";
	}
	
	resizeChilds(bodyContent);
}

function resizeModalContent()
{
	resizeChilds(document.getElementById("modalContent"));
}

function createControl(jsonParameters)
{
	var P = parseParameters(jsonParameters);
	// alert(JSON.stringify(P));

	// get parent
	var parentId = P.parentId;
	var parent = document.getElementById(parentId);
	if (parent == null)
	{
		alert("Das Control " + parentId + " existiert nicht.");
		return null;
	}

	// create a blank div
	var fullControlId = parentId.indexOf("body") == 0 ? P.id : parentId + "_" + P.id;
	var control = document.getElementById(fullControlId);
	if (control)
	{
		alert("Das Control " + fullControlId + " existiert bereits.");
		return null;
	}

	control = xmlCreateElement(parent, getElementTypeByClassName(P.typeName));
	control.setAttribute("class", P.typeName);
	control.setAttribute("id", fullControlId);
	if (typeof P.position != 'undefined')
	{
		var unitWidth = metrics.unitWidth;
		control.requiredPosition = 
		{
			x: parseIntEx(P.position.x) * unitWidth,
			y: parseIntEx(P.position.y) * unitWidth,
			cx: parseIntEx(P.position.cx) * unitWidth,
			cy: parseIntEx(P.position.cy) * unitWidth
		};
		//alert(control.id);
		resizeControl(control, parent);
	}
	return control;
}

function removeControl(jsonParameters)
{
	var P = parseParameters(jsonParameters);
	// alert(JSON.stringify(P));
	var c = getControl(P.fullControlName);
	if (c) c.remove();
}

function getElementTypeByClassName(c)
{
	switch(c)
	{
	case "pushButton":
		return "input";
	case "iconButton":
		return "img";
	case "comboBox":
		return "select";
	case "webView":
		return "iframe";
	//default:
	//	alert(c);
	}
	return "div";
}

function resizeControl(control, parent)
{
	if (!parent) parent = control.parentElement;
	var cxParent = parent.offsetWidth;
	var cyParent = parent.offsetHeight;

	var pos = control.requiredPosition;
	// alert(JSON.stringify(pos));

    var xp = parseInt(pos.x);
    var cxp = parseInt(pos.cx);
	var x = xp < 0 ? cxParent + xp : xp;
	var cx = cxp <= 0 ? cxParent + cxp - x : cxp;
	// alert("X: " + x.toString() + "/" + cx.toString());

    var yp = parseInt(pos.y);
    var cyp = parseInt(pos.cy);
	var y = yp < 0 ? cyParent + yp : yp;
	var cy = cyp <= 0 ? cyParent + cyp - y : cyp;
	//alert(control.id + "Y: " + pos.y.toString() + "/" + y.toString() + "-" + pos.cy.toString() + "/" + cy.toString());

	//if (parent.id == "Toolbar")
	//{
	//	alert("Toolbar." + control.id + " " + x.toString() + "/" + y.toString() + "-" + cx.toString() + "/" + cxParent.toString());
	//}

	control.style.position = "absolute";
	control.style.left = x.toString() + "px";
	control.style.top = y.toString() + "px";
	control.style.width = cx.toString() + "px";
	control.style.minWidth = cx.toString() + "px";
	control.style.maxWidth = cx.toString() + "px";
	control.style.height = cy.toString() + "px";
	control.style.minHeight = cy.toString() + "px";
	control.style.maxHeight = cy.toString() + "px";
	
	if (control.onAfterResize)
	{
		control.onAfterResize(control);
	}
}

function resizeChilds(elem)
{
	var childs = elem.children;
	var l = childs.length;
	for (var i = 0; i < l; i++)
	{
		var c = childs[i];
		if (c.requiredPosition)
			resizeControl(c, elem);
	}
	return true;
}

var __ScrollbarWidth = -1;
function getScrollbarWidth()
{
  if (__ScrollbarWidth < 0)
  {
	  // Creating invisible container
	  var outer = document.createElement('div');
	  outer.style.visibility = 'hidden';
	  outer.style.overflow = 'scroll'; // forcing scrollbar to appear
	  //outer.style.msOverflowStyle = 'scrollbar'; // needed for WinJS apps
	  document.body.appendChild(outer);

	  // Creating inner element and placing it in the container
	  var inner = document.createElement('div');
	  outer.appendChild(inner);
	  
	  // Calculating difference between container's full width and the child width
	  __ScrollbarWidth = (outer.offsetWidth - inner.offsetWidth);

	  // Removing temporary elements from the DOM
	  outer.parentNode.removeChild(outer);
  }
  return __ScrollbarWidth;
}

function xmlCreateElement(parentElement, name, id, className)
{
	var newElement = document.createElement(name);
	if (id) newElement.setAttribute("id", id);
	if (className) newElement.setAttribute("class", className);
	parentElement.appendChild(newElement);
	return newElement;
}

function createGuid()
{
	var dt = new Date().getTime();
	var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) 
	{
		var r = (dt + Math.random()*16)%16 | 0;
		dt = Math.floor(dt/16);
		return (c=='x' ? r :(r&0x3|0x8)).toString(16);
	});
	return "{" + uuid + "}";
}

function getControl(name)
{
	return document.getElementById(name);
}

function addControlEvent(elem, evnt, func) 
{
	if (elem.addEventListener)  // W3C DOM
		elem.addEventListener(evnt,func,false);
	else if (elem.attachEvent) // IE DOM
		elem.attachEvent("on"+evnt, func);
	else // No much to do
		elem["on"+evnt] = func;
}

function getBaseClassName(elem)
{
	var className = elem.getAttribute("class");
	return className ? className.split(' ')[0] : "";
}

function body_onKeyDown(event)
{
	switch (event.key)
	{
		case "F1":
		case "F5":
		case "F6":
		case "F7":
		case "F8":
		case "F9":
		case "F10":
		case "F11":
		case "F12":
			event.preventDefault();
			body_handleSpecialKey(event.key);
			break;

		case "r":
		case "R":
			if (event.ctrlKey)
			{
				event.preventDefault();
				body_handleSpecialKey(event.key);
			}
			break;
	}
}

function body_handleSpecialKey(key)
{
	var msg = { msg: "onSpecialKey", control: "body", data: key };
	notifyHost(msg);
}

String.prototype.replaceAll = function(s1, s2) 
{
	return this.split(s1).join(s2);
};

function parseIntEx(s)
{
	try
	{
		if ((s[0] == '0') && (s.length > 1))
			while ((s[0] == '0') && (s.length > 1)) s = s.substr(1);
		var result = parseInt(s);
		return isNaN(result) ? 0 : result;
	}
	catch(e)
	{
		return 0;
	}
}

function parseFloatEx(s)
{
	var posT1 = s.indexOf('.');
	var posT2 = s.indexOf(',');
	
	// Punkt vorhanden ?
	if (posT1 >= 0)
	{
		// Dezimaltrenner und Tausender vorhanden ?
		if (posT2 >= 0)
		{
			if (posT2 < posT1)  // en-US
				s = s.replaceAll(",","");
			else  // de-DE
				s = s.replaceAll(".","").replaceAll(",",".");
		}
	}
	// Nur Komma vorhanden
	else if (posT2)
	{
		s = s.replaceAll(",",".");
	}
		
	try
	{
		var result = parseFloat(s);
		return isNaN(result) ? 0 : result;
	}
	catch(e)
	{
		return 0;
	}
}

Number.prototype.roundKfm = function(dec)
{                                 
	var faktor = dec ? Math.pow(10,dec) : 1;
	var sign = this < 0;
	var val = Math.round(Math.abs(this) * faktor) / faktor;
	return sign ? -val : val;
};

Number.prototype.formatDE = function(dec, fWithDots, fHideZero)
{
	if ((this == 0) && (fHideZero))
		return "";
	
	var s 	= (dec == undefined) ? Math.abs(this).toString() : Math.abs(this.roundKfm(dec)).toString();
	var s2 = s.split(".");
	
	if (dec > 0)	
	{
		if (s2.length < 2)
			s2[1] = "".padEnd(dec,'0');
		else
			s2[1] = s2[1].padEnd(dec,'0').substr(0,dec);
	}
	
	//if ((typeof fWithDots != 'undefined') && fWithDots)
	if (fWithDots)
	{
		var l = s2[0].length;
		
		if (l > 9)
		{
			s2[0] = s2[0].substring(0,l-9) + "." + s2[0].substring(l-9);
			l++;
		}
		if (l > 6)
		{
			s2[0] = s2[0].substring(0,l-6) + "." + s2[0].substring(l-6);
			l++;
		}
		if (l > 3)
		{
			s2[0] = s2[0].substring(0,l-3) + "." + s2[0].substring(l-3);
		}
	}
	
	return this < 0 ? "-" + s2.join(",") : s2.join(",");
};

Number.prototype.formatEN = function(dec)
{
	var s 	= (dec == undefined) ? Math.abs(this).toString() : Math.abs(this.roundKfm(dec)).toString();
	var s2 = s.split(".");
	
	if (dec > 0)	
	{
		if (s2.length < 2)
			s2[1] = "".padEnd(dec,'0');
		else
			s2[1] = s2[1].padEnd(dec,'0').substr(0,dec);
	}
	
	return this < 0 ? "-" + s2.join(".") : s2.join(".");
};

function parseParameters(jsonParameters)
{
	return typeof jsonParameters == "string" ? JSON.parse(jsonParameters) : jsonParameters;
}

function runPopupMenu(x, y, optionString, fnOnClick)
{
	var menu = xmlCreateElement(document.body, "div", null, "popupMenu");
    //menu.setAttribute("onmouseleave", "this.remove();");
	menu.onmouseleave = function() 
	{
		menu.remove();
		fnOnClick(0);
	};

    optionString.split(';').forEach(function(item)
	{
		var nPos = item.indexOf(' ');
		if (nPos > 0)
		{
			var choiceRet = parseIntEx(item.substring(0,nPos));
			var choiceTxt = item.substring(nPos + 1);
			var enabled = true;
			//alert(choiceRet.toString() + ": " + choiceTxt);
			var btn = xmlCreateElement(menu, "a");
			switch (choiceTxt[0])
			{
				case '-':
					choiceTxt = choiceTxt.substring(1);
					enabled = false;
					break;
			}
			
			btn.innerText = choiceTxt;
			if (enabled)
				btn.onclick = function()
				{
					menu.remove();
					fnOnClick(choiceRet);
				};
			else
				btn.setAttribute("disabled", "true");
		}
		else if (item == "-")
		{
			xmlCreateElement(menu, "hr");
		}
	});
	
	// calculate position from mouse ?
	if (x < 0) x = mousePos.x - 8;
	if (y < 0) y = mousePos.y - 8;

	// position is outside ?
	if (x < 0) x = 1;
	if (y < 0) y = 1;
	var rect = menu.getBoundingClientRect();
	var cxOverFlow = x + rect.width - window.innerWidth;
	var cyOverFlow = y + rect.height - window.innerHeight;
	if (cxOverFlow > 0) x -= cxOverFlow + 1;
	if (cyOverFlow > 0) y -= cyOverFlow + 1;
	
	// top or left position is outside ?
	if (x < 0) x = 1;
	if (y < 0) y = 1;

	// assign position
	menu.style.left = x.toString() + "px";
	menu.style.top = y.toString() + "px";
	menu.style.visibility = "visible";
}
