// validation.js contains functions and classes used for input validation.
var JSDC_VALIDATION_EXISTS = true;
function filter_string(AStr, Mask)  
{
	var Char;
	var strLength = AStr.length;
	for (var currChar = 0; currChar < strLength; currChar++) 
	{ 
		Char = AStr.charAt(currChar); 
		if (Mask.indexOf(Char) == -1) 
		{
			return Char;
			break;
		}
	}
	return null;
   
}


function isdecimal(AStr)
{
	var check_result = filter_string(AStr, "0123456789."); // TODO: Make a little more international.
	if (check_result) 
	{
		return 'A "'+ check_result + '" is not allowed in a decimal number.'
	}
}

function isinteger(AStr)
{
	var check_result = filter_string(AStr, "0123456789"); // TODO: Make a little more international.
	if (check_result) 
	{
		return 'A "'+ check_result + '" is not allowed in a integer number.'
	}
}

function validate_datatype(value, datatype, rules)
{
	switch (datatype)
	{
		case "integer": 
			return isinteger(value);
		break;
		case "decimal": 
			return isdecimal(value);
			
		break;
		case "string": 
			return null;
		break;
		case "custom": 
			return null;
		break;
		case "multiple": 
			return null;
		break;
		default:
			throw ('Internal JSDC error: invalid datatype: "' + datatype + '"');
	}
}

// This object pulls, on it's creation, the important data from the event objects.
function edit_event_object(e)
{
	this.target = window.event ? event.srcElement : e.target; 
	this.keycode = window.event ? window.event.keyCode : e.which;
	this.event = window.event ? window.event : e;
	this.innerWidth = window.event ? document.body.clientWidth : window.innerWidth;
	this.innerHeight = window.event ? document.body.clientHeight : window.innerHeight;
	if (this.keycode > 0 && this.keycode != 13 && this.keycode > 3) // Disregard return keys and FF clicks.
	{					
		// Handle numpad-characters.
		if (this.keycode > 95 && this.keycode < 106) { this.keycode = this.keycode - 48}
		this.key = String.fromCharCode(this.keycode);						
	}
	else
	{
		this.key = null;
	}
	this.value = this.target.value;
}


function setErrorBackground(val_result, event_object, app_obj)
{
	if (val_result)
	{
		if (app_obj)
		{
		
			event_object.target.style.backgroundColor = app_obj.errorcolor;
		}
		else
		{
			event_object.target.style.backgroundColor = "#FFAAAA";
		}
	}
	else
	{
		// Small hack to get back to old color.

	    var tmp_classname = event_object.target.className;

	    if (event_object.target.style.removeProperty)
	    {
		    event_object.target.className = "";
			event_object.target.style.removeProperty("background-color");
			event_object.target.className = tmp_classname;
		}
		else
		{
			if (app_obj) // Bloody IE that doesn't support style.removeProperty.
			{
				event_object.target.style.backgroundColor = app_obj.IEOKcolor;
			}
			else
			{
				event_object.target.style.backgroundColor = "#FFFFFF";
			}
		}
	}

}

// The editor object class holds the settings for input handling of a certain input/select element.
// This is used when creating standalone input elements.
function editor_object(element, datatype, onEdit, onError, app_obj)
{
	this.element = element;
	this.app_obj = app_obj;
	this.datatype = datatype; 
	this.onEdit = onEdit;
	this.onError = onError;
	this.tag = null;
	var parentobj = this; // Declaration for the functions...JavaScript duh..
	if (app_obj)
	{
		app_obj.editors.push(this);
	}
	this.DoOnEdit = function DoOnEdit(e)
	{
		var event_object = new edit_event_object(e);
		if (event_object.key)
		{
			var val_result = validate_datatype(event_object.value, parentobj.datatype);

			setErrorBackground(val_result, event_object, parentobj.app_obj);
			if (val_result)
			{
				if (onError)
				{
					onError(this.element, val_result);
				}
			}
			else
			{
				if (onEdit)
				{
					onEdit(this.element);
				}
			}
		}
	}
	
	// Edit event
	if (element.attachEvent) 
	{
		element.attachEvent("onkeyup", this.DoOnEdit);
	}
	else
	{
		element.addEventListener("keyup", this.DoOnEdit, false); // standards compliant; doesn't work in IE
	}

}

function typeitem(name, datatype, description)
{
	this.name = name;
	this.datatype = datatype;
	this.description = description;
}


function typeset(id, name)
{
	this.id = id;
	this.name = name;
	this.typeitems = new Array();

}

function multiple_type_editor_make_typesets(editor)
{
	var row_idc, curr_typeset, typeinfos, curr_typedatas,typeitems, curr_typeitem;
	var typesets = new Array();
	var data = editor.datatable.columns[1].data;
	var datalength = data.length; 
	for (var row_idx = 1; row_idx < datalength; row_idx++) 
	{
	
		typeinfos = editor.datatable.columns[0].data[row_idx].split(":");
		 
		curr_typeset = new typeset(typeinfos[0],typeinfos[1]);
		
		typeitems = data[row_idx].split(";");
		for (type_idx in typeitems)
		{
			if (typeitems[type_idx] !="")
			{
				curr_typedatas = typeitems[type_idx].split(":");
				curr_typeitem = new typeitem(curr_typedatas[0], curr_typedatas[1], curr_typedatas[2]);
				curr_typeset.typeitems.push(curr_typeitem);
			}
		}
		typesets.push(curr_typeset);

	}
	return (typesets);
}

// The param editor functionality:

function multiple_type_editor_show(row_idx, editor, event_object)
{
	
	// Find applicable type set and current data.
	var typesetid = editor.typesetid_column.getdata(row_idx);
	
	var curr_datas = editor.value_column.getdata(row_idx).split(";");

	// Find type set
	var find_row_idx = 0;
	var typesetslength = editor.typesets.length;
	var typeset = null;
	while (find_row_idx < typesetslength)
	{
		if (editor.typesets[find_row_idx].id == typesetid)
		{
			typeset = editor.typesets[find_row_idx];
			break;
		}
		
		find_row_idx++;
	}

	if (!typeset)
	{
		alert('JSDC error: This row does not have any types. ');
	}
	else
	{
		
		var editor_height = Number(Number(typeset.typeitems.length)* Number(30))+Number(50);

		// Add the close button.

		var editor_width = 400;
		var margin = 70;
		var posx = Number(event_object.event.clientX) - Number(50);
		
		if (Number(posx) + Number(editor_width) + margin >  event_object.innerWidth)
		{
			posx = Number(event_object.innerWidth) - Number(editor_width) - margin;

		}
		var posy = Number(event_object.event.clientY) - Number(50);
		if (Number(posy) + Number(editor_height) + margin >  event_object.innerHeight)
		{
			posy = Number(event_object.innerHeight) - Number(editor_height) - margin;

		}
		if (editor.edit_element)
		{
			editor.edit_element.parentNode.removeChild(editor.edit_element);
		}
		editor.edit_element = document.createElement("div");
		editor.edit_element.style.position = "absolute";
		editor.edit_element.style.top = posy+"px";
		editor.edit_element.style.left = posx+"px";;

		editor.edit_element.style.height = Number(editor_height) + "px";
		editor.edit_element.style.width = editor_width + "px";
		editor.edit_element.style.zIndex  = 100;
		if (editor.windowclass)
		{
			editor.edit_element.className = editor.windowclass;
		}
		else
		{
			editor.edit_element.style.backgroundColor = "#FFFFFF";
		}		

		// Make editor title

		document.body.appendChild(editor.edit_element);
	//	editor.edit_element.document.title = "Editing : " + typeset.name;

		var headerelement = document.createElement("div");
		headerelement.innerHTML = typeset.name + "-editor:";
		if (editor.headerclass)
		{
			headerelement.className = editor.headerclass;
		}
		else
		{
			headerelement.style.textDecoration = "underline";
		}
		editor.edit_element.appendChild(headerelement);
//		editor.edit_element.innerHTML = typeset.typeitems[ps_idx].datatype + "-editor:";
		var tableelement = document.createElement("table");
		editor.edit_element.appendChild(tableelement);
		

		editor.editors.length = 0;
		var ps_idx;
		for (ps_idx in typeset.typeitems)
		{
			var new_row = document.createElement("tr");
			add_tr_to_table(tableelement, new_row)
	
			var name_td = document.createElement("td");
			name_td.innerHTML = typeset.typeitems[ps_idx].name + ":";
			if (editor.captionclass)
			{
				name_td.className = editor.captionclass;
			}

			new_row.appendChild(name_td);
	
			var value_td = document.createElement("td");
			var input_element = document.createElement("input");
			input_element.value = curr_datas[ps_idx];
			if (editor.captionclass)
			{
				input_element.className = editor.editorclass;
			}
			value_td.appendChild(input_element);
	
			var desc = document.createElement("a");
			desc.title = typeset.typeitems[ps_idx].name + ": " +typeset.typeitems[ps_idx].description;
			desc.innerHTML = "[?]";
			if (editor.captionclass)
			{
				desc.className = editor.captionclass;
			}
			value_td.appendChild(desc);
			
			new editor_object(input_element, typeset.typeitems[ps_idx].datatype, editor.DoOnEdit);
			editor.editors.push(input_element);
			new_row.appendChild(value_td)
		
		}
		if (editor.editors.length > 0)
		{
			editor.editors[0].focus();
		}
		
		
		// Add the close button.
		var close_div = document.createElement("div");
		close_div.style.position = "absolute";
		close_div.style.bottom = "10px";
		close_div.style.right = "10px";
		
		var close_button = document.createElement("input");
		close_button.type = "button";
		close_button.value = "Close";
		close_button.name = "Close";
		if (editor.buttonclass)
		{
			close_button.className = editor.buttonclass;
		}
	
		if (close_button.attachEvent) 
		{
			close_button.attachEvent("onclick", editor.DoEditorClose);
		}
		else
		{
			close_button.addEventListener("click", editor.DoEditorClose, false); // standards compliant; doesn't work in IE
		}
		close_div.appendChild(close_button);
		editor.edit_element.appendChild(close_div);
	}
}

function multiple_type_editor(typesetURL, value_column, typesetid_column)
{
	if (typeof JSDC_DATATABLE_EXISTS!="undefined")
	{
		this.datatable = new datatable("mte_dt_"+value_column.columnname);
	}
	else
	{
		alert('JSDC error: You must include datatable.js to use the multiple_type_editor class.');
		throw('JSDC error: You must include datatable.js to use the multiple_type_editor class.');

	}
	this.title = value_column.columnname;
	this.typesetURL = typesetURL;

	if (typesetURL)
	{
		this.datatable.populate_from_csv_URL(typesetURL, "\n", "|");
		this.typesets = multiple_type_editor_make_typesets(this);
	}
	this.value_column = value_column;
	this.typesetid_column = typesetid_column;
	
	if (value_column)
	{
		value_column.multiple_editor = this;
	}
	
	// Custom CSS Style information
	this.windowclass = null; // Style of the edit window.
	this.captionclass = null;// Style of the captions and header.
	this.editorclass = null;// Style of the editors.
	this.buttonclass = null;// Style of the editon button(s).
	
	
	this.edit_element = null;	

	this.current_row_idx = null;
	this.editors = new Array();

	var function_ref = this; // For the functions

	this.edit = function edit(row_idx, event_object)
	{
		multiple_type_editor_show(row_idx, function_ref, event_object);
		function_ref.current_row_idx = row_idx;
	}

	this.DoOnEdit = function DoOnEdit()
	{
		var curr_data = "";
		// Loop input values
		var val_idx = 0;
		for (val_idx in function_ref.editors)
		{
			curr_data = curr_data + function_ref.editors[val_idx].value + ";";
		}
		function_ref.value_column.setdata(function_ref.current_row_idx,curr_data);

	}
	
	this.DoEditorClose = function DoEditorClose()
	{
		
		function_ref.edit_element.parentNode.removeChild(function_ref.edit_element);
		function_ref.edit_element = null;
	}

	
}