/**
 * @author Mark Cassar
 * @version 1.0.2
 * @lastmodified 25/04/07
 */

if (!com) var com = new Object();
if (!com.CS) com.CS = new Object();
if (!com.CS.Forms) com.CS.Forms = new Object();
if (!com.CS.Forms.LinkedMenu) com.CS.Forms.LinkedMenu = new Object();

//REQUIREMENTS
if (!Class) throw new Error("com.CS.Forms.LinkedMenu: Please include Class com.CS.defineClass");
if (!com.CS.General.Listener) throw new Error("com.CS.Forms.LinkedMenu: Please include Class com.CS.General.Listener");
if (!com.CS.Forms.LinkedMenuLevel) throw new Error("com.CS.Forms.LinkedMenu: Please include Class com.CS.Forms.LinkedMenuLevel");
//------------


/**
 * 
 * 
 * This creates a linked menu which has got menus linked to each other.
 * 
 * To use this follow these steps:
 * 
 * 1. Create an instance of the Linked Menu.  The constructor takes n arguments.  The arguments are the list of 
 *    comboboxes / lists.  The order which they are listed will define which level to assign to each list.
 *    IMPORTANT:  You have to set comboxes / lists for the amount of levels you have got.
 * 2. Create a root level object which is an instance of the LinkedMenuLevel Class.  The LinkedMenuLevel takes 3 arguments, which are
 *    text, value and selected.  As for the root level, leave all of them empty / null.
 * 3. To create various sublevels to a section, create another LinkedMenuLevel instance and use LinkedMenuLevel.add(subLevel).
 *    This will add the sublevel to that section.  Each sublevel can have its own sublevels.  The text property of each LinkedMenuLevel
 *    will be shown in the list.  The value is what is retrieved when submitted.
 * 4. After having created the root node, simply call LinkedMenu.initialize(rootNode) and it will do the job for you.
 * 
 */
com.CS.Forms.LinkedMenu = Class({
	name: "LinkedMenu",
	constructor: function() {
		this.lists = new Array();
		for (var i=0;i<arguments.length;i++) {
			var list = arguments[i];
			this.initList(list,i);	
			this.lists.push(arguments[i]);
		}

		
	},
	methods: {
		/**
		 * Initalize the menu with the root level
		 */
		initialize : function(rootLevel) {
			this.populateList(this.lists[0],rootLevel.subLevels)
		},
		/**
		 * Set disabled text when a field is disabled
		 * @param {Object} levelNum Number of level to set disabled text
		 * @param {Object} text Text to display when disabled
		 */
		setDisabledText : function(levelNum,text) {
			var list = this.lists[levelNum];
			list.disabledText = text;
		},
		/**
		 * Set empty text when a level does not contain any other sub levels.  This is different from disabled text.
		 * Disabled text is when you cannot select that section. e.g. Locality (which is there to indicate that you can select a locality
		 * Empty is when the current section does not contain any sub levels
		 * @param {Object} levelNum
		 * @param {Object} text
		 */
		setEmptyText : function(levelNum,text) {
			var list = this.lists[levelNum];
			list.emptyText = text;
		},
		/**
		 * Adds a default item to the level which is ALWAYS populated on top with each list
		 * @param {Object} levelNum
		 * @param {Object} linkedMenuLevel 
		 */
		addDefaultItem : function(levelNum,linkedMenuLevel) {
			var list = this.lists[levelNum];
			list.defaultItems.push(linkedMenuLevel);
		},
		/**
		 * Populate a list
		 * @param {Object} list List to populate
		 * @param {Object} levels The items / sub levels to populate in the list.  This will concatenate the default items with this list
		 */
		populateList : function(list,levels) {
			this.clear(list); //clears the list
			list.disabled = false; //enables it
			levels = list.defaultItems.concat(levels); //Adds the default items to the beginning of the data
			var selectedOption;
			for (var i=0;i<levels.length;i++) {
				var currLevel = levels[i];
				var opt = new Option();
				opt.text = currLevel.text;
				opt.value = currLevel.value;
				opt.selected = currLevel.selected;
				opt.level = currLevel; //set the current linked menu level to the option
				if (!selectedOption || opt.selected) { //Overwrite selected one
					selectedOption = opt;	
				}
				list.options[list.options.length] = opt; //append option
			}
			var selectedSubLevels;
			if (selectedOption.value == "null") {
				this.disableLevelsBelow(list,false);
			}
			else {
				selectedSubLevels = selectedOption.level.subLevels;
				this.populateNextLevel(list,selectedSubLevels)
			}
			
		},
		/**
		 * Disable all the lists under this current list level
		 * @param {Object} list Current list.  All levels underneath this will be disabled
		 * @param {Boolean} isEmpty If the levels are being disabled due to current section being empty, set to true.  Else if the
		 *                  current levels are being disabled since the parent level is not a section in itself, set to false.
		 *                  Defaults to false. 
		 */
		disableLevelsBelow : function(list,isEmpty) {
			var nextIndex = list.levelNum + 1;
			var list;
			
			
			list = this.lists[nextIndex];
			while (list) {
				this.clear(list);
				list.disabled = true;
				nextIndex++;
				if (isEmpty && list.emptyText) {
					list.options[0] = new Option(list.emptyText);
				}
				else if (!isEmpty && list.disabledText) {
						list.options[0] = new Option(list.disabledText);
				}
				list = this.lists[nextIndex];
			}
		},
		/**
		 * Populates the next level from the current list passed with the items passed in items.
		 * @param {Object} currList
		 * @param {Object} items
		 */
		populateNextLevel : function(currList,items) {
			var nextListLevel = currList.levelNum+1;
			if (!items.length) { //Since no items to show as they are empty.. disable the lists under the current level
				this.disableLevelsBelow(currList,true); 
				return false; //exit
			}
			if (this.lists[nextListLevel]) {
				var nextList = this.lists[nextListLevel];
				this.populateList(nextList,items);
			}
			else
			{
				alert("Please create a combo box for level " + (nextListLevel+1));
				throw new Error();
			}
		},
		/**
		 * Clears all items in a list
		 * @param {Object} list List to clear
		 */
		clear : function(list) {
			while (list.length) {
				list.remove(0);
			}
		},
		/**
		 * Initialize a list object
		 * @param {Object} list List object
		 * @param {Object} levelNum Level number of list
		 */
		initList : function(list,levelNum) { //Initialize a list
			list.levelNum = levelNum;
			
			
			
			//list.onchange = list.onkeyup = this.onChangeHandler;
			var scope = this;
			var f = function() {
				
				scope.onChangeHandler(null,list);
			}
			
			com.CS.General.Listener.addEventListener(list,"onchange",f,false)
			
			list.scope = this;
			list.defaultItems = new Array();
		},
		/**
		 * Handler which handles when the user changes the list value.
		 */
		onChangeHandler : function(event,context) {
			//this is passed in as the scope of the list
			var levelNum = this.levelNum;
			
			if (context != null) {
				list = context;
			}
			else {
				list = this;
			}
			alert(list.id)
			
			if (list.selectedIndex == -1) return false; //Nothing is selected (only in case of multiple list)
			var optSelected = list.options[list.selectedIndex];
			var subLevels = optSelected.level.subLevels;
			alert(subLevels);
			if (optSelected.value == "null") {
				list.scope.disableLevelsBelow(list);
			}
			else {
				list.scope.populateNextLevel(list,subLevels);
			}
			
		}
			
	}
});
