/*
 *+------------------------------------------------------------------------+
 *| Licensed Materials - Property of IBM
 *| IBM Cognos Products: Viewer
 *| (C) Copyright IBM Corp. 2001, 2013
 *|
 *| US Government Users Restricted Rights - Use, duplication or
 *| disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
 *|
 *+------------------------------------------------------------------------+
 */
function CognosViewerSort( event, oCV ) {
	this.m_oCV = oCV;
	if( event )
	{
		this.m_oEvent = event;
		this.m_oNode = getCrossBrowserNode(event, true);
	}
}
CognosViewerSort.prototype.setNode = function( node )
{
	this.m_oNode = node;
};
CognosViewerSort.prototype.getNode = function()
{
	return this.m_oNode;
};
/*
 * Checks to see if this is a sort action
 */
CognosViewerSort.prototype.isSort = function() {
	if(this.m_oNode && this.m_oNode.nodeName == 'IMG' && (this.m_oNode.id).indexOf('sortimg') >= 0 )
	{
		return true;
	}
	else
	{
		return false;
	}
};
CognosViewerSort.prototype.execute = function() {
	var selectionController = getCognosViewerSCObjectRef(this.m_oCV.getId());
	selectionController.selectSingleDomNode(this.m_oNode.parentNode);
	var sortAction = this.getSortAction();
	sortAction.setCognosViewer(this.m_oCV);
	sortAction.execute();
	if (window.gViewerLogger) {
		window.gViewerLogger.addContextInfo(selectionController);
	}
};
/*
 * The order of sort is ascending, descending and none.
 * Figure out what the current sort should be based on previous sort order.
 * Eg. if previous sort order is ascending, then next sort order should be descending.
 */
CognosViewerSort.prototype.getSortAction = function() {
	var sortAction = this.m_oCV.getAction("Sort");
	var sortOrder = this.m_oNode.getAttribute( 'sortOrder' );
	if( sortOrder.indexOf('nosort') != -1 )
	{
		sortAction.setRequestParms({order:"ascending", type:"value"});
	}
	else if ( sortOrder.indexOf('ascending') != -1 )
	{
		sortAction.setRequestParms({order:"descending", type:"value"});
	}
	else if( sortOrder.indexOf('descending') != -1)
	{
		sortAction.setRequestParms({order:"none", type:"value"});
	}
	return sortAction;
};
function SortAction()
{
	this.m_sAction = "Sort";
	this.m_sortOrder = "none";
	this.m_sortType = "";
	this.m_sItem = "";
	this.m_sId="";
}
SortAction.prototype = new ModifyReportAction();
SortAction.prototype.doExecute = function() {
	//Abort execute iff existing sort is none and new sort is none
	if (this.m_sortOrder === "none") {
		//Allow the execute if there is no container - i.e. no field is selected.
		//This occurs when the user cancels a sort from the infobar.
		if (this.getContainerId(this.m_oCV.getSelectionController())) {
			var currentSort = this.getCurrentSortFromSelection();
			if (this.m_sortType === "value" && currentSort.indexOf("sortByValue") === -1) {
				return false;
			} else if (this.m_sortType === "label" && currentSort.indexOf("sortByLabel") === -1) {
				return false;
			}
		}
	}
	return true;
};
SortAction.prototype.execute = function() {
	if(this.doExecute()) {
		ModifyReportAction.prototype.execute.call(this);
	}
};
SortAction.prototype.getUndoHint = function()
{
	if (this.m_sortOrder == "none")	{
		return RV_RES.IDS_JS_DONT_SORT;
	}
	else {
		return RV_RES.IDS_JS_SORT;
	}
};
SortAction.prototype.setRequestParms = function(payload)
{
	this.m_sortOrder = payload.order;
	this.m_sortType = payload.type;
	if (payload.id!=null && typeof payload.id != "undefined") {
		this.m_sId   = payload.id;
	}
	if (payload.item!=null && typeof payload.item != "undefined") {
		this.m_sItem = payload.item;
	}
};
SortAction.prototype.addActionContextAdditionalParms = function()
{
	var selectionController = this.m_oCV.getSelectionController();
	var parms = "" + this.m_sortOrder + "";
	if(this.m_sortType == "label")
	{
		parms += "";
	}
	if (this.getContainerId(selectionController)=="" && this.m_sId != null && typeof this.m_sId != "undefined" && this.m_sId != "") {
		parms+= ("" + xml_encode(this.m_sId) + "");
	}
	if (this.m_sItem != null && typeof this.m_sItem != "undefined" && this.m_sItem!="") {
		parms+= ("- " + xml_encode(this.m_sItem) + "
 ");
	}
	parms += this.addClientContextData(/*maxValuesPerRDI*/3);
	
	parms += this.getSelectedCellTags();
	return parms;
};
SortAction.prototype.toggleMenu = function(jsonSpec, enabled)
{
	if (enabled)
	{
		jsonSpec.iconClass = "sort";
		jsonSpec.disabled = false;
	}
	else
	{
		jsonSpec.iconClass = "sortDisabled";
		jsonSpec.disabled = true;
	}
	return jsonSpec;
};
SortAction.prototype.updateMenu = function(jsonSpec)
{
	jsonSpec.visible = this.ifContainsInteractiveDataContainer();
	if (! jsonSpec.visible)
	{
		return jsonSpec;
	}
	this.buildMenu(jsonSpec);
	if (jsonSpec.disabled == true)	{
		return this.toggleMenu(jsonSpec, false);
	}
	return this.buildDynamicMenuItem(this.toggleMenu(jsonSpec, true), "Sort");
};
SortAction.prototype.buildSelectedItemsString = function(selectedObjects, isSortByValue/*isSortByValue=false means sortByLabel*/, containerReportInfo)
{
	try {
		var selObj = selectedObjects[selectedObjects.length -1];
		if (isSortByValue) {
			var itemsLabel = selObj.getDisplayValues()[0];
			if (typeof itemsLabel == "undefined") {
				itemsLabel = selObj.getUseValues()[0][0];
			}
			return itemsLabel;
		} else {
			return selObj.getDataItemDisplayValue(containerReportInfo);
		}
	}
	catch (e) {
		if (console && console.log) {
			console.log(e);
		}
	}
};
SortAction.prototype.buildMenu = function(jsonSpec)
{
	jsonSpec.visible = this.ifContainsInteractiveDataContainer();
	if (! jsonSpec.visible)
	{
		return jsonSpec;
	}
	if(!this.isSelectionSortable())
	{
		return this.toggleMenu(jsonSpec, false);
	}
	jsonSpec = this.toggleMenu(jsonSpec, true);
	var sortItems = [];
	var selectionController = this.m_oCV.getSelectionController();
	var selectedObjects = selectionController.getAllSelectedObjects();
	if(selectedObjects.length == 1 && selectedObjects[0].isHomeCell() == false)
	{
		var containerType = selectionController.getDataContainerType();
		var containerId = this.getContainerId( selectionController );
		var selectedReportInfo = this.getReportInfo(containerId);
		//if the selection is on the section of the sectioned list, the containerType is "".
		if (containerType == "" && !this.isSelectionOnChart() && selectedObjects[0].getLayoutType() == "section") {
			if (selectedReportInfo != null) {
				containerType = selectedReportInfo.displayTypeId;
			}
		}
		var reportInfo, sItemLabel, sSelectionInfo;
		var currentSortFromSelection = this.getCurrentSortFromSelection();
		var bSelectionOnChart = this.isSelectionOnChart();
		var bSortByValue = currentSortFromSelection.indexOf("sortByValue") != -1;
		var bSortByValueAscending = currentSortFromSelection.indexOf("sortByValueAscending") != -1;
		var bSortByValueDescending = currentSortFromSelection.indexOf("sortByValueDescending") != -1;
		var bIsIWidgetMobile = this.m_oCV.isIWidgetMobile();
		
		if(containerType == "list" )
		{
			var oSortByValueAscendingMenuItem = { name: "SortAscending", label: RV_RES.IDS_JS_SORT_ASCENDING, action: { name: "Sort", payload: {order:"ascending", type:"value"} }, items: null };
			this.addMenuItemChecked(bSortByValueAscending, oSortByValueAscendingMenuItem, "sortAscending");
			sortItems.push(oSortByValueAscendingMenuItem);
			var oSortByValueDescendingMenuItem = { name: "SortDescending", label: RV_RES.IDS_JS_SORT_DESCENDING, action: { name: "Sort", payload: { order:"descending", type:"value"} }, items: null };
			this.addMenuItemChecked(bSortByValueDescending, oSortByValueDescendingMenuItem, "sortDescending");
			sortItems.push(oSortByValueDescendingMenuItem);
			var oSortMenuItem = { name: "DontSort", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null };
			this.addMenuItemChecked(!bSortByValue, oSortMenuItem, "sortNone");
			sortItems.push(oSortMenuItem);
		}
		else if (containerType == "crosstab" || bSelectionOnChart)
		{
			if  (selectedObjects[0].getLayoutType() == 'columnTitle' || bSelectionOnChart)
			{
				reportInfo = this.m_oCV.getRAPReportInfo();
				if(this.canSortByValueOnCrosstab(selectedObjects[0], reportInfo))
				{
					sItemLabel = RV_RES.IDS_JS_SORT_BY_VALUE;
					// need to show what item will get sorted if we're dealing with charts since
					// charts don't show selection
					if (bSelectionOnChart) {
						sSelectionInfo = this.buildSelectedItemsString(selectedObjects, true /*sortByValue*/, selectedReportInfo);
						if (typeof sSelectionInfo !== "undefined") {
							sItemLabel += ":" + sSelectionInfo;
						}
					}
					var oSortByValueMenuItem = { name: "SortByValue", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"value"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"value"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"value"} }, items: null } ] };
					this.addMenuItemChecked(bSortByValue, oSortByValueMenuItem);
					this.addMenuItemChecked(bSortByValueAscending, oSortByValueMenuItem.items[0], "sortAscending");
					this.addMenuItemChecked(bSortByValueDescending, oSortByValueMenuItem.items[1], "sortDescending");
					this.addMenuItemChecked(!bSortByValue, oSortByValueMenuItem.items[2], "sortNone");
					if (bIsIWidgetMobile) {
						oSortByValueMenuItem.flatten = true;
					}
					
					sortItems.push(oSortByValueMenuItem);
				}
				if(this.canSortByLabelOnCrosstab(selectedObjects[0]))
				{
					sItemLabel = RV_RES.IDS_JS_SORT_BY_LABEL;
					// need to show what item will get sorted if we're dealing with charts since
					// charts don't show selection
					if (bSelectionOnChart) {
						sSelectionInfo = this.buildSelectedItemsString(selectedObjects, false /*sortByLabel*/, selectedReportInfo);
						if (typeof sSelectionInfo !== "undefined") {
							sItemLabel += ":" + sSelectionInfo;
						}
					}
					var oSortByLabelMenuItem = { name: "SortByLabel", label: sItemLabel, action: null, items: [{ name: "Ascending", label: RV_RES.IDS_JS_SORT_BY_ASCENDING, action: { name: "Sort", payload: {order:"ascending",type:"label"} }, items: null }, { name: "Descending", label: RV_RES.IDS_JS_SORT_BY_DESCENDING, action: { name: "Sort", payload: {order:"descending",type:"label"} }, items: null }, { name: "SortNone", label: RV_RES.IDS_JS_DONT_SORT, action: { name: "Sort", payload: {order:"none",type:"label"} }, items: null } ] };
					var bSortByLabel = currentSortFromSelection.indexOf("sortByLabel") != -1;
					this.addMenuItemChecked(bSortByLabel, oSortByLabelMenuItem);
					this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelAscending") != -1, oSortByLabelMenuItem.items[0], "sortAscending");
					this.addMenuItemChecked(currentSortFromSelection.indexOf("sortByLabelDescending") != -1, oSortByLabelMenuItem.items[1], "sortDescending");
					this.addMenuItemChecked(!bSortByLabel, oSortByLabelMenuItem.items[2], "sortNone");
					if (bIsIWidgetMobile) {
						oSortByLabelMenuItem.flatten = true;
					}
					sortItems.push(oSortByLabelMenuItem);
				}
			}
		}
	}
	if(sortItems.length == 0)
	{
		this.toggleMenu(jsonSpec, false);
	}
	else
	{
		if (bIsIWidgetMobile) {
			if (containerType == "crosstab" || bSelectionOnChart) {
				jsonSpec.useChildrenItems = true;
			}
			else {
				jsonSpec.flatten = true;
			}
		}
		
		jsonSpec.items = sortItems;
		this.toggleMenu(jsonSpec, true);
	}
	return jsonSpec;
};
SortAction.prototype.isSelectionSortable = function()
{
	var selectionController = this.m_oCV.getSelectionController();
	var selectedObjects = selectionController.getAllSelectedObjects();
	if (selectedObjects.length == 1) {
		var selectedObject = selectedObjects[0];
		//If the select object should be disabled when the user selects a measured cell(s).
		if (selectionController.getDataContainerType() == "crosstab" && selectedObject.getLayoutType() == 'datavalue')
		{
			return false;
		}
		if (selectionController.hasSelectedChartNodes())
		{
			var node = selectedObject.getArea();
			if (node.nodeName == 'AREA' || node.nodeName == 'IMG')
			{
				return selectedObjects[0].getLayoutType() == 'ordinalAxisLabel' || selectedObjects[0].getLayoutType() == 'legendLabel';
			}
		}
		else
		{
			var data = selectedObject.getDataItems();
			if(selectedObject.getCellRef().getAttribute("type") == "datavalue" && !(data && data.length)) {
				//Not sortable if there is no logical data in the selection
				return false;
			}
			var oCell = selectedObject.getCellRef();
			if (oCell.getAttribute("no_data_item_column") === "true") {
				return false;
			}
			if (oCell.getAttribute("canSort") != "false") {
				return true;
			}
		}
	}
	return false;
};
SortAction.prototype.getCurrentSortFromSelection = function()
{
	var containerId = this.getContainerId(this.m_oCV.getSelectionController());
	var oRAPReportInfo = this.m_oCV.getRAPReportInfo();
	var currentSortFromSelection = "";
	if(containerId != "" && oRAPReportInfo) {
		var container = oRAPReportInfo.getContainer(containerId);
		if(typeof container.sort != "undefined") {
			var selectionController = this.m_oCV.getSelectionController();
			var selectedObjects = selectionController.getAllSelectedObjects();
			if(selectedObjects.length == 1) {
				var dataItems = selectedObjects[0].getDataItems();
				if(dataItems.length < 1) {
					return currentSortFromSelection;
				}
				var dataItem = dataItems[0][0];
				for(var index = 0; index < container.sort.length; ++index) {
					var sortInfo = container.sort[index];
					if(typeof sortInfo.labels == "string" && sortInfo.labels == dataItem) {
						currentSortFromSelection += sortInfo.order == "descending" ? "sortByLabelDescending" : "sortByLabelAscending";
					}
					if(typeof sortInfo.valuesOf == "string" && (sortInfo.valuesOf == dataItem || this.isSortedValueOnRenamedColumn(selectedObjects[0], sortInfo))) {
						currentSortFromSelection += sortInfo.order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
					}
					else if(sortInfo.valuesOf instanceof Array) {
						var match = true;
						for(var valueSortIdx = 0; valueSortIdx < sortInfo.valuesOf.length; ++valueSortIdx) {
							if(valueSortIdx < selectedObjects[0].m_contextIds[0].length) {
								var ctx = selectedObjects[0].m_contextIds[0][valueSortIdx];
								var selectionDisplayValue = selectionController.getDisplayValue(ctx);
								var sortDisplayValue = this.findItemLabel(container, sortInfo.valuesOf[valueSortIdx].item);
								if(sortDisplayValue != selectionDisplayValue) {
									match = false;
									break;
								}
							}
						}
						if(match) {
							currentSortFromSelection += sortInfo.valuesOf[0].order == "descending" ? "sortByValueDescending" : "sortByValueAscending";
						}
					}
				}
			}
		}
	}
	return currentSortFromSelection;
};
SortAction.prototype.isSortedValueOnRenamedColumn =function(selectedObject, sortInfo){
 if(sortInfo && selectedObject){
 	return (sortInfo.valuesOf === selectedObject.getColumnRP_Name() && selectedObject.getLayoutType() === "columnTitle");
 }	
};
SortAction.prototype.findItemLabel = function(container, item) {
	var itemInfo = container.itemInfo;
	if (itemInfo) {
		for (var i = 0; i < itemInfo.length; i++) {
			if (itemInfo[i].item === item) {
				if (itemInfo[i].itemLabel) {
					return itemInfo[i].itemLabel;
				}
				break;
			}
		}
	}
	return item;
};
SortAction.prototype.canSortByValueOnCrosstab = function(selectedObject, reportInfo)
{
	var selectionController = this.m_oCV.getSelectionController();
	var containerId = this.getContainerId(this.m_oCV.getSelectionController());
	if (selectionController.isRelational() == true) {
		return false;
	}
	if (selectionController.selectionsHaveCalculationMetadata() && this.selectedObjectIsLeaf(containerId, selectedObject, reportInfo)) {
		//The DAM layer allows "tagging" of calculation values which are part of sets with uuid designators.
		//These uuid's are simply passed through and returned as if they were mun's (but are not muns and can't be used in expressions)
		//We don't support these as discrete values.
		var aMuns = selectedObject.getMuns()[0];
		for (var index = 0; index < aMuns.length; ++index)
		{
			if (aMuns[index] != null && aMuns[index].indexOf("uuid:") >= 0)
			{
				return false;
			}
		}
		return true;
	}
	return false;
};
SortAction.prototype.selectedObjectIsLeaf = function (containerId, selectedObject, reportInfo)
{
	if (reportInfo) {
		var dataItems = selectedObject.getDataItems();
		if (dataItems != null && typeof dataItems != "undefined" && dataItems.length > 0) {
			var oDrillability = reportInfo.getDrillability(containerId, dataItems[0][0]);
			if (oDrillability) {
				return oDrillability.leaf == true;
			}
		}
	}
	return false;
};
SortAction.prototype.canSortByLabelOnCrosstab = function(selectedObject)
{
	var selectionController = this.m_oCV.getSelectionController();
	var selectedObjects = selectionController.getAllSelectedObjects();
	if(selectedObjects.length == 1) {
		// FIXME: This variable (selectedObject) is masking the first parameter. Remove variable or the parameter.
		var selectedObject = selectedObjects[0];
		if (this.isSelectSingleMember(selectedObject)==false)
		{
			if (selectionController.selectionsNonMeasureWithMUN() || !selectionController.selectionsHaveCalculationMetadata()) {
					return true;
			}
		}
	}
	return false;
};