//    Licensed Materials - Property of IBM
//
//    IBM Cognos Products: cogadmin
//
//    (C) Copyright IBM Corp. 2005, 2011
//
//    US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
//
// Copyright (C) 2008 Cognos ULC, an IBM Company. All rights reserved.
// Cognos (R) is a trademark of Cognos ULC, (formerly Cognos Incorporated).

//----------------------------------------------------------

com.cognos.admin.ObjectFactory("com.cognos.admin.extension"); 
/* This is a implementation of the extensive event handler. The impl need to have a method named "doAction" to 
 * work as a mapping.
 * @param: env, context of the behaviour controller framework.
 *
 */ 

com.cognos.admin.extension.Privileges = function (env) {

	this.env = env;
	this.meta = this.env.context.getPublicVariables("meta");
	this.state = this.env.state;
	this.privileges  = this.state.getState("privileges");
	this.fragment = this.env.fragment;
	this.tools = com.cognos.admin.util.Tools;

	if (this.meta && this.privileges){
		this.populatePrivileges();
	}
	this.isDirty = false;
};

com.cognos.admin.extension.Privileges.VERSION = "0.1.0";
com.cognos.admin.extension.Privileges.GRANT_ICON_NAME = "g";
com.cognos.admin.extension.Privileges.DENY_ICON_NAME = "deny";
com.cognos.admin.extension.Privileges.MIXED_ICON_NAME = "mixed";
com.cognos.admin.extension.Privileges.DISPLAY_ICON_NAME = "grant";
com.cognos.admin.extension.Privileges.NONE_ICON_NAME = "none";
com.cognos.admin.extension.Privileges.prototype = {
	/*
	 * init the privileges section, if any missing privilege, fill the gap with unset privilege
	 */
	populatePrivileges : function () {
		for (var i=0; i<this.privileges.length; i++){
			var nameList = this.getItemList("name");
			if (this.privileges[i]["privilege"]){
				for (var j=0; j<this.privileges[i]["privilege"].length; j++){
					_F_Array.remove(nameList,this.privileges[i]["privilege"][j].name);
				}
			} else {
				this.privileges[i]["privilege"] = [];
			}
			this.privileges[i]["privilege"] = this.privileges[i]["privilege"].concat(this.getEmptyPrivilegeItem(nameList));
		}
	},
	
	getEmptyPrivilegeItem : function (name) {
		var ret = [];
		for (var i=0; i<name.length; i++){
			var obj = {};
			obj.name = name[i];
			obj.flag = "";
			ret.push(obj);
		}
		return ret;
	},
	
	/* 
	 * if lists is empty, execute the func anyway,
	 * if lists is not empty, and the member is found in priviliges array, execute the func.
	 */
	walkPrivileges : function (func,level,lists) {
		var ret = [];
		if (this.privileges){
			var level = level || 'privilege';
			
			for (var i=0; i<this.privileges.length; i++){
				if (lists && _F_Array.indexOf(lists,this.privileges[i]["key"]) == -1)
					continue;
				
				var key = this.privileges[i]["key"];
				if (level == 'key'){
					ret.push(func(key,i));
					
				} else {
					if (this.privileges[i]["privilege"]) {
						for (var j=0; j<this.privileges[i]["privilege"].length; j++){
							var current = this.privileges[i]["privilege"][j];
							
							if (level == 'privilege'){
								if (typeof func == "function"){
									ret.push(func(key,current));
								}
							} 
						}
					}
				}
			}
		}
		return ret;
	},
	
	
	getNumbers : function () {
		var nums = [];
		
		function getNum (key,current){
			if (!nums[current.name]){
				nums[current.name]={};
				nums[current.name][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y] = 0;
				nums[current.name][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N] = 0;
			}
			
			if (current.flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y){
				nums[current.name][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y]++;
			} else if (current.flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N){
				nums[current.name][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N]++;
			}
		};
		this.walkPrivileges(getNum,'privilege',this.lists);
		
		return nums;
	},
	
	show : function (tag,param){
		var fragId = this.fragment.id;
		var names = this.getItemList("name");
		var nums = this.getNumbers();
		
		for (var k=0; k<names.length; k++){
			var nId = this.tools.getNormalizedId (names[k],fragId);
			var elt = $(nId + "_" + com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y);
			var partner = $(nId + "_" + com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N);	
			if (elt && partner){
				var cb = new com.cognos.admin.util.Tools.ThreeCheckbox(elt,fragId);
				var cbp = new com.cognos.admin.util.Tools.ThreeCheckbox(partner,fragId);
				
				if (this.lists.length == 0){
					cb.setState(com.cognos.admin.util.Tools.ThreeCheckbox.DISABLED);
					cbp.setState(com.cognos.admin.util.Tools.ThreeCheckbox.DISABLED);
				} else {
					cb.setState(com.cognos.admin.util.Tools.ThreeCheckbox.UNCHECKED);
					cbp.setState(com.cognos.admin.util.Tools.ThreeCheckbox.UNCHECKED);
					
					if (nums[names[k]]){
						if (nums[names[k]][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y] == this.lists.length){
							cb.setState(com.cognos.admin.util.Tools.ThreeCheckbox.CHECKED);
						} else if (nums[names[k]][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N] == this.lists.length){
							cbp.setState(com.cognos.admin.util.Tools.ThreeCheckbox.CHECKED);
						} else {
							if (nums[names[k]][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y] > 0){
								cb.setState(com.cognos.admin.util.Tools.ThreeCheckbox.MIXED);
							}
							if (nums[names[k]][com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N] > 0){
								cbp.setState(com.cognos.admin.util.Tools.ThreeCheckbox.MIXED);
							}
						}
					}
				}
			}
		}
	},
	/*
	*  the payload will trace the route from root till you find the destination(s), and return all the items along this route.
	*/
	walkItems : function (func,items,lists,payload,scope){
		var payl = [];
		if (items){
			for (var j=0; j<items.length; j++){
				if ((!scope || (items[j]["scope"] == scope)) && (!payload)){
					payl[j]=items[j];
				} else {
					payl[j]=payload;
				}
				
				if ((!scope || (items[j]["scope"] == scope)) && (!lists || (lists.length == 0) || (_F_Array.indexOf(lists,items[j]["name"]) != -1))){
					if (typeof func == "function"){
						func([payl[j]]);
					}
				} else if (items[j].meta){
					this.walkItems (func,items[j].meta,lists,payl[j],scope);
				}
			}
		}
	},
	
	getItemList : function (name,lists,scope) {
		var ret = [];
		
		if (this.meta){
			var items = this.meta;
			
			function getList (item){
				if (item){
					for (var i=0; i<item.length; i++){
						if (!name){
							ret.push (item[i]);
						} else {
							ret.push (item[i][name]);
						}
						if (item[i].meta){
							getList(item[i].meta);
						}
					}
				}
			};
	
			this.walkItems(getList,items,lists,"",scope);
		}
		return ret;
	},
	/*
	*  lookfor: {key:xxx, value:xxx}
	*/
	lookupItem : function (lookfor,name,lists,scope) {
		var ret = "";
		if (this.meta){
			var items = this.meta;
			function getItem (item){
				if (item){
					for (var i=0; i<item.length; i++){
						if (item[i][lookfor.key] == lookfor.value){
							ret = item[i][name];
						}
						if (item[i].meta){
							getItem(item[i].meta);
						}
					}
				}
			};
	
			this.walkItems(getItem,items,lists,"",scope);
		}
		return ret;
	},
	
	update : function (tag){
		if (!this.lists || this.lists.length == 0) return false;
		
		var fragId = this.fragment.id;
		var nId = this.tools.getNormalizedId(tag.id,fragId,true);
		var name = nId.substring(0,(nId.length-2));
		var flag = this.tools.getFlag(nId);
		var names = this.getItemList("name",[name]);
		var fullNames = this.getItemList("name","","package");
		
		if (name == "toggle_all"){
			this.updateEx(fullNames,flag,name,true);
			if (partner = this.tools.getPartner(tag,com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y,com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N)){
				if (tag.checked) partner.checked = !tag.checked;
			}
		} else {
			//privilige specific toggle rules #1 deny check toggler
			if (_F_Array.indexOf(names,name) == 0 && flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N && tag.getAttribute("state") != com.cognos.admin.util.Tools.ThreeCheckbox.CHECKED){
				this.updateEx(names,flag,names[0],true);
			} else {
				this.updateEx([name],flag,names[0],false);
			} 
		}
	},
	
	updateEx : function (names,flag,toggleName,isToggled) {
		var self = this;
		var fragId = this.fragment.id;
		
		for (var i = 0; i < names.length; i++){
			var currentElt = $(this.tools.getNormalizedId(names[i] + "_" + flag,fragId));
			var isSelf = (names[i] == toggleName);
			var toggled = isToggled && !isSelf;
			this.updateRHS(names[i],flag,toggleName,toggled);

			function updateFlag (key,current){
				var isUpdated = false;
				if (current.name == names[i]){
					current.flag = (currentElt.getAttribute("state") == com.cognos.admin.util.Tools.ThreeCheckbox.CHECKED) ? flag : "";
					isUpdated = true;
				}
				//privilige specific toggle rules #2 deselect deny toggler, when children's stage changed
				if (!toggled && !isSelf && current.name == toggleName && current.flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N && !(flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N && currentElt.getAttribute("state") == com.cognos.admin.util.Tools.ThreeCheckbox.CHECKED)){
					current.flag = "";
					isUpdated = true;
				}
				if (isUpdated){
					self.updateLHS(key,names[i]);
				}
			};
			this.walkPrivileges (updateFlag,'privilege',this.lists);
		}
	},
	
	updateRHS : function (name,flag,togglerName,isToggled) {
		var fragId = this.fragment.id;
		var currentElt = $(this.tools.getNormalizedId(name + "_" + flag,fragId));
		var toggler = $(this.tools.getNormalizedId(togglerName + "_" + flag,fragId));
		var cb = new this.tools.ThreeCheckbox(currentElt,fragId,toggler);
		cb.setIsToggled(isToggled);
		cb.click();
	},
	
	updateLHS : function (key,name){
		var self = this;
		var fragId = this.fragment.id;
		var iconList = this.getItemList("icon",[name]);
		var nameList = this.getItemList("name",[name]);
		var scopeList = this.getItemList("scope",[name]);
		var flagList = [];
		var altText = "";
		var elt = $(fragId + "_" + key + "_" + nameList[0]);
		
		if (elt) {
			function getFlag (insideKey,current){
				if (key == insideKey && _F_Array.indexOf(nameList,current.name) > -1 && scopeList[_F_Array.indexOf(nameList,current.name)] == 'package'){
					flagList.push(current.flag);
					altText += self.getAltText(current.name,current.flag);
				}
			}
			this.walkPrivileges (getFlag,'privilege');
			elt.src = com.cognos.admin.WEBCONTENT + this.switchIcon(iconList[0],this.adjustFlag(flagList));
			dojo.attr(elt,"alt",altText);
			this.setIsDirty(true);
		}
	},
	
	getAltText: function(name,flag){
		var returnText = "";
		var caption = this.lookupItem({"key":"name","value":name},"caption",[name]);
		if (flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y){
			returnText = ADM.formatString(ADM.CAP.IDS_ADMNEW_CAP_GRANT,[caption+" "])+",";
		} else if (flag == com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N){
			returnText = ADM.formatString(ADM.CAP.IDS_ADMNEW_CAP_DENY,[caption+" "])+",";
		}
		return returnText;
	},
	
	switchIcon : function (initSrc,flag){
		if (!initSrc) throw new Error ("Cogadmin/Privilege: Icon's initial src cannot be empty.");
		
		var src = initSrc;
		var regOrigIcon = new RegExp("_" + com.cognos.admin.extension.Privileges.DISPLAY_ICON_NAME + ".gif","i");
		
		switch (flag){
			case com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y:
				src = src.replace(regOrigIcon, "_" + com.cognos.admin.extension.Privileges.GRANT_ICON_NAME + ".gif");
				break;
			case com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N:
				src = src.replace(regOrigIcon,"_" + com.cognos.admin.extension.Privileges.DENY_ICON_NAME + ".gif");
				break;
			case com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_M:
				src = src.replace(regOrigIcon,"_" + com.cognos.admin.extension.Privileges.MIXED_ICON_NAME + ".gif");
				break;
			default:
				var reg = new RegExp("access_(.)*_" + com.cognos.admin.extension.Privileges.DISPLAY_ICON_NAME + ".gif","i");
				src = src.replace(reg,"access_" + com.cognos.admin.extension.Privileges.NONE_ICON_NAME + ".gif"); 
		}
		
		return src;
	},
	
	getIsDirty : function () {return this.isDirty;},
	
	setIsDirty : function (flag) {
		this.isDirty = flag;
		this.state.setState("isDirty",this.isDirty);
	},
	
	adjustFlag : function (flags){
		var flag;
		if (flags) {
			for (var i=0; i<flags.length; i++){
				if (i==0){
					flag = flags[0];
				} else if (flags[i] != flags[i-1]){
					flag = com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_M;
					break;
				}
			}
		}
		return flag;
	},
	
	addEntries : function (entries){
		if (entries) {
			var isExist = false;
			for (var k=0; k<entries.length; k++){
				var isNew = true;
				function updateEntry (key,position){
					if (entries[k].key == key){
						isExist = true;
						isNew = false;
					}
				};
				this.walkPrivileges(updateEntry,'key');
				if (isNew){
					this.privileges.push(entries[k]);
				}
			}
			
			if (isExist){
				alert(ADM.CAP.IDS_ADMNEW_CAP_ALREADY_EXIST);
			}
			
			this.fragment.raiseEvent("fragment.refresh");
		}
	},
	
	getUnsetEntries : function (){
		var isUnset = [];
		var self = this;
		function checkUnset(key,position){
			isUnset[position] = true;
			if (privilege = self.privileges[position].privilege){
				for (var i=0; i<privilege.length; i++){
					if (privilege[i].flag){
						isUnset[position] = false;
					}
				}
			} 
		}
		this.walkPrivileges(checkUnset,"key");
		if (com.cognos.admin.config.debug && _F_Array.indexOf(isUnset,true) > -1){
			_F_log("D","Unset Entries:");
			_F_log("D",this.privileges[_F_Array.indexOf(isUnset,true)].key)
		}
		return _F_Array.indexOf(isUnset,true) > -1;
	},
	
	removeUnsetEntries : function (){
		this.lists = [];
		var self = this;
		function checkUnset(key,position){
			if (privilege = self.privileges[position].privilege){
				var isUnset = true;
				for (var i=0; i<privilege.length; i++){
					if (privilege[i].flag){
						isUnset = false;
						break;
					}
				}
				if (isUnset) {
					self.lists[self.lists.length]=self.privileges[position].key;
				}
			} 
		}
		this.walkPrivileges(checkUnset,"key");

		//remove 
		var positions = [];
		function removeEntry (key,position){
			positions.push (position);
		}
		
		this.walkPrivileges(removeEntry,'key',this.lists);
		function numOrder (a,b){
			return b-a;
		}
		positions.sort(numOrder);
		for (var i=0; i<positions.length; i++){
			_F_Array.removeAt(this.privileges,positions[i]);
		}
		
	},
	
	removeEntries : function (){
		if (this.lists){
			var positions = [];
			function removeEntry (key,position){
				positions.push (position);
			}
			
			this.walkPrivileges(removeEntry,'key',this.lists);
			function numOrder (a,b){
				return b-a;
			}
			positions.sort(numOrder);
			for (var i=0; i<positions.length; i++){
				_F_Array.removeAt(this.privileges,positions[i]);
			}
			//remove the deleted items from the state "grpActionRows"
			while (this.lists.length>0){
				this.state.removeState(com.cognos.admin.util.ClientState.GROUP_ACTION_ROWS,this.lists[0],true);
			}
			this.fragment.raiseEvent("fragment.refresh");
		}
	},


	getTooltipParam : function (tag,currentName){
		if (tag.src.indexOf("access_none.gif") != -1) return;
		
		var grant = [];
		var deny = [];
		var blank = [];
		var ret = [];
		var list = this.getItemList("",[currentName]);
		var currentKey = this.tools.getKey(tag);
		
		for (var i=0; i<list.length; i++){
			var name = list[i].name;
			var self = this;
			
			function getP(key,current) {
				if (currentKey == key && current.name == name) {
					var obj = {};
					obj.text = list[i].caption;
					obj.image = self.switchIcon(list[i].icon,current.flag);
					
					if (list[i].scope == 'package') {
						switch (current.flag){
							case com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_Y:
								obj.caption = ADM.formatString(ADM.CAP.IDS_ADMNEW_CAP_GRANT,[""]);
								grant.push(obj);
								break;
							case com.cognos.admin.util.Tools.ThreeCheckbox.FLAG_N:
								obj.caption = ADM.formatString(ADM.CAP.IDS_ADMNEW_CAP_DENY,[""]);
								deny.push(obj);
								break;
							default:
								obj.caption = ADM.CAP.IDS_ADMNEW_CAP_NOT_SET;
								//in tooltips, we have to display the grant icon for NOT SET.
								obj.image = list[i].icon;
								blank.push(obj);
						}
					}
				}
			};
			
			this.walkPrivileges(getP,'privilege');
		}
		
		ret = ret.concat(grant,deny,blank);
		if (com.cognos.admin.config.debug){
			_F_log ("D","Get tool tip for privileges:");
			_F_log ("D",ret);
		}
		return ret;
	},
	
	/* behaviour controller framework interface implementation
	 * @param: e, the event trigger this action
	 * @param: tag, the target of the event
	 * @param: param, "cogParam" passing from the markup.
	 */
	doAction : function (e,tag,param) {
	
		this.lists = this.state.getState("grpActionRows",true);

		switch (param.actionName){
			case "update":
				return this.update(tag);
			case "removeEntries":
				return this.removeEntries();
			case "show":
				return this.show(tag,param);
			case "getTooltipParam":
				return this.getTooltipParam(tag,param.name);
			default:
				throw new Error ("Unknown action name, check your cogParam -> actionName.");
				return false; //not handled here
		}
	}
};