var form;

/*---------------------------------------------
global functions
-----------------------------------------------*/

/*returns the element with the given id

id : string --> return element
id: object --> returns id
*/
function $(id)
{
	if (typeof id == "object")
		return id;

	if (typeof id == "string")
		return document.getElementById(id);

	return id;
}

/* days in month depending on year (4digits) */
function getDaysInMonth(year,month)
{
	var monthLength = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
	if (month == 2)
	{
		// berechnen ob schaltjahr
		if ( (year % 4 == 0 && year % 100 != 0) || (year % 4 == 0 && year % 100 == 0 && year % 400 == 0))
		{
			monthLength[1] = 29;
		}
	}
	
	return monthLength[month-1];
}

/*	returns distinct colum from 2 dimensional array */
function getColumnFromArray(arr,index)
{
	// copy value into output array
	var arrOut = new Array();		
	var x=0,xOld='_#%#_';
	var j=0;
	for(var i=0; i<arr.length; i++)
	{
		x = arr[i][index];
		
		if (x != xOld)
		{
			xOld = x;
			arrOut[j] = new Array(x);
			j++;
			
		}
	}
	arrOut.sort();
	
	// make output array distinct
	x=0;
	xOld=0;
	j=0;
	var arrOut2 = new Array();
	for(var i=0; i< arrOut.length; i++)
	{
		x = arrOut[i];
		if (x != xOld)
		{
			xOld = x;
			arrOut2[j] = x;
			j++;
		}
	}
	arrOut2.sort();				
	
	return arrOut2;
}

/*Returns subset from multidimensional array.

arr = source array
index = Field for comparison
search = Field comparison value
*/
function getSubsetFromArray(arr,index,search)
{
	var arrOut = new Array();
	var x;
	var j=0;
	for(var i=0; i< arr.length; i++)
	{
		x = arr[i][index];
		if (x == search)
		{
			arrOut[j] = arr[i];
			j++;
		}
	}
	return arrOut;
}						

/* sorts multidimensional array on specified field 
arr = array
dimesion = field in array
*/
function sortArrayDimension(arr,dimension)
{
	// Die Schlüssel in dieser dimension finden und sortieren. Die Schlüsselliste sollte keine doppelten Werte enthalten.
	var arrKeys = new Array();	
	var oldKey = '_#%#_';
	var j=0;
	for(var i=0; i < arr.length; i++)
	{
		var key = arr[i][dimension];
		if (key != oldKey)
		{
			oldKey = key;
			arrKeys[j] = key;
			j++;
		}
	}		
	
	arrKeys.sort();
	
	// jetzt ist der Schlüssel sortiert als nächstes müssen alle Wertepaare mit diesem Schlüssel untereinander eingefügt werden.
	
	var arrOut = new Array();
	var k=0;
	for(var i=0; i< arrKeys.length; i++)
	{
		for(var j=0; j< arr.length; j++)
		{
			if (arr[j][dimension] == arrKeys[i])
			{
				arrOut[k] = arr[j];
				k++;
			}
		}
	}	
	
	return arrOut;
}

/*returns an 2 Dimensional array with value,key pairs as rows.*/
function getValueKeyArray(values,keys)
{
	var result = new Array();
	for(var i=0; i< keys.length; i++)
	{
		result[i] = new Array(values[keys[i]], keys[i]);
	}	
	result = sortArrayDimension(temp,0);	
	return result;
}

/*lists a multi dimensional array*/
function arrayToString(arr)
{
	var result = "";
	for(var i=0; i< arr.length;i++)
	{		
		result += i + ")\t";
		for (var j=0; j< arr[i].length; j++)
		{
				result += "'" + arr[i][j] + "'\t";
		}
		result += "\n";
	}
	return result;
}

/*simply lists a 1D Array*/
function simpleArrayToString(arr)
{
	var result = "";
	for(var i=0; i< arr.length;i++)
	{		
		result += i + ")\t" + arr[i] + "\n";				
	}
	return result;
}

/*using a delegate to create a proper self reference on eventhandler methods.*/
function delegate(instance, method) {
  return function() {
    return method.apply(instance, arguments);
  }
}

/*---------------------------------------------
formular element functions
-----------------------------------------------*/

/*	Sets the options for this dd */
function setDropdownOptions(dd, data, titleIndex, valueIndex, keepFirst)
{
	clearDropdown(dd, keepFirst);	
	var optionOffset = 0;
	if (keepFirst && keepFirst == true)
	{
		optionOffset = 1;
	}
		
	for(var i=0; i< data.length; i++)
	{
		dd.options[i+optionOffset] = new Option(data[i][titleIndex], data[i][valueIndex]);
	}		
			
	dd.selectedIndex = 0;	
}

/* Sets the selectedIndex to the option with the specified value */
function setDropdownSelectedValue(dd,value)
{
	for(var i=0; i<dd.options.length; i++)
	{
		if (dd.options[i].value == value)
		{
			dd.selectedIndex = i;
			break;
		}
	}
}

/* return the selected value of the specified dropdown */
function getDropdownSelectedValue(dd)
{
	return dd.options[dd.selectedIndex].value;
}

/*	clears all options of the specified Dropdown
	If useAll is set to true the function assumes that the first Element in the dd is the all Element.
*/
function clearDropdown(dd, keepFirst)
{
	dd = $(dd);
	if (keepFirst && keepFirst == true)
	{
		var firstOption = dd.options[0];
		dd.options.length = 0;
		dd.options[0] = firstOption;	
	}
	else
	{
		dd.options.length = 0;
	}
	dd.selectedIndex = 0;
}

/* generates a linklist an writes the result to the cDiv innerHTML */
function viewLinklist(output, selectedKey,datatable,keyIndex,titleIndex,urlIndex)
{
	var subset = datatable.getDatasource();
	if (selectedKey != "%") 
		subset = datatable.subset(keyIndex,selectedKey);
	var result = "<ul>";
	for (var i=0; i< subset.length; i++)
	{
		result += '<li><a href="' + subset[i][urlIndex] + '">' + subset[i][titleIndex] + '</a></li>\n';
	}
	result += '</ul>';
	
	output.clear();
	output.write(result);
}

function debugShowSelf()
{
	var  text = "Variablen, Funktionen und Klassen<br>";
	for(entry in self) {
		text = text + "<br><b>" + entry + "</b> typeof=<b>" + typeof(self[entry]) + "</b> value=<i>" +  self[entry] + "</i>"
	}
	self.document.body.innerHTML = text;
}

/*
------------------------------------------------------------
- Klassendefinitionen
------------------------------------------------------------
*/

/*Datatable Klasse*/	
var cDatatable = function(datasource){
	var _datasource = datasource;	
	this.getDatasource = function() { return _datasource; }
	this.column = function(index) { return getColumnFromArray(_datasource,index);}
	this.count = function() { return _datasource.length; }
	this.sort = function(dimension) { _datasource = sortArrayDimension(_datasource,dimension); }
	this.subset = function(keyIndex, key) { return getSubsetFromArray(_datasource,keyIndex,key); }
}

/*Div Klasse*/	
var cDiv = function(id){
	var _id = id;
	this.write = function(text) { $(_id).innerHTML += text; }
	this.clear = function() { $(_id).innerHTML = ""; }
}	

/*
	Abhängige Dropdowns 
	Hiermit können voneinander abhängige Dropdowns realisiert werden.
	
	also dd2 ist von dd1 abhängig.
	Dabei ist die Struktur der Datatable vorgegeben.
	
	0 = Title & Key des ersten DD
	1 = Title des zweiten DD
	2 = URL und damit Value des zweiten DD
*/
var cDDUpdate = function(dt, dd1, dd2, action){

/*--------------------------------------*/
/*variablen*/
	var _dt = dt
	var _dd1 = dd1
	var _dd2 = dd2
	
	// Den Eventhandler für onChange des zweten DropDown eintragen
	var _action = ""
	if (action)
		_action = action
		
	//Soll bei dem zweiten DropDown das erste Element behalten werden
	var _dd2KeepFirst = false;
	if (_action == "gotoUrl")
		_dd2KeepFirst = true;

/*--------------------------------------*/	
/*methoden*/
	
	var _update = function(dd){		
		if (debug)
			alert("changed dd: " + dd);			
					
		_clearOnchange();
		
		if (dd == _dd1)
		{
			//Hier die verschiedenen Eventhandler für das erste DropDown eintragen
			setDropdownOptions($(_dd2), _dt.subset(0,_selectedValue(_dd1)),1,2,_dd2KeepFirst);
		}
		else
		{
			// Hier die verschiedenen Eventhandler für das zweite DropDown eintragen
			if (_action == "gotoUrl")
			{
				var result = _selectedValue(_dd2);
				if (debug)
					alert("gotoUrl: " + result);			
				if (result != "-")
					document.location.href = result;
			}
			else
			{
				// alle anderen sind nicht definiert und machen nichts
			}
		}
		
		_setOnchange();
	}
	this.update = _update;
	
	var _selectedValue = function(dd) { 
		var result
		if ( $(dd).options.length >0)
			result = $(dd).options[$(dd).options.selectedIndex].value;			
		if (debug)
			alert(dd + " selectedValue: " + result);
		return result;
	}	
	this.selectedValue = _selectedValue;
	
	var _setOnchange = function(){
		if (debug)
			alert("set: DDUpdate onchange handler");
		$(_dd1).onchange = function () {_update(_dd1) };
		$(_dd2).onchange = function() {_update(_dd2) };
	}
	this.setOnchange = _setOnchange;
	
	var _clearOnchange = function(){
		if (debug)
			alert("clear: DDUpdate onchange handler");
		$(_dd1).onchange = function(){};
		$(_dd2).onchange = function(){};
	}
	this.clearOnchange = _clearOnchange;
	
/*--------------------------------------*/
/*konstruktor*/

	setDropdownOptions($(_dd1), _dt.column(0), 0, 0, false);		   	
	setDropdownOptions($(_dd2), _dt.subset(0,_selectedValue(_dd1)),1,2,_dd2KeepFirst);

	this.setOnchange();

}

/*
Öffnet ein Popup mit der Adresse die als Wert in dem selektierten Element des angegebenen DropDown eingetragen ist.
*/
function openUrlSelected(dd)
{
	var elem = $(dd)
	if (elem && elem.options)
	{
		var url = elem.options[elem.options.selectedIndex].value;
		if (debug)
			alert("openUrlSelected: " + url);
		gotoUrlNewWinSizeScrollableWithMenuR(url,800,600);			
	}
}