/**
 * The "cargo" object is the single global object used by CARGO Library.  It
 * contains utility function for setting up dashboard, and widgets
 * created automatically for and used by the library.
 * @title  CARGO
 * @module cargo
 * @author Jose Manuel Rodriguez CNIO-INB (jmrodriguez@cnio.es)
 * @version 2.0
 */

/**
 * cargo is an abstract base class. It is defined by means of
 * list of widget description in xml format.
 * @constructor
 * @param {XMLDocument} oXMLDocument Description of cargo
 */
function cargo(oXMLDocument)
{
// alert(new XMLSerializer().serializeToString(oXMLDocument));
	var oConstant = new constant();
	oConstant.setXpathNamespaces(oXMLDocument);

	// Check if Cargo server has return exception message
	var sPrefix = oConstant.xmlNamespaces['cargo'].p;
	var oNodeList = oXMLDocument.selectNodes(sPrefix+":cargo/"+sPrefix+":exception/"+sPrefix+":message");
	if (oNodeList.length > 0) { // There were some error
		for(var i=0; i < oNodeList.length; i++){
			document.write("<html><body>"+Sarissa.getText(oNodeList[i])+"</body></html>");
			document.close();
		}
		return null;
	}
	else
	{
		this._createElementContainer(oConstant.divContainerName, this.name, "cargo-panel"); // Create div "cargo" Element

		var sPrefix = oConstant.xmlNamespaces['projectList'].p;
		var sIconProject = Sarissa.getText(oXMLDocument.selectSingleNode("//"+sPrefix+":projectList/"+sPrefix+":project/"+sPrefix+":icon"));

		this.services = this._getServiceObjects(oXMLDocument); // Create service widgets
		this.searches = this._getSearchObjects(oXMLDocument); // Create search widgets

		this.menuBar = new menubar(this.name, this.services); // Initialize menu bar from cargo widgets

		this.dashboard = new dashboard(this.name, 2, sIconProject); // Create dashboard object
		this.inputboard = new inputboard(this.name); // Create searchboard from search widget
		this.searchboard = new searchboard(this.name, this.searches); // Create searchboard from search widget
		this.searchboard.addEventOnSearchTabs(this.searches);
		this.searchboard.showFirstSearchPanel(this.searches);

		this.menuMin = new menumin(this.name); // Initialize menu bar for Minimized widgets (IMPORTANT!! THIS SENTENCES IS CORRECT HERE. YOU HAVE TO CREATE THE HERE THE MENU MIN)

	}
	return this;
};

cargo.prototype = {

/* ATTRIBUTES */

	/**
	* The name of this CARGO
	* @type String
	*/
	name: "cargo",
	/**
	* The unique identifier of this CARGO
	* @type String
	*/
	id: "69",
	/**
	* History of inputs that have been selected. 
	* The input is an object whose keys are ns (namespace) and id (identifier)
	* @history Array
	*/
	history: new Array(),
	/**
	* The dashboard instance
	* @type Object
	*/
	dashboard: null,
	/**
	* The searchboard instance
	* @type Object
	*/
	searchboard: null,
	/**
	* The inputboard instance
	* @type Object
	*/
	inputboard: null,
	/**
	* The list of service objects
	* @type Array
	*/
	services: null,
	/**
	* Widget object that will insert input into cargo
	* @type Object
	*/
	searches: null,
	/**
	* YAHOO MenuBar extended to use events in Cargo
	* @type Object
	*/
	menuBar: null,
	/**
	* YAHOO MenuBar extended to use events in Cargo
	* @type Object
	*/
	menuMin: null,


/* Private METHODS */

	/**
	* Create "div" element
	* @private
	* @param {String} sContainerName Name of "div" container
	*/
	_createElementContainer: function (sDivContainerName, sDivId, sDivClass)
	{
		var oDivElement = document.createElement("div");
		oDivElement.setAttribute("id", sDivId);
		oDivElement.setAttribute("class", sDivClass);
		document.getElementById(sDivContainerName).appendChild(oDivElement);
	},
	/**
	* Create a array (service list) from list of widget description from xml document.
	* @private
	* @param {XMLDocument} oXMLDocument Description of cargo
	* @return {Array} widgets List of widget objects
	*/
	_getServiceObjects: function (oXMLDocument)
	{
		var oConstant = new constant();
		var aServiceList = new Array();
		if(Sarissa.getParseErrorText(oXMLDocument) == Sarissa.PARSED_OK)
		{
			// The document was parsed/loaded just fine, go on
			var sPrefix = oConstant.xmlNamespaces['widgetList'].p;
			var oServiceNode = oXMLDocument.selectNodes("//"+sPrefix+":widgetList/"+sPrefix+":widget");
			for (var iIndex = 0; iIndex < oServiceNode.length; iIndex++)
			{
				var iServiceId = Sarissa.getText(oServiceNode[iIndex].selectSingleNode("@id"));
				aServiceList[iServiceId] = new service(iServiceId, oServiceNode[iIndex]);
			}
		}
		return aServiceList;
	},
	/**
	* Create a array (search list) from list of search description from xml document.
	* @private
	* @param {XMLDocument} oXMLDocument Description of cargo
	* @return {Array} aSearchList List of objects of search widget
	*/
	_getSearchObjects: function (oXMLDocument)
	{
		var oConstant = new constant();
		var aSearchList = new Array();
		if(Sarissa.getParseErrorText(oXMLDocument) == Sarissa.PARSED_OK)
		{
			// The document was parsed/loaded just fine, go on
			var sPrefix = oConstant.xmlNamespaces['searchList'].p;
			var oSearchNode = oXMLDocument.selectNodes("//"+sPrefix+":searchList/"+sPrefix+":search");
			for (var iIndex = 0; iIndex < oSearchNode.length; iIndex++)
			{
				var iSearchId = Sarissa.getText(oSearchNode[iIndex].selectSingleNode("@id"));
				aSearchList[iSearchId] = new search(iSearchId, oSearchNode[iIndex]);
			}
		}
		return aSearchList;
	},

/* Public METHODS */

	/*
	* Destroy the widget given as input
	*/
	destroyWidget: function (type, oScope, silent, signature)
	{
		// this => "widget"
		var aWidgets = cargo.services[this.serviceId].widgets;
		for (var iIndex = 0; iIndex < aWidgets.length; iIndex++)
		{
			if ( (aWidgets[iIndex] != null) && (aWidgets[iIndex].name == this.name) )
			{
				aWidgets[iIndex] = null;
			}
		}
	},
	/*
	* Minimize the widget given as input
	*/
	minimizeWidget: function (type, oScope, silent, signature)
	{
		// this => "widget"
		var iServiceId = this.serviceId;
		var sWidgetName = this.name;
		var sWidgetType = this.type;

		var aTypeSubMenuMin = cargo.menuMin.menu.getSubmenus(); // Get the minimized menus
		var bInserted = false;
		if (aTypeSubMenuMin && (aTypeSubMenuMin.length > 0))
		{
			var iMenuMinIndex = cargo.menuMin._checkIfTypeMiniMenuExists(aTypeSubMenuMin, sWidgetType);
			if (iMenuMinIndex != -1) // the type of widget already exists
			{
				var oMenuItem = new YAHOO.widget.MenuItem(sWidgetName);
				oMenuItem.value = sWidgetName;
				oMenuItem.text = sWidgetType;
				oMenuItem.target = iServiceId;
				oMenuItem.clickEvent.subscribe(cargo.menuMin._onWidgetMenuMinClick, oMenuItem );
	
				aTypeSubMenuMin[iMenuMinIndex].insertItem(oMenuItem, sWidgetType);
	
				bInserted = true;
			}
		}
		if (!bInserted) // the type of widget does not exist yet
		{
			var oMenuItem = new YAHOO.widget.MenuItem(sWidgetName);
			oMenuItem.value = sWidgetName;
			oMenuItem.text = sWidgetType;
			oMenuItem.target = iServiceId;
			oMenuItem.clickEvent.subscribe(cargo.menuMin._onWidgetMenuMinClick, oMenuItem );
			var oTypeMenuMin = {
					id: sWidgetType,
					text: sWidgetType,
					submenu: {
						id: sWidgetType,
						text: sWidgetType,
						itemdata: [ oMenuItem ]
						}
					};
			cargo.menuMin.menu.addItem(oTypeMenuMin, sWidgetType);
		}
		cargo.menuMin.menu.render(document.getElementById(this.sDivMenuMin));
	},
	/**
	* Reload all widgets that are contained in dashboard (they are visible).
	* But not all of them are reloaded; only the widgets (services) that accept
	* the namespace as input.
	* @param {Integer} iGivenWidgetId Widget identifier
	* @param {String} sNamespace Namespace
	* @param {String} sId Id of input
	*/
	runCargoFromInputEntity: function (iGivenWidgetId, sNamespace, sId)
	{
		this.history.push({ ns: sNamespace, id: sId}); // Add the current input into cargo history
		for (var iIndex = 0; iIndex < this.dashboard.widgets.length; iIndex++)
		{
			if (this.dashboard.widgets[iIndex] != null)
			{
				var iServiceId = this.dashboard.widgets[iIndex].serviceId;
				var sWWidgetName = this.dashboard.widgets[iIndex].name;
				var bMinimized = this.dashboard.widgets[iIndex].minimized;
				var bConnected = this.dashboard.widgets[iIndex].connected;
				if ( 	(iGivenWidgetId != iServiceId) &&
					(this.services[iServiceId].acceptGivenNamespace(sNamespace)) &&
					!(bMinimized) &&
					bConnected ) {
					this.services[iServiceId].reloadWidget(this.id, sWWidgetName, sNamespace, sId);
				}
			}
		}
	}

};