/******************************************************************************************
* Generic form management class (with some BOSI-specific hacks for WYSIWYG fields etc.)
******************************************************************************************/
function BOSIFormManager(form,parent) {
	
	// initialize the member function references 
	// for the class prototype
	if (typeof(_BOSIFormManager_prototype_called) == 'undefined')
	{
		_BOSIFormManager_prototype_called = true;
		BOSIFormManager.prototype.init = init;
		BOSIFormManager.prototype.reset = reset;
		BOSIFormManager.prototype.toStruct = toStruct;
		BOSIFormManager.prototype.fromStruct = fromStruct;
		BOSIFormManager.prototype.toPackage = toPackage;
		BOSIFormManager.prototype.fromPackage = fromPackage;
		BOSIFormManager.prototype.getValue = getValue;
		BOSIFormManager.prototype.setValue = setValue;
	}

	this.form = form
	this.parent = parent
	this.fields = new Array();
	this.init();

	function init() {
		for( var j=0; j < this.form.elements.length; j++ ) {
			if(this.parent && this.form.elements[j].bosiparent != this.parent) continue;
			if(this.form.elements[j].tagName == 'FIELDSET') continue;
			this.fields.push(this.form.elements[j]);
		}
	}

	function reset(){
		for( var j=0; j < this.fields.length; j++ ) {
			this.setValue(this.form.elements[this.fields[j].name],'');
		}
		return true;
	}

	function toStruct(){
		struct = new Object();
		// loop through form elements (get the element by name not index so we get a list if it's multiple checkboxes/radios)
		for( var j=0; j < this.fields.length; j++ ) {
			struct[this.fields[j].name] = this.getValue(this.form.elements[this.fields[j].name]);

			// error handling
			var key = this.fields[j].name
			var err = document.getElementById(key.substring(7,key.length)+'_ERROR');
			var con = document.getElementById(key.substring(7,key.length)+'_CONTAINER');
			if(con && err && con.className == 'error') {
				struct['_ERROR_'+key] = err.innerHTML;
			}
		}
		return struct;
	}
	
	function fromStruct(struct){
		// loop through form elements
		for( key in struct ){
			var element = this.form.elements[key];
			if( element != null ) {
				this.setValue(element,struct[key]);
			}

			// error handling
			var err = document.getElementById(key.substring(7,key.length)+'_ERROR');
			var con = document.getElementById(key.substring(7,key.length)+'_CONTAINER');
			if(key.substring(0,7) == '_ERROR_') {
				if(err) err.innerHTML = struct[key];
				if(con) con.className = 'error';
			} else {
				if(err) err.innerHTML = '';
				if(con) con.className = '';
			}
		}
		return true;
	}

	
	function toPackage(){
		return serialise(this.toStruct());
	}

	function fromPackage(pkg){
		return this.fromStruct(deserialise(pkg));
	}

	function getValue(element) {
		var type;
		var value = '';
	
		if(element.isscintilla) {
			return element.text.substring(0,element.text.length-1);
		}

		if(element.type == null)
			type = (element[0].type.substring(0,6) == "select") ? "select" : element[0].type;
		else
			type = (element.type.substring(0,6) == "select") ? "select" : element.type;
	
		if( type == "select" ){
			if( element.type == "select-one" ){
				value = (element.selectedIndex == -1) ? "" : element[element.selectedIndex].value;
			} else {
				// loop through all element in the array for element field
				value = new Object();
				for( var i=0; i < element.length; i++ ){
					// if the element is selected, get the selected values (unless it's a dummy container)
					if( element[i].selected ){
						// append the selected value, if the value property doesn't exist, use the text
						value[element[i].value] = 1;
					}
				}
			}
		} else if( type == "checkbox" ){
			// if more then one checkbox
			if( !!element[0] ){
				// loop through all checkbox elements, and if a checkbox is checked, grab the value
				value = new Object();
				for( var i=0; i < element.length; i++ ) if( element[i].checked ) value[element[i].value] = 1;
			// otherwise, store the value of the field (if checkmarked) into the list
			} else if( element.checked ){
				value = 'yes';
			}
		} else if( type == "radio" ){
			// loop through all checkbox elements, and if a checkbox is checked, grab the value
			value = new Object();
			for( var i=0; i < element.length; i++ ) if( element[i].checked ) value = element[i].value;
		} else if( element.getAttribute('iswysiwyg')=='1' ) {
			if(element.onblur) { element.onblur(); }
			value = element.value;
		} else {
			value = element.value;
		}
		
		return value;
	}
	
	function setValue(element,value){
		var type;
		var v;
		var reset = true;
	
		if(element.isscintilla) {
			element.text = value;
		}

		if(element.type == null)
			type = (element[0].type.substring(0,6) == "select") ? "select" : element[0].type;
		else
			type = (element.type.substring(0,6) == "select") ? "select" : element.type;
		
		if( type == "select" ){
			var bSelectOne = (element.type == "select-one") ? true : false;
			bLookForFirst = true; // if select-one type, then only select the first value found
			// loop through all element in the array for this field
			for( var i=0; i < element.length; i++ ){
				v = element[i].value;
				if(bSelectOne) {
					bSelectItem = (value == v);
				} else {
					//alert(v + ' -- ' + !!value[v]);
					bSelectItem = !!value[v];
				}
				if( bSelectItem && (bLookForFirst || !bSelectOne) ) element[i].selected = true;
				else if(reset || bSelectOne) element[i].selected = false;
				if( bSelectItem && bLookForFirst ) bLookForFirst = false;
			}
		} else if( (type == "checkbox") || (type == "radio") ){
			// if more then one checkbox
			if( !!element[0] ){
				// loop through all checkbox elements, and if a checkbox is checked, grab the value
				for( var i=0; i < element.length; i++ ){
					v = element[i].value;
					//alert(v + ' -> ' + !!value[v]);
					if( !!value[v] ) element[i].checked = true;
					else if( reset ) element[i].checked = false;
				}
			// otherwise, store the value of the field (if checkmarked) into the list
			} else if( value ){
				element.checked = true;
			} else if( reset ){
				element.checked = false;
			}
//		} else if( element.getAttribute('iswysiwyg')=='1' ) {
//			element.value = (!value) ? "" : value;
//			if(element.onchange) { element.onchange(); }
		} else {
			element.value = (!value) ? "" : value;
			if(element.onchange) { element.onchange(); }
		}

		return true;
	}
}
	

/******************************************************************************************
* Replacement splice funciton
******************************************************************************************/
function splice(index,delcount) {
	var i,j;
	var array = this.slice(0);
	while(this.length) this.pop();
	for(i=0;i<array.length;i++) {
		if(i==index) {
			if(!delcount) {
				this.push(array[i]);
			}
			for(j=2;j<arguments.length;j++) {
				this.push(arguments[j]);
			}
		} else if(i>index && i<(index+delcount)) {
			continue;
		} else {
			this.push(array[i]);
		}
	}
	if(i==index) {
		for(j=2;j<arguments.length;j++) {
			this.push(arguments[j]);
		}
	}
}

/******************************************************************************************
* BOSI-Specific List Manager
******************************************************************************************/
function BOSIListManager(name) {

	// initialize the member function references 
	// for the class prototype
	if (typeof(_BOSIListManager_prototype_called) == 'undefined')
	{
		_BOSIListManager_prototype_called = true;
		BOSIListManager.prototype.init = init;
		BOSIListManager.prototype.load = load;
		BOSIListManager.prototype.render = render;
		BOSIListManager.prototype.select = select;
		BOSIListManager.prototype.insertSelected = insertSelected;
		BOSIListManager.prototype.deleteSelected = deleteSelected;
		BOSIListManager.prototype.moveSelected = moveSelected;
		BOSIListManager.prototype.move = move;
		BOSIListManager.prototype.save = save;
		BOSIListManager.prototype.save_write = save_write;
		BOSIListManager.prototype.onkeydown = onkeydown;
		BOSIListManager.prototype.popupEditSelected = popupEditSelected;
	}

	this.name = name;
	this.init();

	function init() {
		this.selected = null;
		this.table = document.getElementById(this.name+'_TABLE');
		this.form = new BOSIFormManager(document.getElementById('mainform'),this.name);
		this.load();
	}

	function load() {
		var serialised = unescape(document.getElementById('mainform').elements[this.name].value);
		if(!serialised) { this.packages = new Array(); }
		else { this.packages = eval(serialised); }
		if(!this.packages.splice) { this.packages.splice = splice };
	}
	
	function render() {
		var htmlout = '';
		var struct;
		var count;
		var i, j;
		var keys = new Array();
	
		this.selected = null;
	
		if(!this.packages.length) { 
			this.table.innerHTML = '<table class="listing" id="' + this.name + '_TABLE_ACTUAL" width="' + (this.table.offsetWidth-22) + '"><tr><td><center>no items</center></tr></td></table>'; 
			return; 
		}
		
		htmlout += '<table class="listing" id="' + this.name + '_TABLE_ACTUAL" width="' + (this.table.offsetWidth-22) + '">';

		htmlout += '<thead><tr>';
		for(j=0;j<this.form.fields.length && j<3;j++) {
			if(!this.form.fields[j].getAttribute('default')) continue;
			htmlout += '<th nowrap>' + this.form.fields[j].getAttribute('default').substring(0,20) + '</th>';
		}
		htmlout += '</tr></thead><tbody>';
	
		for(i=0;i<this.packages.length;i++) {
			struct = this.packages[i];
	
			htmlout = htmlout + '<tr id="'+this.name+'_ROW_'+i+'" onclick="BOSILists[' + "'" + this.name + "'].select(" + i + ');">'
			count=0;
			for(j=0;j<this.form.fields.length && j<3;j++) {
				if(!this.form.fields[j].getAttribute('default')) continue;
				var key = this.form.fields[j].name;
				if(struct[key] && struct[key].substring) {
					htmlout += '<td nowrap>' + struct[key].substring(0,50).replace(/</g,'&lt;').replace(/>/g,'&gt;') + '</td>';
					//htmlout += '<td nowrap>' + struct[key].replace(/</g,'&lt;').replace(/>/g,'&gt;') + '</td>';
				} else {
					htmlout += '<td>&nbsp;</td>';
				}
			}
			htmlout += '</tr>'
	
		}
	
		htmlout += '</tbody></table>'
		this.table.innerHTML = htmlout
	}
	
	function insertSelected(clone) {
		var index = 0;
		if(this.selected!=null) { this.save(); index = this.selected; }
		if(!clone) { this.form.reset(); }
		this.packages.splice(index,0,this.form.toStruct());
		document.getElementById(this.name).value = serialise(this.packages);
		this.render()
		this.select(index)
		if(!!document.getElementById(this.name+'_LISTUID')) { document.getElementById(this.name+'_LISTUID').value = ''; }
	}
	
	function deleteSelected() {
		if(this.selected==null) { return; }
		index = this.selected;
		this.packages.splice(index,1);
		document.getElementById(this.name).value = serialise(this.packages);
		this.render()
		if(index>this.packages.length-1) {
			this.select(this.packages.length-1)
		} else {
			this.select(index)
		}
	}
	
	function select(index) {
		if(!this.packages.length) { return; }
	
		if(this.selected != null) {
			document.getElementById(this.name+'_ROW_'+this.selected).style.background = 'white';
			document.getElementById(this.name+'_ROW_'+this.selected).style.color = 'black';
			// save any sublists
			for(j=0;j<this.form.fields.length;j++) {
				if(this.form.fields[j].getAttribute('bosilist')) { BOSILists[this.form.fields[j].name].save_write(); }
			}
			this.save_write();
			this.render();
		}
		
		document.getElementById(this.name+'_ROW_'+index).style.background = '#000080';
		document.getElementById(this.name+'_ROW_'+index).style.color = 'white';
		this.selected = index;
		this.form.fromStruct(this.packages[index]);
	}
	
	function move(index,direction) {
		// save current form details first
		this.packages[this.selected] = this.form.toStruct();
	
		var newindex = this.selected;
		switch(direction) {
			case 'up':
				if(index==0) { return; }
				this.packages.splice(index-1,2,this.packages[index],this.packages[index-1]);
				if(	newindex==index)
					newindex -= 1;
				else if(newindex==index-1)
					newindex += 1;
				break;
			case 'down':
				if(index==this.packages.length-1) { return; }
				this.packages.splice(index,2,this.packages[index+1],this.packages[index]);
				if(newindex==index)
					newindex += 1;
				else if(newindex==index+1)
					newindex -= 1;
				break;
			case 'top':
				if(index==0) { return; }
				this.packages.splice(0,0,this.packages[index]);
				this.packages.splice(index+1,1);
				if(newindex==index)
					newindex = 0;
				else
					newindex += 1;
				break;
			case 'bottom':
				if(index==this.packages.length-1) { return; }
				this.packages.splice(this.packages.length,0,this.packages[index]);
				this.packages.splice(index,1);
				if(newindex==index)
					newindex = this.packages.length-1;
				else
					newindex -= 1;
				break;
			default:
				return;
		}
		document.getElementById(this.name).value = serialise(this.packages);
		this.render();
		this.select(newindex);
	}
	
	function moveSelected(direction) {
		this.move(this.selected,direction);
	}

	function save() {
		// save the currently selected element, if necessary
		if(this.selected != null)
			// save any sublists
			for(j=0;j<this.form.fields.length;j++) {
				if(this.form.fields[j].getAttribute('bosilist')) { BOSILists[this.form.fields[j].name].save_write(); }
			}
			this.packages[this.selected] = this.form.toStruct();

		/*
		 push each item into the form and out again to make sure all this.packages structures are in the same format
		 they will have when we finally submit the form; vital for checking the form for changes in onunload
		*/
		for(i=0;i<this.packages.length;i++) {
			this.form.fromStruct(this.packages[i]);
			this.packages[i] = this.form.toStruct();
		}

		// restore the currently selected element if necessary, otherwise re-clear the form
		if(this.selected != null)
			this.form.fromStruct(this.packages[this.selected]);
		else
			this.form.reset()
		document.getElementById(this.name).value = serialise(this.packages);
	}

	function save_write() {
		// save the currently selected element, if necessary
		if(this.selected != null)
			// save current form to packages
			this.packages[this.selected] = this.form.toStruct();
		document.getElementById(this.name).value = serialise(this.packages);
	}
	
	function onkeydown() {
		switch(event.keyCode) {
			case 40:
				if(this.selected+1 < this.packages.length) {
					this.select(this.selected+1);
					break;
				} else {
					return true;
				}
			case 38:
				if(this.selected > 0) {
					this.select(this.selected-1);
					break;
				} else {
					return true;
				}
			case 33:
				if(this.selected > 0) {
					this.select(Math.max(0,this.selected-10));
					break;
				} else {
					return true;
				}
			case 34:
				if(this.selected+1 < this.packages.length) {
					this.select(Math.min(this.packages.length-1,this.selected+10));
					break;
				} else {
					return true;
				}
			default:
				return true;
		}
		document.getElementById(this.name+'_TABLE_ACTUAL').all.tags("TR")[this.selected+1].scrollIntoView(false);
		event.returnValue = false;
		return false;
	}

	function popupEditSelected(element) {
		if(this.selected==null) return;
		BOSIpopup_popup(element,this.name+'_POPUP',false);
	}

//	function popupEditSelected(element) {
//		if(this.selected==null) return;
//		rc = showModalDialog('/bosi/modalDialog',{document:document,name:this.name},'dialogHeight:600px; dialogWidth:800px; center: yes; status: no');
//	}
}


/******************************************************************************************
* Global stuff
******************************************************************************************/
var BOSILists = new Object();

function saveforms() {
	var key;
	for(key in BOSILists) {
		BOSILists[key].save();
	}
	return true;
}

function initialiseLists() {
	var key, list, name;
	for(key in BOSILists) {
		list = BOSILists[key];
		name = list.name;
		if(!document.getElementById(name+'_TABLE').style.height) { document.getElementById(name+'_TABLE').style.height = document.getElementById(name+'_FORM').offsetHeight < 150 ? 150 : document.getElementById(name+'_FORM').offsetHeight-30; }
		list.render();
		list.select(0);
		list.save();
	}
}

window.attachEvent("onload", initialiseLists);
