/******************************************************************************
* gshpAjaxBasket.js
*******************************************************************************

*******************************************************************************
*                                                                             *
* Copyright 2008
*                                                                             *
******************************************************************************/

/* gshp.basket singleton */
var gshp;
if (YAHOO.lang.isUndefined(gshp))
	gshp = {};
gshp.basket = function() {
	/* private member */
	var genericErrorMsg = "Un incident technique a empéché de mener à bien cette opération";
	var items = null;
	var loadId = null;
	var changeId = null;
	var events = {
		"ready":new YAHOO.util.CustomEvent("ready",null,false,YAHOO.util.CustomEvent.FLAT),
		"busyStart":new YAHOO.util.CustomEvent("busyStart",null,false,YAHOO.util.CustomEvent.FLAT),
		"busyEnd":new YAHOO.util.CustomEvent("busyEnd",null,false,YAHOO.util.CustomEvent.FLAT),
		"change":new YAHOO.util.CustomEvent("change",null,false,YAHOO.util.CustomEvent.FLAT),
		"actionFail":new YAHOO.util.CustomEvent("actionFail",null,false,YAHOO.util.CustomEvent.FLAT),
		"actionSuccess":new YAHOO.util.CustomEvent("actionSuccess",null,false,YAHOO.util.CustomEvent.FLAT)
	};
	events.ready.fireOnce=true;
	function cancelLoad()
	{
		if (loadId != null)
		{
			YAHOO.log("cancelLoad","info","gshp.basket");
			YAHOO.util.Connect.abort(loadId,null,false);
			loadId = null;
		}
	}
	function load()
	{
		YAHOO.log("load","info","gshp.basket");
		cancelLoad();
		loadId = YAHOO.util.Connect.asyncRequest('GET',
			gshpAjaxBasketURL + ((gshpAjaxBasketURL.indexOf('?') == -1)?'?':'&') + "f=getAll", {
			success:onLoaded,
			failure: onAjaxFailure
			},null);
	}	
	isoYUILoader.onReady(function () {
		YAHOO.util.Event.addListener(window, "beforeunload", cancelLoad);  
		YAHOO.util.Event.addListener(window, "unload", cancelLoad); 
		load();
	});
	function onAjaxFailure(response)
	{
		YAHOO.log("onAjaxFailure","error","gshp.basket");
		if (loadId != null && response.tId == loadId.tId)
			loadId = null;
		if (changeId != null && response.tId == changeId.tId)
		{
			changeId = null;
			events.busyEnd.fire();
			events.actionFail.fire("Internal error");
		}
		YAHOO.log("status : "+response.status+" "+response.statusText,"info","gshp.basket");
	}
	function onLoaded(response)
	{
		YAHOO.log("onLoaded","info","gshp.basket");
		loadId = null;	
		var bFirstLoad = items == null;
		items = [];			
		ajax.util.readResponse(response, {
			gshp: {
				item:function(e) {
					items[items.length] = ajax.util.parseDataXMLElement(e);
					return true;
				}
			}},
			null,
			function () {
				if (bFirstLoad)
					events.ready.fire();
				else
					events.change.fire();
			}
		);		
	}
	function onActionSuccess(response, options)
	{
		YAHOO.log("onActionSuccess","info","gshp.basket");
		changeId = null;
		events.busyEnd.fire();
		var ok = true;
		var errMsg = null;		
		var root = response.responseXML.documentElement;
		if (root.nodeName != "root" || root.getAttribute("namespace") != "ajax")
		{
			YAHOO.log("Invalid root element : <"+root.getAttribute("namespace")+":"+root.nodeName+">","error","gshp.basket");
			ok = false;
			errMsg = genericErrorMsg;
		}
		for (var i=0;i<root.childNodes.length;i++)
		{
			var xmlElement = root.childNodes[i];
			if (xmlElement.nodeType != 1) continue;
			switch (xmlElement.getAttribute("namespace"))
			{
			case "ajax":
				switch (xmlElement.nodeName)
				{
				case "trace":
					var textNode = xmlElement.firstChild;
					YAHOO.log(textNode?textNode.nodeValue:"","info","gshp.basket");
					break;
				case "error":
					var textNode = xmlElement.firstChild;
					YAHOO.log((textNode?textNode.nodeValue:""),"error","gshp.basket");
					ok = false;
					errMsg = genericErrorMsg;					
					break;
				default:
					var msg = "unknown element <ajax:"+xmlElement.nodeName+">";
					YAHOO.log(msg,"warn","gshp.basket");
					ok = false;
					errMsg = genericErrorMsg;
					break;					
				}
				break;
			case "gshp":
				switch (xmlElement.nodeName)
				{
				case "error":
					var textNode = xmlElement.firstChild;
					YAHOO.log((textNode?textNode.nodeValue:""),"error","gshp.basket");
					ok = false;
					errMsg = (textNode?textNode.nodeValue:"");
					break;
				case "warning":
					var textNode = xmlElement.firstChild;
					YAHOO.log((textNode?textNode.nodeValue:""),"warn","gshp.basket");
					ok = false;
					errMsg = (textNode?textNode.nodeValue:"");
					break;
				case "success":
					YAHOO.log("success","info","gshp.basket");
					break;
				default:
					var msg = "unknown element <gshp:"+xmlElement.nodeName+">";
					YAHOO.log(msg,"warn","gshp.basket");
					ok = false;
					errMsg = genericErrorMsg;
					break;				
				}
				break;
			default:
				var msg = "unknown namespace '"+xmlElement.getAttribute("namespace")+"'";
				YAHOO.log(msg,"warn","gshp.basket");
				ok = false;
				errMsg = genericErrorMsg;
				break;
			}
		}
		load();
		if (ok)
			events.actionSuccess.fire();
		else
			events.actionFail.fire(errMsg);
	}
	function runAction(params)
	{
		var p = [];
		for (var n in params)
			p.push(n+"="+encodeURIComponent(params[n]));
		YAHOO.log("runAction : "+p.join(", "),"info","gshp.basket");
		if (gshp.basket.isBusy())
		{
			YAHOO.log("busy : action canceled !","warn","gshp.basket");
			return false;	/* action en cours */
		}
		changeId = YAHOO.util.Connect.asyncRequest('GET',
			gshpAjaxBasketURL + ((gshpAjaxBasketURL.indexOf('?') == -1)?'?':'&') + p.join("&"), {
			success:onActionSuccess,
			failure:onAjaxFailure
			},null);
		events.busyStart.fire(params);
		return true;
	}	
	return {
		// public methods
		isReady: function()
		{
			return items!=null;
		},
		isBusy: function()
		{
			return changeId!=null;
		},
		isEmpty: function()
		{
			if (!this.isReady())
				throw new Error("gshp.basket not ready");
			return items.length==0;
		},
		eachItem: function (fn, scope)
		{
			if (!this.isReady())
				throw new Error("gshp.basket not ready");
			YAHOO.util.Dom.batch(items, fn, scope, true);
		},
		deleteAll: function()
		{
			return runAction({"f": "deleteAll"});
		},
		deleteItem: function(oid)
		{
			return runAction({"f": "deleteItem", "item":oid});
		},
		changeItemQuantity: function(oid, quantity)
		{
			return runAction({"f": "changeItemQuantity", "item":oid, "quantity":quantity});
		},
		addReference: function(oid, quantity)
		{
			return runAction({"f": "addReference", "reference":oid, "quantity":quantity});
		},		
		addPack: function(oid, quantity, referencesDescr)
		{
			return runAction({"f": "addPack", "pack":oid, "quantity":quantity, "referencesDescr":referencesDescr});
		},
		on: function(name, fn, scope)
		{
			var event = events[name];
			if (event == null)
				throw new Error("event '"+name+"' not defined on gshp.basket");
			event.subscribe(fn,scope);
		},
		un: function(name, fn, scope)
		{
			var event = events[name];
			if (event == null)
				throw new Error("event '"+name+"' not defined on gshp.basket");
			event.unsubscribe(fn,scope);
		}
	};
}();
