var cms_ngapp = angular.module('sn.$sp');

cms_ngapp.config(function($httpProvider) {
	$httpProvider.defaults.headers.common["X-UserToken"] = window.g_ck;
});

cms_ngapp.config(function($mdIconProvider) {
	$mdIconProvider.defaultFontSet( 'fontawesome' );
});

if ( typeof primaryPalette == "undefined") {
	var primaryPalette = "blue-grey";
	if ( typeof primaryPaletteOptions == "undefined") {
		var primaryPaletteOptions = {};
	}
}

if ( typeof accentPalette == "undefined") {
	var accentPalette = "orange";
	if ( typeof accentPaletteOptions == "undefined") {
		var accentPaletteOptions = {};
	}
}

if ( typeof primaryPalette != "undefined") {
	cms_ngapp.config(function($mdThemingProvider) {
		$mdThemingProvider.theme('default')
		.primaryPalette(primaryPalette, primaryPaletteOptions)
		.accentPalette(accentPalette, accentPaletteOptions);
	});
}
	
cms_ngapp.service('$userService', function($q, $http){
    this.user_attributes = {};
	
	this.getValue = function( attributeName ) {
		if ( typeof this.user_attributes[attributeName] != "undefined" ) {
			return this.user_attributes[attributeName];	
		}
	};
	
	this.setValue = function( attributeName, value) {
		this.user_attributes[attributeName] = value;
	};
	
	this.getDisplayValue = function() {
		return this.getValue('displayValue');
	};
	
	this.setUserObj = function( inputAttr ) {
		this.user_attributes = inputAttr;
	};
	
	this.loadUser = function( userID ) {
		var ga = new GlideAjax(glideAjax).setScope("x_ever_metro_porta"); 
		ga.addParam('sysparm_name','getUserObj'); 
		ga.addParam('sysparm_user_id', userID);
		var deferred = $q.defer();
		ga.getXML(function (ajaxresponse) {
			var tmpData =ajaxresponse.responseXML.documentElement.getAttribute("answer");
			deferred.resolve(JSON.parse(tmpData));
		});
		return deferred.promise;
	};
	
	this.getCartDetails = function( cartName ) {
		if ( cartName == null ) { cartName = "DEFAULT"; }
		var deferred = $q.defer();
		$http.get('/api/x_ever_metro_porta/evgess_common/get_cart_details/'+cartName).then(function (response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
	this.storePreference = function(sPreferenceName, sPreferenceValue) {
		var ga2 = new GlideAjax(glideAjax).setScope("x_ever_metro_porta");
		ga2.addParam('sysparm_name','setUserPreference');
		ga2.addParam('sysparm_preference', sPreferenceName);
		ga2.addParam('sysparm_preference_value', sPreferenceValue);
		ga2.getXML(function (ajaxresponse) {
		});
	};
	
});

cms_ngapp.service('$msgService', function($mdToast, $animate, $mdDialog){
	this.showSimpleToast = function(sMsg, sType) {
		if ( sType == null ) { sType = "info";}
		if ( sType == "error" ) {
			sMsg = "<i class=\"fa fa-exclamation-circle\"></i>" + sMsg;
		}
			
		if ( sType == "success" ) {
			sMsg = "<i class=\"fa fa-check-circle\"></i>" + sMsg;
		}
			
		$mdToast.show({
			template: '<md-toast class="md-toast"><div class="md-toast-content ' + sType +'">' + sMsg + '</div></md-toast>',
			hideDelay: 4000,
			position: 'top right',
			parent: document.getElementById('toast-container')
		});
		
	};
	
	this.showAlert = function( sMsg, ev, sText ) {
		if ( sText == null ) { sText = sMsg;}
		$mdDialog.show(
			$mdDialog.alert()
			.parent(angular.element(document.body))
			.clickOutsideToClose(true)
			.title(sMsg)
			.textContent(sText)
			.ariaLabel(sMsg)
			.ok('Ok')
			.targetEvent(ev)
		);
	};
	
});

cms_ngapp.service('$cacheSvc', function($window){
	this.default_expire_mins = 15;
	this.enabled = true;
	this.cache_cards = [];
	
	this.setEnabled = function( bMode ) {
		this.enabled = bMode;
	};
	
	this.setDefaultExpire = function( iMinutes ) {
		this.default_expire_mins = iMinutes;
	};
	
	this.setCacheCards = function( aCardTypes ) {
		this.cache_cards = aCardTypes;
	};
	
	this.setData = function( key, data, expireDate ) {
		if ( this.enabled ) {
			if ( expireDate == null ) {
				expireDate = this.getDefaultExpire();	
			}
			var cacheObj = {};
			cacheObj.key = key;
			cacheObj.data = data;
			cacheObj.expire = expireDate;
			try {
				$window.localStorage.setItem(key, JSON.stringify(cacheObj));
			} catch( err ) {
				console.warn('[setData] Error setting cache key '+key + ', error:'+err);
			}
		}
	};
	
	this.removeCache = function( key ) {
		if ( key != null ) {
			$window.localStorage.removeItem(key);	
		} else {
			$window.localStorage.clear();
			return $window.localStorage.length;	
		}
	};
	
	this.getData = function( key ) {
		if ( this.enabled ) {
			var tmpObj = $window.localStorage.getItem(key);
			if ( tmpObj != undefined && tmpObj != "") {
				var cacheObj = JSON.parse(tmpObj);
				var currentDate = new Date().getTime();
				if ( cacheObj.expire != null && cacheObj.expire > currentDate ) {
					return cacheObj.data;	
				} else {
					this.removeCache(key);
				}
			
				return "";
			}
		}
				
		return "";
	};
	
	this.buildExpireDate = function( iMinutes ) {
		if ( iMinutes == null ) {
			iMinutes = this.default_expire_mins;
		}
		var currentDate = new Date().getTime();
		return (currentDate + iMinutes*60000);
	};
	
	this.getDefaultExpire = function() {
		return this.buildExpireDate();
	};
	
	this.isCardTypeCache = function( aTypes ) {
		if ( this.cache_cards.length == 0) { return false; }
		for ( var i=0; i<aTypes.length; i++ ) {
			if ( this.cache_cards.indexOf(aTypes[i]) < 0 ) {
				return false;
			}
		}
		
		return true;
	};
	
	this.getCacheKeys = function( sNamespace, bContainsFlag ) {
		var i = 0;
		if ( bContainsFlag == null ) { bContainsFlag = false; }
		var sKey;
		var aKeys = [];
		for (; sKey = $window.localStorage.key(i); i++) {
			if ( sNamespace == null ) {
				aKeys.push(sKey);
			} else {
				if ( !bContainsFlag ) {
					if ( sKey.startsWith(sNamespace)) {
						aKeys.push(sKey);
					}
				} else {
					if ( sKey.indexOf(sNamespace) > -1 ) {
						aKeys.push(sKey);
					}
				}
				
			}
		}
		return aKeys;
	};
	
});

cms_ngapp.service('$favoriteService', function($q, $http){
	this.favorites = [];
	this.recent_views = [];
	this.show_favorites = false;
	this.getting_favorites = false;
	this.getting_recent = false;
	
	this.removeFavorite = function( favObj, ev ) {
		var deferred = $q.defer();		
		$http.post('/api/x_ever_metro_porta/evgess_favorites/remove_favorite/'+favObj.activity_id).then(function(response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
	this.removeFilter = function( filterObj, sQueryTypes) {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_query_card_types = sQueryTypes;
		$http.post('/api/x_ever_metro_porta/evgess_favorites/remove_filter/'+filterObj.id, postData).then(function(response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
	this.addToFavorites = function( card, ev ) {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_table = card.x_name;
		postData.sysparm_seq = this.favorites.length;
		postData.sysparm_context = "sp";
		$http.post('/api/x_ever_metro_porta/evgess_favorites/add_favorite/'+card.id, postData).then(function(response) {
			deferred.resolve(response);
		});
				
		return deferred.promise;
	};
	
	this.saveFilter = function(sName, tags, sTypes, sQueryTypes, sPageID) {
		var deferred = $q.defer();
		var sFilterStr = JSON.stringify(tags);
		if ( sQueryTypes == null ) { sQueryTypes = sTypes; }
		var postData = {};
		postData.sysparm_filter_name = sName;
		postData.sysparm_filter_str = sFilterStr;
		postData.sysparm_card_types = sTypes;
		postData.sysparm_query_card_types = sQueryTypes;
		postData.sysparm_page_id = sPageID;
		$http.post('/api/x_ever_metro_porta/evgess_favorites/save_filter', postData).then(function(response) {
			deferred.resolve(response);
		});
				
		return deferred.promise;
	};
	
	this.storeSequences = function() {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_favorites = JSON.stringify(this.favorites);
		$http.post('/api/x_ever_metro_porta/evgess_favorites/set_sequence', postData).then(function(response) {
			deferred.resolve(response);
		});
				
		return deferred.promise;
	};
	
	this.registerActivity = function( sDocumentID, sTable, sType, addlInfo ) {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_document_id = sDocumentID;
		postData.sysparm_table = sTable;
		postData.sysparm_type = sType;
		postData.sysparm_addl_info = JSON.stringify(addlInfo);
		$http.post('/api/x_ever_metro_porta/evgess_favorites/register_activity', postData).then(function(response) {
			deferred.resolve(response);
		});
				
		return deferred.promise;
	};
	
	this.getFavorites = function() {
		this.getting_favorites = true;
		var deferred = $q.defer();
		$http.get('/api/x_ever_metro_porta/evgess_favorites').then(function(response) {
			this.getting_favorites = false;
			var bSuccess = false;
			if ( typeof response.status != "undefined") {
				bSuccess = (response.status == 200);
			}
			if ( bSuccess ) {
				deferred.resolve(response.data.result);
			} else {
				deferred.resolve([]);
			}
		});
		
		return deferred.promise;
	};
	
	this.getRecentActivity = function() {
		this.getting_recent = true;
		var deferred = $q.defer();
		$http.get('/api/x_ever_metro_porta/evgess_favorites/get_recent_activity').then(function(response) {
			this.getting_recent = false;
			var bSuccess = false;
			if ( typeof response.status != "undefined") {
				bSuccess = (response.status == 200);
			}
			if ( bSuccess ) {
				deferred.resolve(response.data.result);
			} else {
				deferred.resolve([]);
			}
		});
		
		return deferred.promise;
	};
	
	this.setFavoriteLabel = function( favoriteID, sLabel) {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_label = sLabel;
		$http.post('/api/x_ever_metro_porta/evgess_favorites/update_favorite_label/'+favoriteID, postData).then(function(response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
	this.setFilterLabel = function( filterID, sLabel) {
		var deferred = $q.defer();
		var postData = {};
		postData.sysparm_label = sLabel;
		$http.post('/api/x_ever_metro_porta/evgess_favorites/update_filter_label/'+filterID, postData).then(function(response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
});

cms_ngapp.service('$eventsService', function($q, $http){
	this.events = [];
	this.polling_interval = -1;
	
	this.ackEvent = function( eventObj, ev ) {	
		var deferred = $q.defer();
		$http.post('/api/x_ever_metro_porta/evgess_events/ack_event/'+eventObj.id).then(function(response) {
			deferred.resolve(response);
		});
			
		return deferred.promise;
	};
	
	this.getEvents = function() {
		var deferred = $q.defer();
		var addlParms = {};
		addlParms.params = {sysparm_context :"sp"};
		$http.get('/api/x_ever_metro_porta/evgess_events', addlParms).then(function (response) {
			deferred.resolve(response);
		});
		
		return deferred.promise;
	};
	
});

cms_ngapp.service('$cardviewer', function($q, $http, $cacheSvc){
    this.attributes = {
		'view' : "list",
		'expand_behavior' : "click",
		'click_behavior' : "open",
		'x_expanded' : false,
		'x_pin_sidebar': true,
		'x_show_sidebar': true,
		'x_count_mode' : false,
		'x_sidebar_title' : "Additional Options"
	};
	this.current_pageid = null;
	this.sidebar_id = "right";
	this.debug = false;
	this.cache_keys = {};
	this.cache_in_use = false;
	this.cache_svc = $cacheSvc;
	
	this.getValue = function( attributeName ) {
		if ( typeof this.attributes[attributeName] != "undefined" ) {
			return this.attributes[attributeName];	
		}
		return "";
	};
	
	this.setAttribute = function( attributeName, value ) { this.attributes[attributeName] = value;};
	this.setObj = function( inputAttr ) { this.attributes = inputAttr;};
	this.setViewType = function( sViewType ) {this.setAttribute('view', sViewType);};
	this.setExpandBehavior = function( sBehavior ) {this.setAttribute('expand_behavior', sBehavior);};
	this.setClickBehavior = function( sBehavior ) {this.setAttribute('click_behavior', sBehavior);};
	this.setExpanded = function( sMode ) {this.setAttribute('x_expanded', sMode);};
	this.setPinSidebar = function( sMode, bStorePreference ) {
		if ( sMode == null || sMode == "" ) { sMode = false; }
		if ( bStorePreference == null ) { bStorePreference = true; }
		if ( this.current_pageid == null ) { bStorePreference = false; }
		this.setAttribute('x_pin_sidebar', sMode);
		if ( bStorePreference ) {
			var sPrefValue = "false";
			if ( sMode ) { sPrefValue = "true"; }
			var deferred = $q.defer();
			var postData = {};
			postData.sysparm_preference = "evg.sidenav.pin::"+this.current_pageid;
			postData.sysparm_preference_value = sPrefValue;
			$http.post('/api/x_ever_metro_porta/evgess_common/store_pref', postData).then(function(response) {
				deferred.resolve(response);
			});
			
			return deferred.promise;
		}
	};
	this.setShowSidebar = function( sMode ) {this.setAttribute('x_show_sidebar', sMode);};
	this.setSidebarTitle = function( sTitle ) {this.setAttribute('x_sidebar_title', sTitle);};
	
	this.setFilter = function( sFilterName, value ) {
		var aFilters = this.getValue('x_filters');
		for ( var i=0; i<aFilters.length; i++ ) {
			if ( aFilters[i].name == sFilterName ) {
				aFilters[i].value = value;
				return;
			}
		}
	};
	
	this.clearFilters = function() {
		var aFilters = this.getValue('x_filters');
		for ( var i=0; i<aFilters.length; i++ ) {
			aFilters[i].value = "";	
		}
	};
	
	this.getFilter = function( sFilterName ) {
		var aFilters = this.getValue('x_filters');
		for ( var i=0; i<aFilters.length; i++ ) {
			if ( aFilters[i].name == sFilterName ) {
				return aFilters[i];
			}
		}
		
		return {};
	};
	
	this.toJSON = function() {	
		return JSON.stringify(this.attributes);
	};
	
	this.getActionScript = function( actionID ) {
		var actions = this.getValue('actions');
		for ( var q=0; q<actions.length; q++ ) {
			if ( actions[q].id == actionID ) {
				return actions[q].x_function;	
			}
		}
		
		return null;
	};
	
	this.getTypes = function() {
		var aTypes = [];
		var typeList = this.getValue('types');
		for ( var qq=0; qq< typeList.length; qq++ ) {
			aTypes.push(typeList[qq].name);
		}	
		return aTypes;
	};
	
	this.getFilters = function() {
		return this.getValue('x_filters');
	};
	
	this.getFiltersMin = function() {
		var aFilters = [];
		var aTmpFilters = this.getFilters();
		for ( var x=0; x<aTmpFilters.length; x++ ) {
			aFilters.push(aTmpFilters[x].name +"^"+aTmpFilters[x].value);
		}
		
		return aFilters;
	};
	
	this.getCards = function(aTypes, aFilters, bClearCache) {
		if ( bClearCache == null ) { bClearCache = false; }
		if ( this.debug ) { console.time("$cardviewer.getCards");}
		var deferred = $q.defer();
		if ( aTypes == null ) { aTypes = this.getTypes(); }
		if ( aFilters == null ) { aFilters = this.getFiltersMin(); }
		var bExpanded = this.getValue('x_expanded');
		if ( bExpanded == "") { bExpanded = false;}
		var sFilterData = JSON.stringify(aFilters);
		var sCardTypeData = aTypes.join(',');
		
		var bUseCache = this.cache_svc.isCardTypeCache(aTypes);
		if ( this.debug ) { console.log('bUseCache for '+aTypes+' equals '+bUseCache);}
		var cacheData = "";
		var cacheKey = 'card_types='+sCardTypeData+'&card_filters='+sFilterData+'&expanded='+bExpanded;
		
		if ( bClearCache ) {
			var removeKey = this.current_pageid+"."+cacheKey;
			if ( this.debug ) { console.log('Getting new cards by clearing cache key:'+removeKey);}
			this.cache_svc.removeCache(removeKey);
			this.removeCacheKey(removeKey);
		}
		
		if ( bUseCache ) {
			cacheData = this.getCacheData(cacheKey);
		}
		
		if ( cacheData != "" ) {
			if ( this.debug ) { console.log('[$cardviewer.getCards] Used cached data key '+cacheKey+' for results'); }
			deferred.resolve(JSON.parse(cacheData));	
		} else {
			var bDebug = this.debug;
			var cardViewerDuplicate = this;
			var addlData = {};
			addlData.sysparm_cardtypes = sCardTypeData;
			addlData.sysparm_cardfilters = sFilterData;
			addlData.sysparm_expanded = bExpanded;
			addlData.sysparm_context = "sp";
			$http.post('/api/x_ever_metro_porta/evgess_cards', addlData).then(function (response) {
				if (bDebug) { console.timeEnd("$cardviewer.getCards");}
				var bSuccess = false;
				if ( typeof response.status != "undefined") {
					bSuccess = (response.status == 200);
				}
				if ( bUseCache ) {
					if ( bDebug ) { console.log('[$cardviewer.getCards] Storing cached data with key '+cacheKey); }
					cardViewerDuplicate.setCacheData(cacheKey, JSON.stringify(response.data.result));
				}
				if ( bSuccess ) {
					deferred.resolve(response.data.result);
				} else {
					deferred.resolve([]);
				}
			});
		}
		
		return deferred.promise;
	};
	
	this.setActionLabel = function( sActionName, sNewLabel ) {
		var aActions = this.getValue('actions');
		var bChanged = false;
		for ( var i=0; i<aActions.length; i++ ) {
			if ( aActions[i].name == sActionName ) {
				aActions[i].label = sNewLabel;	
				bChanged = true;
			}
		}
		if ( bChanged ) {
			this.setAttribute('actions', aActions);	
			
		}
		
	};
	
	this.isVerbose = function() {
		var bAttributeValue = this.getValue('x_verbose');
		if ( bAttributeValue != "" ) {
			return bAttributeValue;
		}
		
		return false;
	};
	
	this.getCacheData = function( sKey ) {
		sKey = this.current_pageid+"."+sKey;
		var tmpData = this.cache_svc.getData(sKey);
		if ( tmpData != "" ) {
			this.addCacheKey(sKey);
		}
		
		return tmpData;
	};
	
	this.setCacheData = function( sKey, sData ) {
		sKey = this.current_pageid+"."+sKey;
		this.cache_svc.setData(sKey, sData);
	};
	
	this.addCacheKey = function( sKey ) {
		if ( typeof this.cache_keys[this.current_pageid] == "undefined" ) {
			this.cache_keys[this.current_pageid] = [];
		}
		
		this.cache_keys[this.current_pageid].push(sKey);
		this.cache_in_use = true;
	};
	
	this.removeCacheKey = function( sKey ) {
		if ( typeof this.cache_keys[this.current_pageid] == "undefined" ) {
			return;
		}
		var aKeys = this.getCacheKeys();
		var iIndex = -1;
		for ( var i=0; i<aKeys.length; i++ ) {
			if ( aKeys[i] == sKey ) {
				iIndex = i;
			}
		}
		
		if ( iIndex > -1 ) {
			this.cache_keys[this.current_pageid].splice(iIndex, 1);
			this.cache_in_use = (this.cache_keys[this.current_pageid].length > 0);
		}
	};
	
	this.getCacheKeys = function() {
		if ( typeof this.cache_keys[this.current_pageid] == "undefined" ) {
			this.cache_keys[this.current_pageid] = [];
		}
		
		this.cache_in_use = (this.cache_keys[this.current_pageid].length > 0);
		
		return this.cache_keys[this.current_pageid];
	};
	
	this.clearCache = function(bReload) {
		if ( bReload == null ) { bReload = false; }
		this.refreshCacheKeys();
		var aKeys = this.getCacheKeys();
		for ( var i=0; i<aKeys.length; i++ ) {
			this.cache_svc.removeCache(aKeys[i]);
		}
		if ( bReload ) {
			window.location.reload();
		} else {
			this.refreshCacheKeys();
		}
	};
	
	this.refreshCacheKeys = function() {
		this.cache_in_use = false;
		this.cache_keys[this.current_pageid] = [];
		var aKeys = this.cache_svc.getCacheKeys(this.current_pageid+".");
		for ( var i=0; i<aKeys.length; i++ ) {
			this.addCacheKey(aKeys[i]);
		}
	};
	
	this.setSavedFilterLabel = function(sFilterID, sLabel) {
		if (typeof this.attributes.x_saved_filters == "undefined" ) {
			return;
		}
		
		for ( var i=0; i<this.attributes.x_saved_filters.length; i++ ) {
			if (this.attributes.x_saved_filters[i].id == sFilterID ) {
				this.attributes.x_saved_filters[i].label = sLabel;
				break;
			}
		}
	};
	
	this.removeSavedFilterFromList = function( sFilterID) {
		if (typeof this.attributes.x_saved_filters == "undefined" ) {
			return;
		}
		var newList = [];
		for ( var i=0; i<this.attributes.x_saved_filters.length; i++ ) {
			if (this.attributes.x_saved_filters[i].id != sFilterID ) {
				newList.push(this.attributes.x_saved_filters[i]);
			}
		}
		
		this.attributes.x_saved_filters = newList;
	};
	
});

cms_ngapp.service('$ticketService', function($q, $http){
	this.id = null;
	this.label = "";
	this.description = "";
	this.has_workflow = false;
	this.show_workflow = false;
	this.stageInfo = {};
	this.started = 0;
	this.ended = 0;
	this.wf_msgs = [];
	
	this.initialize = function() {
		this.id = null;
		this.label = "";
		this.description = "";
		this.has_workflow = false;
		this.show_workflow = false;
		this.stageInfo = {};
	};
	
	this.toggleWorkflowView = function() {
		if ( !this.has_workflow ) {
			this.show_workflow = false;
			return;
		}
		this.show_workflow = !this.show_workflow;
	};
	
	this.getWorkflowDetails = function() {
		var deferred = $q.defer();
		$http.get('/api/x_ever_metro_porta/evgess_cards/get_workflow_data/'+this.id).then(function (response) {
			if ( response.status == "200" ) {
				deferred.resolve(response.data.result);
			} else {
				deferred.resolve({});
			}
		});
		
		return deferred.promise;
	};
	
	this.buildWorkflowStageData = function(workflowData) {
		if ( workflowData == null ) {
			return [];
		}
		
		var workflowStageData = [];
		var lastStart = this.started;
		var lastEnd = this.ended;
		var iOffset = 0;
		
		workflowStageData.tz_offset = workflowData.tz_offset;
		//console.log('[buildWorkflowStageData] tz_offset:'+workflowStageData.tz_offset);
		//console.log('[buildWorkflowStageData] workflowData:'+JSON.stringify(workflowData));
		//console.log('[buildWorkflowStageData] stageData:'+JSON.stringify(this.stageInfo));
				
		if ( typeof this.stageInfo.stages !== 'undefined' ) {
			var aStages = this.stageInfo.stages;
			var iDoneStage = this.stageInfo.done_stage;
			for ( var x=0; x<aStages.length; x++ ) {
				var tmpStageObj = {};
				tmpStageObj.value = aStages[x].value;
				tmpStageObj.label = aStages[x].label;
				tmpStageObj.badge_class = "pending";
				tmpStageObj.icon_class = "";
				tmpStageObj.side = "left";
				if ( x % 2 === 0) { tmpStageObj.side = "right"; }
				if ( aStages[x].done ) { tmpStageObj.badge_class = "success";tmpStageObj.icon_class="fa-check";}
				if ( x == iDoneStage && !aStages[x].done ) { tmpStageObj.badge_class = "success";tmpStageObj.icon_class="fa-arrow-right";}
				if ( !workflowData.active && x == (aStages.length - 1) ) { tmpStageObj.badge_class = "success";tmpStageObj.icon_class="fa-check"; }
				tmpStageObj.started = "";
				tmpStageObj.ended = "";
				tmpStageObj.started_numeric = 0;
				tmpStageObj.ended_numeric = 0;
				tmpStageObj.duration = 0;
				for ( var q=0; q<workflowData.stage_history.length; q++ ) {
					if ( workflowData.stage_history[q].stage == tmpStageObj.value ) {
						tmpStageObj.started = workflowData.stage_history[q].started;
						tmpStageObj.started_numeric = workflowData.stage_history[q].started_numeric;
						if ( tmpStageObj.started_numeric > 0 ) { tmpStageObj.started_numeric = tmpStageObj.started_numeric;}
						if ( tmpStageObj.started_numeric > lastStart ) {lastStart = tmpStageObj.started_numeric;}
					}
					if ( workflowData.stage_history[q].old_value == tmpStageObj.value ) {
						tmpStageObj.ended = workflowData.stage_history[q].started;
						tmpStageObj.ended_numeric = workflowData.stage_history[q].started_numeric;
						if ( tmpStageObj.ended_numeric > 0 ) { tmpStageObj.ended_numeric = tmpStageObj.ended_numeric;}
						if ( tmpStageObj.ended_numeric > lastEnd ) {lastEnd = tmpStageObj.ended_numeric;}
					}
					
				}
				if ( tmpStageObj.started_numeric == 0 ) {
					tmpStageObj = this.getStageStartFromActivities(tmpStageObj, workflowData, iOffset);
					if ( tmpStageObj.started_numeric > lastStart ) {lastStart = tmpStageObj.started_numeric;}
				}
				
				if ( tmpStageObj.started_numeric > 0 && tmpStageObj.ended_numeric > 0 ) {
					if ( tmpStageObj.started_numeric > lastStart ) {lastStart = tmpStageObj.started_numeric;}
					if ( tmpStageObj.ended_numeric > lastEnd ) {lastEnd = tmpStageObj.ended_numeric;}
					tmpStageObj.duration = (tmpStageObj.ended_numeric - tmpStageObj.started_numeric);
				}
				
				tmpStageObj.activities = [];
				var workflowActivities = workflowData.historyObj;
				for ( var t=0; t<workflowActivities.length; t++ ) {
					if ( tmpStageObj.started_numeric > 0 ) {
						if ( workflowActivities[t].started_numeric >= tmpStageObj.started_numeric && workflowActivities[t].ended_numeric <= tmpStageObj.ended_numeric && !workflowActivities[t].used) {
							var tmpActivityObj = {};
							tmpActivityObj.id = workflowActivities[t].activity_id;
							tmpActivityObj.name = workflowActivities[t].activity.name;
							tmpActivityObj.ended = workflowActivities[t].ended;
							tmpActivityObj.ended_numeric = workflowActivities[t].ended_numeric;
							if ( tmpActivityObj.ended_numeric > 0 ) { tmpActivityObj.ended_numeric = tmpActivityObj.ended_numeric;}
							tmpActivityObj.started = workflowActivities[t].started;
							tmpActivityObj.started_numeric = workflowActivities[t].started_numeric;
							if ( tmpActivityObj.started_numeric > 0 ) { tmpActivityObj.started_numeric = tmpActivityObj.started_numeric;}
							tmpActivityObj.state = workflowActivities[t].state;
							tmpActivityObj.duration = 0;
							workflowActivities[t].used = true;
							if ( tmpActivityObj.started_numeric > 0 && tmpActivityObj.ended_numeric > 0 ) {
								tmpActivityObj.duration = (tmpActivityObj.ended_numeric - tmpActivityObj.started_numeric);
							}
							if ( tmpActivityObj.name != null ) {
								tmpStageObj.activities.push(tmpActivityObj);
							}
						}
					}
				}
				
				if ( tmpStageObj.started_numeric == 0 ) {
					tmpStageObj = this.getStageStartFromCurrentActivities(tmpStageObj, workflowData, iOffset);
					if ( tmpStageObj.started_numeric > lastStart ) {lastStart = tmpStageObj.started_numeric;}
				}
				
				var workflowActivities2 = workflowData.activeListObj;
				for ( var tt=0; tt<workflowActivities2.length; tt++ ) {
					if ( tmpStageObj.started_numeric > 0 ) {
						if ( workflowActivities2[tt].started_numeric >= tmpStageObj.started_numeric && tmpStageObj.ended_numeric == 0) {
							var tmpActivityObj2 = {};
							tmpActivityObj2.id = workflowActivities2[tt].activity_id;
							tmpActivityObj2.name = workflowActivities2[tt].activity.name;
							tmpActivityObj2.ended = workflowActivities2[tt].ended;
							tmpActivityObj2.ended_numeric = workflowActivities2[tt].ended_numeric;
							if ( tmpActivityObj2.ended_numeric > 0 ) { tmpActivityObj2.ended_numeric = tmpActivityObj2.ended_numeric;}
							tmpActivityObj2.started = workflowActivities2[tt].started;
							tmpActivityObj2.started_numeric = workflowActivities2[tt].started_numeric;
							if ( tmpActivityObj2.started_numeric > 0 ) { tmpActivityObj2.started_numeric = tmpActivityObj2.started_numeric;}
							tmpActivityObj2.state = workflowActivities2[tt].state;
							tmpActivityObj2.duration = 0;
							tmpStageObj.activities.push(tmpActivityObj2);
						}
					}
				}
				
				tmpStageObj.messages = [];
				for ( var yy=0; yy<workflowData.workflow_messages.length; yy++ ) {
					var bInclude = false;
					var sMessage = workflowData.workflow_messages[yy].message;
					var aMessageParts = sMessage.split('|');
					if ( aMessageParts.length == 2 ) {
						if ( aMessageParts[0] == tmpStageObj.value ) {
							bInclude = true;
							sMessage = aMessageParts[1];
						}
					}
									
					if ( bInclude ) {
						var tmpMsgObj = {};
						tmpMsgObj.started = workflowData.workflow_messages[yy].created;
						tmpMsgObj.started_numeric = workflowData.workflow_messages[yy].created_numeric;
						if ( tmpMsgObj.started_numeric > 0 ) { tmpMsgObj.started_numeric = tmpMsgObj.started_numeric;}
						tmpMsgObj.message = sMessage;
						tmpStageObj.messages.push(tmpMsgObj);
						this.wf_msgs.push(yy);
					}
						
				}
				
				if ( tmpStageObj.badge_class == "success" && tmpStageObj.started_numeric == 0 ) {
					if ( x == 0) {
						tmpStageObj.started_numeric = lastStart;
					} else {
						tmpStageObj.started_numeric = lastEnd;
					}
				}
				
				if ( tmpStageObj.badge_class == "success" && tmpStageObj.ended_numeric == 0 ) {
					var iAdder = 0;
					if ( aStages[x].last) {
						iAdder = 10;
					}
					tmpStageObj.ended_numeric = (lastEnd + iAdder);
				}
				
				if ( tmpStageObj.messages.length == 0 ) {
					tmpStageObj.messages = this.getMessagesFromDateRange(tmpStageObj, workflowData);
				}
				
				workflowStageData.push(tmpStageObj);
			}
			//End of for loop for each stage
		}
		
		return workflowStageData;
	};
	
	this.getStageStartFromActivities = function(tmpStageObj, workflowData, iOffset) {
		var workflowActivities = workflowData.historyObj;
		for ( var t=0; t<workflowActivities.length; t++ ) {
			if ( workflowActivities[t].activity.stage_value == tmpStageObj.value ) {
				if ( tmpStageObj.started_numeric == 0 ) {
					tmpStageObj.started = workflowActivities[t].started;
					tmpStageObj.started_numeric = workflowActivities[t].started_numeric;
					if ( tmpStageObj.started_numeric > 0 ) { tmpStageObj.started_numeric = tmpStageObj.started_numeric;}
				}
				tmpStageObj.ended = workflowActivities[t].ended;
				tmpStageObj.ended_numeric = workflowActivities[t].ended_numeric;
				if ( tmpStageObj.ended_numeric > 0 ) { tmpStageObj.ended_numeric = tmpStageObj.ended_numeric;}
			}
		}
		
		return tmpStageObj;
		
	};
	
	this.getStageStartFromCurrentActivities = function(tmpStageObj, workflowData, iOffset) {
		var workflowActivities = workflowData.activeListObj;
		for ( var t=0; t<workflowActivities.length; t++ ) {
			if ( workflowActivities[t].activity.stage_value == tmpStageObj.value ) {
				if ( tmpStageObj.started_numeric == 0 ) {
					tmpStageObj.started = workflowActivities[t].started;
					tmpStageObj.started_numeric = workflowActivities[t].started_numeric;
					if ( tmpStageObj.started_numeric > 0 ) { tmpStageObj.started_numeric = tmpStageObj.started_numeric;}
				}
			}
		}
		
		return tmpStageObj;
	};
	
	this.getMessagesFromDateRange = function( tmpStageObj, workflowData ) {
		var returnMsgs = [];
		var workflowMsgs = workflowData.workflow_messages;
		for ( var t=0; t<workflowMsgs.length; t++ ) {
			var iDateCheck = workflowMsgs[t].created_numeric;
			if ( iDateCheck >= tmpStageObj.started_numeric && iDateCheck < tmpStageObj.ended_numeric ) {
				if ( this.wf_msgs.indexOf(t) < 0 ) {
					returnMsgs.push(workflowMsgs[t]);
					this.wf_msgs.push(t);
				}
			}
		}
		
		return returnMsgs;
	};
	
});

/*** Keyboard Detect Service ***/
cms_ngapp.factory('keyboardManager', ['$window', '$timeout', function ($window, $timeout) {
	var keyboardManagerService = {};

	var defaultOpt = {
		'type':             'keydown',
		'propagate':        false,
		'inputDisabled':    false,
		'target':           $window.document,
		'keyCode':          false
	};
	// Store all keyboard combination shortcuts
	keyboardManagerService.keyboardEvent = {};
	// Add a new keyboard combination shortcut
	keyboardManagerService.bind = function (label, callback, opt) {
		var fct, elt, code, k;
		// Initialize opt object
		opt   = angular.extend({}, defaultOpt, opt);
		label = label.toLowerCase();
		elt   = opt.target;
		if(typeof opt.target == 'string') elt = document.getElementById(opt.target);

		fct = function (e) {
			e = e || $window.event;

			// Disable event handler when focus input and textarea
			if (opt['inputDisabled']) {
				var elt;
				if (e.target) elt = e.target;
				else if (e.srcElement) elt = e.srcElement;
				if (elt.nodeType == 3) elt = elt.parentNode;
				if (elt.tagName == 'INPUT' || elt.tagName == 'TEXTAREA') return;
			}

			// Find out which key is pressed
			if (e.keyCode) code = e.keyCode;
			else if (e.which) code = e.which;
			var character = String.fromCharCode(code).toLowerCase();

			if (code == 188) character = ","; // If the user presses , when the type is onkeydown
			if (code == 190) character = "."; // If the user presses , when the type is onkeydown

			var keys = label.split("+");
			// Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
			var kp = 0;
			// Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
			var shift_nums = {
				"`":"~",
				"1":"!",
				"2":"@",
				"3":"#",
				"4":"$",
				"5":"%",
				"6":"^",
				"7":"&",
				"8":"*",
				"9":"(",
				"0":")",
				"-":"_",
				"=":"+",
				";":":",
				"'":"\"",
				",":"<",
				".":">",
				"/":"?",
				"\\":"|"
			};
			// Special Keys - and their codes
			var special_keys = {
				'esc':27,
				'escape':27,
				'tab':9,				
				'space':32,
				'return':13,
				'enter':13,
				'backspace':8,
				'forwardslash':191,

				'scrolllock':145,
				'scroll_lock':145,
				'scroll':145,
				'capslock':20,
				'caps_lock':20,
				'caps':20,
				'numlock':144,
				'num_lock':144,
				'num':144,

				'pause':19,
				'break':19,

				'insert':45,
				'home':36,
				'delete':46,
				'end':35,

				'pageup':33,
				'page_up':33,
				'pu':33,

				'pagedown':34,
				'page_down':34,
				'pd':34,

				'left':37,
				'up':38,
				'right':39,
				'down':40,

				'f1':112,
				'f2':113,
				'f3':114,
				'f4':115,
				'f5':116,
				'f6':117,
				'f7':118,
				'f8':119,
				'f9':120,
				'f10':121,
				'f11':122,
				'f12':123
			};
			// Some modifiers key
			var modifiers = {
				shift: {
					wanted:		false, 
					pressed:	e.shiftKey ? true : false
				},
				ctrl : {
					wanted:		false, 
					pressed:	e.ctrlKey ? true : false
				},
				alt  : {
					wanted:		false, 
					pressed:	e.altKey ? true : false
				},
				meta : { //Meta is Mac specific
					wanted:		false, 
					pressed:	e.metaKey ? true : false
				}
			};
			// Foreach keys in label (split on +)
			for(var i=0, l=keys.length; k=keys[i],i<l; i++) {
				switch (k) {
					case 'ctrl':
					case 'control':
						kp++;
						modifiers.ctrl.wanted = true;
						break;
					case 'shift':
					case 'alt':
					case 'meta':
						kp++;
						modifiers[k].wanted = true;
						break;
				}

				if (k.length > 1) { // If it is a special key
					if(special_keys[k] == code) kp++;
				} else if (opt['keyCode']) { // If a specific key is set into the config
					if (opt['keyCode'] == code) kp++;
				} else { // The special keys did not match
					if(character == k) kp++;
					else {
						if(shift_nums[character] && e.shiftKey) { // Stupid Shift key bug created by using lowercase
							character = shift_nums[character];
							if(character == k) kp++;
						}
					}
				}
			}

			if(kp == keys.length &&
				modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
				modifiers.shift.pressed == modifiers.shift.wanted &&
				modifiers.alt.pressed == modifiers.alt.wanted &&
				modifiers.meta.pressed == modifiers.meta.wanted) {
        $timeout(function() {
				  callback(e);
        }, 1);

				if(!opt['propagate']) { // Stop the event
					// e.cancelBubble is supported by IE - this will kill the bubbling process.
					e.cancelBubble = true;
					e.returnValue = false;

					// e.stopPropagation works in Firefox.
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
					return false;
				}
			}

		};
		// Store shortcut
		keyboardManagerService.keyboardEvent[label] = {
			'callback': fct,
			'target':   elt,
			'event':    opt['type']
		};
		//Attach the function with the event
		if(elt.addEventListener) elt.addEventListener(opt['type'], fct, false);
		else if(elt.attachEvent) elt.attachEvent('on' + opt['type'], fct);
		else elt['on' + opt['type']] = fct;
	};
	// Remove the shortcut - just specify the shortcut and I will remove the binding
	keyboardManagerService.unbind = function (label) {
		label = label.toLowerCase();
		var binding = keyboardManagerService.keyboardEvent[label];
		delete(keyboardManagerService.keyboardEvent[label])
		if(!binding) return;
		var type		= binding['event'],
		elt			= binding['target'],
		callback	= binding['callback'];
		if(elt.detachEvent) elt.detachEvent('on' + type, callback);
		else if(elt.removeEventListener) elt.removeEventListener(type, callback, false);
		else elt['on'+type] = false;
	};
	//
	return keyboardManagerService;
}]);

/*** Filter for display of html code ***/
cms_ngapp.filter('ishtml', ['$sce', function ($sce) {
    return function (text) {
        return text ? $sce.trustAsHtml(text) : '';
    };
}]);

/*** Filter for replacing line breaks with br tags ***/
cms_ngapp.filter('nl2br', ['$sce', function ($sce) {
    return function (text) {
        return text ? $sce.trustAsHtml(text.replace(/\n/g, '<br/>')) : '';
    };
}]);

/*** Filter for dividing a number by 1000 ***/
cms_ngapp.filter('dividebyK', function () {
  return function (item) {
    return item / 1000;
  };
});

cms_ngapp.filter('trusted', ['$sce', function($sce) {
    var div = document.createElement('div');
    return function(text) {
        div.innerHTML = text;
        return $sce.trustAsHtml(div.textContent);
    };
}]);

/*** Custom filter for search refiners ***/
cms_ngapp.filter('cardFilter', ['$filter', function($filter) {
	return function (items, filters) {
		var filtered = items;
		
		function containsComparator (expected, actual) {  
			return actual.indexOf(expected) > -1;
		}
		
		
		if ( typeof filters != "undefined" ) {
			for ( var i=0; i<filters.length; i++ ) {
				var bKeywordFilter = (filters[i].attribute == 'keyword');
				var bCompareFilter = (filters[i].field_type == 'multiselectchk');
				var bIgnoreBlanks = (filters[i].field_type == 'switch' && (filters[i].value == '' || filters[i].value == null));
								
				if ( !bIgnoreBlanks ) {				
					if ( bKeywordFilter ) {
						filtered = $filter('filter')(filtered, filters[i].value);
					} else {
						var attributeObj = {};
						attributeObj[filters[i].attribute] = filters[i].value;
						if ( bCompareFilter ) {
							filtered = $filter('filter')(filtered, attributeObj, containsComparator);		
						} else {
							filtered = $filter('filter')(filtered, attributeObj);	
						}
					}
				}				
			}
		}
		
		return filtered;
	};
}]);

/*** Custom filter for search refiners ***/
cms_ngapp.filter('serviceBrowseFilter', ['$filter', function($filter) {
	return function (items, filter_categories) {
		
		var filtered = items;
		
		function containsComparator (expected, actual) {
			return actual.indexOf(expected) > -1;
		}
		if (filter_categories.indexOf("ROLE_BASED") > -1) {
			var ret = [];
			
			filtered.forEach(function(ele) {
				
				ele.child.forEach(function(child) {
					if (filter_categories.indexOf(child.id) > -1) {
						if (ret.indexOf(ele) == -1)
							ret.push(ele);
					}
				});
				
			});
			filtered = ret;
			
		} 
		if ( typeof filter_categories == "undefined" ) {
			return filtered;
		}

		if ( filter_categories.length == 0 ) {
			return filtered;
		}

		var compareObj = {};
		compareObj.id = filter_categories;

		filtered = $filter('filter')(filtered, compareObj, containsComparator);

		return filtered;
	};
}]);

/*** Custom filter for search refiners ***/
cms_ngapp.filter('childServiceBrowseFilter', ['$filter', function($filter) {
	return function (items, filter_categories) {
		
		var filtered = items;
		
		if (filter_categories.indexOf("ROLE_BASED") > -1) {
			
			if ( typeof filter_categories == "undefined" ) {
				return filtered;
			}

			if ( filter_categories.length == 0 ) {
				return filtered;
			}

			function containsComparator (expected, actual) {
				return actual.indexOf(expected) > -1;
			}
			
			var compareObj = {};
			compareObj.id = filter_categories;
			//console.log("FILTERING : ", filter_categories);

			filtered = $filter('filter')(filtered, compareObj, containsComparator);

			//console.log(filtered);
		} 
		
		
		return filtered;
	};
}]);

/*** Custom filter for truncating strings ***/
cms_ngapp.filter('cut', function () {
	return function (value, wordwise, max, tail) {
		if (!value) return '';
		
		max = parseInt(max, 10);
		if (!max) return value;
		if (value.length <= max) return value;

		value = value.substr(0, max);
		if (wordwise) {
			var lastspace = value.lastIndexOf(' ');
			if (lastspace != -1) {
				//Also remove . and , so its gives a cleaner result.
				if (value.charAt(lastspace-1) == '.' || value.charAt(lastspace-1) == ',') {
					lastspace = lastspace - 1;
				}
				value = value.substr(0, lastspace);
			}
		}

		return value + (tail || ' …');
	};
});

cms_ngapp.directive('ngSearchInput', ['$document', function ($document) {
   return function (scope, element, attrs) {
	   if ( attrs.ngSearchInput != "false" ) {
		var ESCAPE_KEY_KEYCODE = 27,
		FORWARD_SLASH_KEYCODE = 191;
	    angular.element($document[0].body).bind('keydown', function(event) {
			if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement && typeof document.activeElement.type == "undefined") {
				event.stopPropagation();
                event.preventDefault();

                var input = element[0];
                scope.$apply(function (){
                    scope.$eval(attrs.ngSearchInput);
                });
				input.value = '';
				input.focus();
            }
			
			if ( event.keyCode == ESCAPE_KEY_KEYCODE ) {
				event.stopPropagation();
                event.preventDefault();
				var input = element[0];
				input.value = '';
				input.blur();
				scope.$apply(function (){
                    scope.$eval(attrs.ngSearchInput);
                });
			}
        });
	   }
    };
}]);

/*** Directive for dynamic display of html/angularjs code ***/
cms_ngapp.directive('dynamic', function ($compile) {
  return {
    restrict: 'A',
    replace: true,
    link: function (scope, ele, attrs) {
      scope.$watch(attrs.dynamic, function(html) {
        ele.html(html);
        $compile(ele.contents())(scope);
      });
    }
  };
});
	
function bindBackToTopLink( container ) {
	$(document).ready(function() {
		$backToTop = $(container);
		if ($backToTop.length > 0) {
			window.onscroll = function() {
				//var scrollTop = $(this).scrollTop();
				var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
				if ($(this).scrollTop() > 100) {
					$backToTop.addClass('show');
				} else {
					$backToTop.removeClass('show');
				}
			};
		} else {
			console.log('[bindBackToTopLink] no element of '+container+' found');
		}
	});
}

function setCheckBox(box) {
	var name = box.name;
	var id = name.substring(3);
	var frm = box.form;
	if (frm)
		frm[id].value = box.checked;
	else {
		var widget = $(id);
		if (widget)
			widget.value = box.checked;
	}
	if (box['onchange'])
		box.onchange();
}

function scrollToSection(iTop) {
	if ( iTop == null ) {
		iTop = 600;
	}
	
	window.scrollTo(iTop, 0);
	/*
	$('html, body').animate({
		scrollTop: iTop
	}, 1000);
	*/
}