//------------------------------------------------------------------
// Cygnet Web Controls Toolkit
// editingmodel library
//
// ©2005 Cygnet Solutions Ltd
//
//------------------------------------------------------------------

var forms = new Array();
function form(el){
	while(el){
		if (forms[el.id]) return forms[el.id];
		el = el.parentNode;
	}
	return null;
}

var EditableArray = Class.create();
EditableArray.prototype = {
	initialize: function(containerid, serverside, addbuttonelement) {
		this.containerid = containerid;
		this.serverside = serverside;
		this.addbuttonelement = (addbuttonelement || containerid+":add");
		if (containerid) this.initializeEvents(containerid);
	},
	
	initializeEvents: function(el){
		AddEventListener($(el), "keypress", function(evt){
			var key = (evt.keyCode || evt.which);
			if (key == 13) { // [ENTER] or [RETURN]
				//form($(el)).save(el); // Would like to submit the (sub)form here.
				if (evt.target.tagName.toUpperCase() != "TEXTAREA"){ // Insert a newline for TEXTAREA, othewise...
					evt.stopPropagation();
					evt.preventDefault(); // ...cancel the event (which would otherwise cause a top-level form submission).
				}
			}
		}, false);
	},
	

	edit: function(elementid, dbid){
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: elementid, id: dbid, editmode: 1}, 
			null,
			function(req){
				replaceRow(elementid, req);
			}
		);
	},

	editnew: function(){
		var me = this;
		var addrow = this.addbuttonelement;
		Ajax.call(
			this.serverside, uriParameters({ContainerID: this.containerid, editmode: 1}) + "&" + Form.serialize(addrow), 
			null,
			function(req){
			var id = insertRowBefore(addrow, req);
				me.newElementAdded( id );
			}
		);
	},

	save: function(elementid, dbid, newelementid){
		var wasNew = (dbid == null);
		var me = this;
		if (newelementid == null) newelementid = wasNew ? '' : elementid;
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: newelementid, id: (dbid || ''), editmode: 1},
			Form.serialize(elementid),
			function(req, saved){
				replaceRow(elementid, req);
				if (saved) 
					me.noNewElement(elementid);
			}
		);
	},

	reset: function(elementid, dbid, newelementid){
		var wasNew = (elementid == this.newelement)//(dbid == null);
		var me = this;
		if (newelementid == null) newelementid = $(elementid).id;
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: newelementid, id: (dbid || ''), editmode: 0},
			null,
			function(req){
				replaceRow(elementid, req);
				me.noNewElement(elementid);
			}
		);
	},
	
	remove: function(elementid, dbid){
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: elementid, id: dbid},
			Form.serialize(elementid)+"&delete=1", 
			function(req){ replaceRow(elementid, req); }
		);
	},
	
	newElementAdded: function(id){
		if (id != null){
			Element.hide(this.addbuttonelement);
			this.newelement = id;
		}
	},
	noNewElement: function(id){
		if (id != null && id == this.newelement){
			delete this.newelement;
			new Effect.Appear(this.addbuttonelement);
		}
	}

}
EditableArray.register = function(containerid, serverside, addbuttonelement){
	forms[containerid] = new EditableArray(containerid, serverside, addbuttonelement);
}

var ProxiedEntity = Class.create();
ProxiedEntity.prototype = (new EditableArray()).extend({
	initialize: function(proxiedelementid, serverside) {
		this.containerid = proxiedelementid;
		this.serverside = serverside;
		if (proxiedelementid) this.initializeEvents(proxiedelementid);
	},
	
	save: function(elementid, dbid){
		var wasNew = (dbid == null);
		var p = $(this.containerid);
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: elementid, id: (dbid || ''), editmode: 1},
			Form.serialize(elementid),
			function(req, saved){
				replaceRow(elementid, req);
				if (saved && wasNew){
					dbid = req.getResponseHeader("X-Entity-Key");
					form(p.parentNode).reset(p.id, dbid, '');
				}
			}
		);
	},

	reset: function(elementid, dbid){
		var wasNew = (dbid == null);
		if (wasNew) {
			form($(this.containerid).parentNode).reset(this.containerid);
		}else{
			Ajax.call(
				this.serverside, {ContainerID: this.containerid, ElementID: elementid, id: (dbid || ''), editmode: 0},
				null,
				function(req){
					replaceRow(elementid, req);
				}
			);
		}
	},

	remove: function(elementid, dbid){
		var p = this.containerid;
		Ajax.call(
			this.serverside, {ContainerID: this.containerid, ElementID: elementid, id: dbid},
			Form.serialize(elementid)+"&delete=1", 
			function(req, removed){
				if (removed) {
					replaceRow(p, req);
				}else {
					replaceRow(elementid, req);
				}			
			}
		);
	}
	
});
ProxiedEntity.register = function(containerid, serverside, addbuttonelement){
	forms[containerid] = new ProxiedEntity(containerid, serverside, addbuttonelement);
}

var HTMLForm = Class.create();
HTMLForm.prototype = (new EditableArray()).extend({

	initialize: function(formelementid, serverside, cancelpage){
		this.formelementid = formelementid;
		this.serverside = serverside;
		this.cancelpage = cancelpage;
	},
	
	reset: function(elementid, dbid){
		if (dbid != null){
			window.location = uriAddParameters(this.serverside, {id: dbid});
		}else{
			window.location = this.cancelpage;
		}
	}

});
HTMLForm.register = function(formelementid, serverside, cancelpage){
	forms[formelementid] = new HTMLForm(formelementid, serverside, cancelpage);
}


function insertRowBefore(ns, req){ // Returns element ID if it exists
	var el = $(ns);
	
	if (req.responseText == '') {
		// Do nothing
		return null;
	
	}else if (req.responseXML){
		var newTR = cloneXML(req.responseXML.documentElement, document);
		el.parentNode.insertBefore(newTR, el);
		new Effect.Appear(newTR);
		return newTR.id;
		
	}else {
		throw "Fault: no responseText and no responseXML";
	}
}

function replaceRow(ns, req){ // Returns element ID if it exists
	var el = $(ns);
	
	if (req.responseText == '') {
		el.parentNode.removeChild(el);
		return null;
	
	}else if (req.responseXML){
		var newTR = cloneXML(req.responseXML.documentElement, document);
		el.parentNode.replaceChild(newTR, el);
		return newTR.id;
		
	}else {
		throw "Fault: no responseText and no responseXML";
	}
}
