'use strict';

angular.module('cs.dashboard.query', [])
    .controller('DashboardQueryController', ['$scope', '$window', '$timeout', '$modal', 'navigationBarService', '$location', '$http', 'csApi', '$animate', 'toaster', 'GLOBAL_PROFILE_EXTENSIONS', 'CUSTOM_EXTENSIONS', 'PROFILE_CONFIG', 'localizationService', 'JTimeLineQuery', 'GRAPH_CONFIGS',
        function($scope, $window, $timeout, $modal, navigationBarService, $location, $http, csApi, $animate, toaster, GLOBAL_PROFILE_EXTENSIONS, CUSTOM_EXTENSIONS, PROFILE_CONFIG, localizationService, JTimeLineQuery, GRAPH_CONFIGS) {
			var filePath = 'url.txt';
            $animate.enabled(true);
            navigationBarService.initialize();
            $scope.multipleResults = false;
            $scope.stateObj = {};
            $scope.stateObj.focusOn = 'KPIs';
            $scope.mapping = GLOBAL_PROFILE_EXTENSIONS.mapping;
            $scope.customMapping = CUSTOM_EXTENSIONS.mapping;
            $scope.searchOptions = GLOBAL_PROFILE_EXTENSIONS.searchOptions;
            $scope.xtraNavSettings = PROFILE_CONFIG.NAVBAR_ADDITIONAL_SETTINGS;
            $scope.searching = false;
            $scope.showCustomerInfo = false;
            $scope.selectedCustomer = {};
            $scope.profileHeadersList = PROFILE_CONFIG.PROFILE_HEADERS;
            $scope.KPIJourneyHeaders = PROFILE_CONFIG.KPI_JOURNEY_HEADERS;
            $scope.KPIStateHeaders = PROFILE_CONFIG.KPI_STATE_HEADERS;

            $scope.donutTimeout = true;


			$scope.getBaseurl = function() {
				$http.get(filePath)
				.then(function(response) {
				// The URL is in the response.data
				$scope.baseUrl = response.data.trim(); // Trimming any newline characters
				if(!$scope.baseUrl){
				  $scope.baseUrl = '/genesys/1/cs';
				}
				$scope.getData();
				})
				.catch(function(error) {
                    console.error("Error reading the URL from file:", error);
				});
			};
		
            $scope.KPIStateHeaderArray = [];
            for (var i in PROFILE_CONFIG.KPI_STATE_HEADERS) {
                $scope.KPIStateHeaderArray.push(PROFILE_CONFIG.KPI_STATE_HEADERS[i]);
            }

            $scope.KPIJourneyHeaderArray = [];
            for (var i in PROFILE_CONFIG.KPI_JOURNEY_HEADERS) {
                $scope.KPIJourneyHeaderArray.push(PROFILE_CONFIG.KPI_JOURNEY_HEADERS[i]);
            }

            $scope.detailsHeader = [];
            for (var i in PROFILE_CONFIG.DETAILS_HEADER) {
                // made into an array so it keeps a consistent order 
                $scope.detailsHeader.push(PROFILE_CONFIG.DETAILS_HEADER[i]);
            }

            $scope.stateObj.detailsHeaderStates = [];
            for (var i in PROFILE_CONFIG.STATE_DETAILS) {
                // made into an array so it keeps a consistent order 
                $scope.stateObj.detailsHeaderStates.push(PROFILE_CONFIG.STATE_DETAILS[i]);
            }


            $scope.contactsCategoryInfo = ['PhoneNumber', 'EmailAddress'];

            // filter initialization
            $scope.journeyFilter = {};
            $scope.journeyFilter.statusFilters = ['Select All'];
            $scope.journeyFilter.serviceTypeFilter = ['Select All'];
            $scope.journeyFilter.stateTypeFilter = ['Select All'];
            $scope.journeyFilter.dateFilter = 'Show All';
            $scope.journeyFilter.durationStyle = 'both';
            $scope.journeyFilter.timeLineReady = false;
            $scope.journeyFilter.dateFilterType = 'Starting';
            $scope.journeyFilter.existingServiceTypes = [];
            $scope.journeyFilter.existingServiceTypes[0] = 'Select All';
            $scope.journeyFilter.existingStateTypes = [];
            $scope.journeyFilter.existingStateTypes[0] = 'Select All';

            $scope.unParsedValues = {}; // used to store unparsed values of the
            // customer values.

            $scope.optionsToQuery = []; // options used to get desired customer_id
            $scope.navIndex = 0;
            $scope.journeyStats = {};
            $scope.tableValueExists = [];

            //Configs for graphs in KPI Section
            $scope.serviceDonutConfig = GRAPH_CONFIGS.SERVICE_DONUT;
            $scope.mediaDonutConfig = GRAPH_CONFIGS.MEDIA_DONUT;
            $scope.journeyDonutConfig = GRAPH_CONFIGS.JOURNEY_DONUT;
            $scope.stateDonutConfig = GRAPH_CONFIGS.STATE_DONUT;
            $scope.stateBarConfig = GRAPH_CONFIGS.STATE_BAR;
            $scope.journeyBarConfig = GRAPH_CONFIGS.JOURNEY_BAR;
            $scope.journeyStateBarConfig = GRAPH_CONFIGS.JOURNEY_STATE_BAR;
            $scope.serviceBarConfig = GRAPH_CONFIGS.SERVICE_BAR;

            $scope.stateBarConfig.legend.format = function(d) {
                return d + ' days';
            };

            $scope.journeyBarConfig.legend.format = function(d) {
                return d + ' days';
            };

            $scope.journeyStateBarConfig.legend.format = function(d) {
                return d + ' days';
            };

            $scope.serviceBarConfig.legend.format = function(d) {
                return d + ' days';
            };

            $scope.navTitles = ['Customer Profile']; // default and mandatory
            // navTitle must always be
            // customer profile.
            var navXtraSize = _.size($scope.xtraNavSettings);

            for (var i = 1; i <= navXtraSize; i++) {
                // adding on the custom navTitles;
                $scope.navTitles[i] = $scope.xtraNavSettings[i];
            }

            $scope.customExEmpty = _.isEmpty(CUSTOM_EXTENSIONS);

            if (!$scope.customExEmpty) {
                // Merge the default with the custom
                for (var customMap in $scope.customMapping) {
                    $scope.mapping[customMap] = $scope.customMapping[customMap];
                }
            }


            for (var map in $scope.mapping) {
                if (map !== 'Customer ID' && map !== 'Anonymous ID') {
                    $scope.optionsToQuery.push($scope.mapping[map]);
                }
            }
            $scope.extraQueryOptions = GLOBAL_PROFILE_EXTENSIONS.ExtraQueryOptions;
            $scope.customerProperties = GLOBAL_PROFILE_EXTENSIONS.CustomerProperties;


            if (!$scope.customExEmpty) {

                $scope.customProperties = CUSTOM_EXTENSIONS.CustomerProperties;
                $scope.multivaluedProperties = CUSTOM_EXTENSIONS.Multivalued;

                // Merge the default with the custom
                $scope.customerProperties.push.apply($scope.customerProperties, $scope.customProperties);
                $scope.customerProperties.push.apply($scope.customerProperties, $scope.multivaluedProperties);

            }


            for (var i = 0; i < $scope.customerProperties.length; i++) {
                if (angular.isDefined($scope.customerProperties[i].primaryKey) && $scope.customerProperties[i].primaryKey === 'yes') {
                    $scope.primaryKey = {
                        label: $scope.customerProperties[i].label,
                        value: $scope.customerProperties[i].value
                    };
                }
            }

            $scope.tabData = {};
            $scope.dateSearch = {};
            $scope.queryHistory = [];
            $scope.tabData.ajaxHistory = [];
            $scope.reload = 'true';
            $scope.tabsList = [{
                'title': 'Task View',
                'templateUrl': 'app/modules/context-services/tree-view.html'
            }, {
                'title': 'Timeline View',
                'templateUrl': 'app/modules/context-services/timeline-view.html'
            }];

            $scope.getQueryHistory = function() {
                return $scope.queryHistory;
            };

            $scope.setEntityId = function(value) {
                $scope.entityId = value;
            };

            $scope.changeNavIndex = function(index, title) {
                // used to switch between tabs like KPIs and details under the
                // timeline.
                $scope.navIndex = index;
                $scope.navTitle = title;
            };

            $scope.$watch(function() {
                //when user clicks on a state, infobox switches to journey details
                return $scope.stateObj.switchToJD;
            }, function(value) {
                if ((value == true) && ($scope.navTitle !== 'KPIs')) {
                    $scope.changeNavIndex(2, 'Journey Details');
                }
            });

            localizationService.getLocaleJSON(function(localeJSON) {

                $scope.noInfoLabel = localeJSON.KPIInfo.NO_INFO;
                $scope.onlyActiveJourneysLabel = localeJSON.KPIInfo.ONLY_ACTIVE_JOURNEYS;
                $scope.noJourneysLabel = localeJSON.KPIInfo.NO_JOURNEYS;
                $scope.aboutLabel = localeJSON.KPIInfo.ABOUT;
                $scope.noStatesLabel = localeJSON.KPIInfo.NO_STATES;
                $scope.onlyActiveStatesLabel = localeJSON.KPIInfo.ONLY_ACTIVE_STATES;
                $scope.serviceNotDoneLabel = localeJSON.KPIInfo.SERVICE_NOT_DONE;
                $scope.inProgressLabel = localeJSON.KPIInfo.IN_PROGRESS;
                $scope.minutesLabel = localeJSON.KPIInfo.MINUTES;
                $scope.hoursLabel = localeJSON.KPIInfo.HOURS;
                $scope.daysLabel = localeJSON.KPIInfo.DAYS;
                $scope.cannotCalculateLabel = localeJSON.KPIInfo.CANNOT_CALCULATE;
                $scope.AllServicesLabel = localeJSON.KPIInfo.ALL_SERVICES;

                $scope.currSelectedLabel = localeJSON.TimelineGeneral.CURR_SELECTED;
                $scope.multipleCustomerLabel = localeJSON.TimelineGeneral.MULTIPLE_CUSTOMERS;
                $scope.cancelTableLabel = localeJSON.TimelineGeneral.CANCEL;
                $scope.anonIDLabel = localeJSON.TimelineGeneral.ANON_ID;
                $scope.noServiceLabel = localeJSON.TimelineGeneral.NO_SERVICE;
                $scope.noStatesLabel = localeJSON.TimelineGeneral.NO_STATES;
                $scope.selectServiceLabel = localeJSON.TimelineGeneral.SELECT_SERVICE;
                $scope.selectServiceThenStateLabel = localeJSON.TimelineGeneral.SELECT_SERVICE_THEN_STATE;
                $scope.selectStateLabel = localeJSON.TimelineGeneral.SELECT_STATE;
                $scope.noStatesThisServiceLabel = localeJSON.TimelineGeneral.NO_STATES_THIS_SERVICE;

                $scope.connectFailedLabel = localeJSON.FormControl.CONNECT_FAILED;
                $scope.emailFailLabel = localeJSON.FormControl.EMAIL_FIND_FAILED;
                $scope.phoneFailLabel = localeJSON.FormControl.PHONE_FIND_FAILED;
                $scope.findFailLabel = localeJSON.FormControl.FIND_FAILED;


            });

            $scope.tabData.queryById = function(queryType, entityId, customerQuery) {
                $scope.searching = true;
                var customerInfo, entityInfo;
                if (queryType && entityId) {
                    $scope.queryType = queryType;
                    $scope.entityId = entityId;
                }
                var jsonService = {
                    active_tasks: true,
                    completed_tasks: true,
                    active_states: true,
                    completed_states: true
                };
                $scope.tabData.oldCustomerId = $scope.entityId;
                $scope.tabData.oldQueryType = $scope.queryType;
                if ($scope.queryHistory.indexOf($scope.entityId) < 0) {
                    $scope.queryHistory = [$scope.entityId].concat($scope.queryHistory);
                }

                if ($scope.queryType === 'Service ID') {
                    csApi.queryServiceById($scope.baseUrl, $scope.entityId, jsonService).then(function(res) {
                        entityInfo = res.data;
                        $scope.queryByIdSuccessCallback(res, entityInfo, null, customerQuery);
                    });
                } else if ($scope.queryType === 'State ID') {
                    csApi.queryStateById($scope.baseUrl, $scope.serviceId, $scope.entityId, jsonService).then(function(res) {
                        entityInfo = res.data;
                        $scope.queryByIdSuccessCallback(res, entityInfo, null, customerQuery);
                    });
                } else if ($scope.queryType === 'Task ID') {
                    csApi.queryTaskById($scope.baseUrl, $scope.serviceId, $scope.entityId, jsonService).then(function(res) {
                        entityInfo = res.data;
                        $scope.queryByIdSuccessCallback(res, entityInfo, null, customerQuery);
                    });
                } else if ($scope.queryType === 'Anonymous ID') {
                    $scope.tabData.customerId = $scope.entityId;
                    $scope.tabData.isAnon = true;
                    csApi.queryCustomerServices($scope.baseUrl, $scope.entityId, $scope.tabData.isAnon, jsonService).then(function(res) {
                        customerInfo = res.data;
                        $scope.queryByIdSuccessCallback(res, null, customerInfo, customerQuery);
                    });
                } else {
                    $scope.tabData.isAnon = false;
                    $scope.tabData.customerId = $scope.entityId;
                    csApi.queryCustomerServices($scope.baseUrl, $scope.entityId, $scope.tabData.isAnon, jsonService).then(function(res) {
                        customerInfo = res.data;
                        $scope.queryByIdSuccessCallback(res, null, customerInfo, customerQuery);
                    });
                }
            };

            $scope.queryByIdSuccessCallback = function(httpResponse, entityInfo, customerInfo, customerQuery) {
                $scope.addHttpRequestHistory(httpResponse);
                if ($scope.dateSearch && $scope.dateSearch.searchEnabled) {
                    initTimeFilter($scope.dateSearch);
                }
                if (customerInfo) {
                    $scope.rawData = customerInfo;
                    $scope.tabData.maxChildren = 0;
                    $scope.inputClass = 'form-control';
                    $scope.queryFeedback = '';
                    $scope.tabData.data = {
                        'name': 'Customer',
                        'subheading': 'ID: ' + $scope.entityId,
                        'hideChildren': $scope.parseItems(customerInfo, 'Service'),
                        'stroke': ''
                    };
                    $scope.tabData.data.items = $scope.tabData.data.hideChildren;
                    $scope.tabData.data.label = $scope.tabData.data.name + ' ' + $scope.tabData.data.subheading;
                    if ($scope.queryType === 'Anonymous ID' && !$scope.selectedCustomer['anonymous_id']) {
                        $scope.selectedCustomer['anonymous_id'] = $scope.entityId;
                    } else if (!$scope.selectedCustomer[$scope.primaryKey.label]) {
                        $scope.selectedCustomer[$scope.primaryKey.label] = $scope.entityId;
                    }
                } else if (entityInfo) {
                    $scope.rawData = entityInfo;
                    $scope.tabData.maxChildren = 0;
                    $scope.inputClass = 'form-control';
                    $scope.queryFeedback = '';
                    $scope.tabData.data = $scope.parseItems([entityInfo], $scope.queryType.split(' ')[0])[0];
                } else {
                    $scope.inputClass = 'form-control has-error';
                    if (httpResponse.status === 0) {
                        $scope.queryFeedback = $scope.connectFailedLabel;
                    } else if (customerQuery === 'EmailAddress') {
                        $scope.queryFeedback = $scope.emailFailLabel;
                    } else if (customerQuery === 'PhoneNumber') {
                        $scope.queryFeedback = $scope.phoneFailLabel;
                    } else {
                        $scope.queryFeedback = $scope.findFailLabel + ' ' + $scope.queryType.substring(0, 1).toLowerCase() + $scope.queryType.substring(1) + '.';
                    }
                    if (httpResponse.status < 200 || httpResponse.status > 299) {
                        $scope.clientFound = false;
                    } else {
                        $scope.clientFound = true;
                    }
                    $scope.searching = false;
                    $scope.tabData.data = {};
                    $scope.journeyStats.selectedClient = null;
                    return;
                }
                $scope.searching = false;
                $scope.clientFound = true;
                $scope.journeyFilter.customerData = $scope.tabData.data;
                $scope.tabData.treeData = [$scope.tabData.data];
                $scope.journeyStats.selectedClient = $scope.tabData.customerId;
                if ($scope.tabData.node && $scope.tabData.refreshTree) {
                    $scope.tabData.refreshTree();
                }
            };

            function initTimeFilter(dateInfo) {
                if (dateInfo.startDate) {
                    var splitStart = dateInfo.startTime.split('.');

                    dateInfo.startDate.setUTCHours(parseInt(splitStart[0]) + (splitStart[2] === 'AM' ? 0 : 12));
                    dateInfo.startDate.setUTCMinutes(parseInt(splitStart[1]));
                }
                if (dateInfo.endDate) {
                    var splitEnd = dateInfo.endTime.split('.');

                    dateInfo.endDate.setUTCHours(parseInt(splitEnd[0]) + (splitEnd[2] === 'AM' ? 0 : 12));
                    dateInfo.endDate.setUTCMinutes(parseInt(splitEnd[1]));
                }
            }

            $scope.queryIfEnter = function(event) {
                if (event.keyCode === 13) {
                    $scope.tabData.queryById();
                }
            };

            $scope.tabData.serviceAttributes = {};
            $scope.tabData.taskAttributes = {};
            $scope.tabData.stateAttributes = {};
            $scope.tabData.propertyAttributes = {};
            $scope.tabData.applicationAttributes = {
                'Service': {},
                'Task': {},
                'State': {}
            };

            $scope.tabData.resourceAttributes = {
                'Service': {},
                'Task': {},
                'State': {}
            };

            $scope.tabData.mediaAttributes = {
                'Service': {},
                'Task': {},
                'State': {}
            };
            
            $scope.toDisplayName = function(key, name){
            	// type: 'Service', 'State', or 'Task'
            	if (!$scope.stateObj.focusOn){
            		return name;
            	}
            	if ($scope.stateObj.focusOn == 'KPIs'){
            		return " ";
            	}
            	var itemType = $scope.stateObj.focusOn.substring(0, 1).toUpperCase() 
                               + $scope.stateObj.focusOn.substring(1);
            	if (key.indexOf('resource_type') != -1 && 
            			$scope.tabData.resourceAttributes[itemType] !== undefined &&
            			$scope.tabData.resourceAttributes[itemType][name] !== undefined){
            		return $scope.tabData.resourceAttributes[itemType][name];
            	}
            	if (key.indexOf('application_type') != -1 &&
            			$scope.tabData.applicationAttributes[itemType] !== undefined &&
            			$scope.tabData.applicationAttributes[itemType][name] !== undefined){
            		return $scope.tabData.applicationAttributes[itemType][name];
            	}
            	if (key.indexOf('media_type') != -1 &&
            			$scope.tabData.mediaAttributes[itemType] !== undefined &&
            			$scope.tabData.mediaAttributes[itemType][name] != undefined){
            		return $scope.tabData.mediaAttributes[itemType][name];
            	}
            	return name;
            };

            //querying data from the server
			$scope.getData = function() {	
                    csApi.getBusinessAttributesRaw($scope.baseUrl).then(function(httpResponse) {
                    	$scope.showUI = true;
                        $scope.businessProperties = httpResponse.data;
                        $scope.addHttpRequestHistory(httpResponse, 'Get Business Attributes');
                        
                        //get list of extensions from schema to query all later
                        csApi.getProfileExtensions($scope.baseUrl).then(function(httpResponse) {
                            $scope.extensionsList = httpResponse.data;
                            $scope.addHttpRequestHistory(httpResponse, 'Get Profile Extensions');
                        }, function(err) {
                            csApi.getProfileExtensionsFallback($scope.baseUrl).then(function(httpResponse) {
                                $scope.extensionsList = httpResponse.data;
                            });
                        });

                        for (var i = 0; i < $scope.businessProperties.length; i++) {
                            if ($scope.businessProperties[i].cv_attributes.indexOf('Service.type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                		$scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                    $scope.journeyFilter.existingServiceTypes[j + 1] = $scope.businessProperties[i].values[j].display_name; // so we can filter off types. 
                                }
                            } else if ($scope.businessProperties[i].cv_attributes.indexOf('Task.type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                		$scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            } else if ($scope.businessProperties[i].cv_attributes.indexOf('State.type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                		$scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                    $scope.journeyFilter.existingStateTypes[j + 1] = $scope.businessProperties[i].values[j].display_name; // so we can filter off types. 

                                }

                                $scope.journeyFilter.existingStateTypes[j + 1] = "No States"; // so we can filter off no states.
                            } else {
                            	for (var j = 0; j < $scope.businessProperties[i].cv_attributes.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.propertyAttributes[$scope.businessProperties[i].cv_attributes[j]] = {};
                                        for (var k = 0; k < $scope.businessProperties[i].values.length; k++) {
                                            $scope.tabData.propertyAttributes[$scope.businessProperties[i].cv_attributes[j]]
                                                [$scope.businessProperties[i].values[k].name] =
                                                	$scope.businessProperties[i].values[k].display_name;
                                        }
                                	} else {
                                        $scope.tabData.propertyAttributes[$scope.businessProperties[i].cv_attributes[j]] = {};
                                        for (var k = 0; k < $scope.businessProperties[i].values.length; k++) {
                                            $scope.tabData.propertyAttributes[$scope.businessProperties[i].cv_attributes[j]]
                                                [$scope.businessProperties[i].values[k].dbid] =
                                            	    $scope.businessProperties[i].values[k].display_name || $scope.businessProperties[i].values[k].name;
                                        }
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('Service.media_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.mediaAttributes['Service'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.mediaAttributes['Service'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('Task.media_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.mediaAttributes['Task'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.mediaAttributes['Task'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('State.media_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.mediaAttributes['State'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.mediaAttributes['State'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }

                            if ($scope.businessProperties[i].cv_attributes.indexOf('Service.application_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.applicationAttributes['Service'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.applicationAttributes['Service'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('Task.application_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.applicationAttributes['Task'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.applicationAttributes['Task'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('State.application_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.applicationAttributes['State'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.applicationAttributes['State'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }

                            if ($scope.businessProperties[i].cv_attributes.indexOf('Service.resource_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.resourceAttributes['Service'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.resourceAttributes['Service'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('Task.resource_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.resourceAttributes['Task'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.resourceAttributes['Task'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                            if ($scope.businessProperties[i].cv_attributes.indexOf('State.resource_type') + 1) {
                                for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                                	if ($scope.businessProperties[i].map_name){
                                		$scope.tabData.resourceAttributes['State'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                                	} else {
                                        $scope.tabData.resourceAttributes['State'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                	}
                                }
                            }
                        }
                    })};
		
			$scope.getBaseurl();
			
            $scope.isPropertyEmpty = function(obj) {

                function isEmpty(obj) {
                    for (var key in obj) {
                        if (obj.hasOwnProperty(key))
                            return false;
                    }
                    return true;
                }

                if (isEmpty(obj['Service']) && isEmpty(obj['Task']) && isEmpty(obj['State']))
                    return true;
                return false;
            }

            $scope.addHttpRequestHistory = function(httpResponse, customAction) {
                var action = 'Query' + $scope.queryType;
                if (customAction) {
                    action = customAction
                }
                $scope.tabData.ajaxHistory.push({
                    'action': action,
                    'path': httpResponse.config.url,
                    'data': httpResponse.data,
                    'method': httpResponse.config.method,
                    'status': httpResponse.status + ' (' + httpResponse.statusText + ')',
                    'time': Date()
                });
            }

            $scope.parseItems = function(info, type) {
                var nodes = [],
                    cn,
                    states,
                    outNodes = [];
                if ($scope.tabData.maxChildren < info.length) {
                    $scope.tabData.maxChildren = info.length;
                }
                for (var j = 0; j < info.length; j++) {
                    cn = info[j];
                    nodes[j] = cn;
                    nodes[j].entityType = cn.service_type || cn.state_type || cn.task_type;
                    if (nodes[j].entityType === cn.service_type) {
                        nodes[j].entityString = $scope.tabData.serviceAttributes[nodes[j].entityType] ? $scope.tabData.serviceAttributes[nodes[j].entityType] : '';
                    } else if (nodes[j].entityType === cn.state_type) {
                        nodes[j].entityString = $scope.tabData.stateAttributes[nodes[j].entityType] ? $scope.tabData.stateAttributes[nodes[j].entityType] : '';
                    } else if (nodes[j].entityType === cn.task_type) {
                        nodes[j].entityString = $scope.tabData.taskAttributes[nodes[j].entityType] ? $scope.tabData.taskAttributes[nodes[j].entityType] : '';
                    }
                    nodes[j].name = nodes[j].entityString ?
                        type + ': ' + nodes[j].entityString :
                        type + ': ' + '(' + nodes[j].entityType + ')';
                    nodes[j].subheading = cn.started.timestamp;
                    nodes[j].label = nodes[j].name + ' ' + cn.started.timestamp;
                    nodes[j].type = type;
                    nodes[j].stroke = '';
                    if (nodes[j].started.media_type) {
                        nodes[j].startedMediaInfo = $scope.tabData.mediaAttributes[nodes[j].type][nodes[j].started.media_type] + ' (' + nodes[j].started.media_type + ')';
                    }
                    if (nodes[j].completed && nodes[j].completed.media_type) {
                        nodes[j].completedMediaInfo = $scope.tabData.mediaAttributes[nodes[j].type][nodes[j].completed.media_type] + ' (' + nodes[j].completed.media_type + ')';
                    }
                    if (nodes[j].started.resource_type) {
                        nodes[j].startedResourceInfo = $scope.tabData.resourceAttributes[nodes[j].type][nodes[j].started.resource_type] + ' (' + nodes[j].started.resource_type + ')';
                    }
                    if (nodes[j].completed && nodes[j].completed.resource_type) {
                        nodes[j].completedResourceInfo = $scope.tabData.resourceAttributes[nodes[j].type][nodes[j].completed.resource_type] + ' (' + nodes[j].completed.resource_type + ')';
                    }
                    if (nodes[j].started.application_type) {
                        nodes[j].startedApplicationInfo = $scope.tabData.applicationAttributes[nodes[j].type][nodes[j].started.application_type] + ' (' + nodes[j].started.application_type + ')';
                    }
                    if (nodes[j].completed && nodes[j].completed.application_type) {
                        nodes[j].completedApplicationInfo = $scope.tabData.applicationAttributes[nodes[j].type][nodes[j].completed.application_type] + ' (' + nodes[j].completed.application_type + ')';
                    }
                    if (cn.active_states && cn.completed_states &&
                        (cn.active_states.length || cn.completed_states.length)) {
                        states = $scope.parseItems(cn.active_states
                            .concat(cn.completed_states),
                            'State');
                        nodes[j].hideChildren = states;
                    }
                    if (cn.active_tasks && cn.completed_tasks &&
                        (cn.active_tasks.length || cn.completed_tasks.length)) {
                        var tasks = $scope.parseItems(cn.active_tasks
                            .concat(cn.completed_tasks),
                            'Task');
                        for (var k = 0; k < tasks.length; k++) {
                            if (tasks[k].state_id && states) {
                                for (var l = 0; l < states.length; l++) {
                                    if (states[l].state_id === tasks[k].state_id) {
                                        if (states[l].hideChildren) {
                                            states[l].hideChildren
                                                .push(tasks[k]);
                                        } else {
                                            states[l].hideChildren = [tasks[k]];
                                        }
                                        if (states[l].items) {
                                            states[l].items.push(tasks[k]);
                                        } else {
                                            states[l].items = [tasks[k]];
                                        }
                                        break;
                                    }
                                    if (states[l].hideChildren && states[l].hideChildren.length > $scope.tabData.maxChildren) {
                                        $scope.tabData.maxChildren = nodes[l].hideChildren.length;
                                    }
                                }
                            } else {
                                if (nodes[j].hideChildren) {
                                    nodes[j].hideChildren
                                        .push(tasks[k]);
                                } else {
                                    nodes[j].hideChildren = [tasks[k]];
                                }
                            }
                        }
                    }
                    if (nodes[j].hideChildren && nodes[j].hideChildren.length > $scope.tabData.maxChildren) {
                        $scope.tabData.maxChildren = nodes[j].hideChildren.length;
                    }
                    nodes[j].items = nodes[j].hideChildren;
                    if ($scope.tabData.node && nodes[j].type === $scope.tabData.node.type && (
                        ($scope.tabData.node.type === 'Service' && nodes[j].service_id === $scope.tabData.node.service_id) ||
                        ($scope.tabData.node.type === 'State' && nodes[j].state_id === $scope.tabData.node.state_id) ||
                        ($scope.tabData.node.type === 'Task' && nodes[j].task_id === $scope.tabData.node.task_id))) {
                        $scope.tabData.node = nodes[j];
                    }
                    if (nodes[j].items && nodes[j].items.length) {
                        outNodes.push(nodes[j]);
                        continue;
                    }
                    if ($scope.dateSearch && $scope.dateSearch.searchEnabled) {
                        var searchType = $scope.dateSearch.timeSearchType;

                        if ($scope.dateSearch.startDate && !$scope.dateSearch.endDate) {
                            if (searchType === "All" && (new Date(info[j].started.timestamp) < $scope.dateSearch.startDate) ||
                                (info[j].completed && (searchType === "Completed" || searchType === "Active") &&
                                    new Date(info[j].completed.timestamp) < $scope.dateSearch.startDate)) {
                                continue;
                            }
                        } else if (!$scope.dateSearch.startDate && $scope.dateSearch.endDate) {
                            if ((new Date(info[j].started.timestamp) > $scope.dateSearch.endDate &&
                                    (searchType === "All" || searchType === "Active")) ||
                                (info[j].completed && searchType === "Completed" &&
                                    new Date(info[j].completed.timestamp) > $scope.dateSearch.endDate)) {
                                continue;
                            }
                        } else if ($scope.dateSearch.startDate && $scope.dateSearch.endDate) {
                            if (((new Date(info[j].started.timestamp) < $scope.dateSearch.startDate ||
                                    new Date(info[j].started.timestamp) > $scope.dateSearch.endDate) && searchType === "All") ||
                                (info[j].completed && searchType === "Completed" &&
                                    (new Date(info[j].completed.timestamp) > $scope.dateSearch.endDate ||
                                        new Date(info[j].completed.timestamp) < $scope.dateSearch.startDate))) {
                                continue;
                            } else if (searchType === "All" && (new Date(info[j].started.timestamp) > $scope.dateSearch.endDate ||
                                (info[j].completed && new Date(info[j].completed.timestamp) < $scope.dateSearch.startDate))) {
                                continue;
                            }
                        }
                    }
                    outNodes.push(nodes[j]);
                }
                return outNodes.sort(compareTime);
            }

            function compareTime(node1, node2) {
                var revOrder = 1;
                if ($scope.tabData.sortOrder === 'Earliest First') {
                    revOrder = -1;
                }
                if ($scope.tabData.sortType === 'Time Completed') {
                    if (!node2.completed && node1.completed) {
                        return revOrder;
                    } else if (node2.completed && !node1.completed) {
                        return -1 * revOrder;
                    } else if (node2.completed && node1.completed) {
                        return revOrder * (new Date(node2.completed.timestamp).getTime() - new Date(node1.completed.timestamp).getTime());
                    }
                }
                return revOrder * (new Date(node2.started.timestamp).getTime() - new Date(node1.started.timestamp).getTime());
            }

            function recursiveSort(nodes) {
                nodes.sort(compareTime);
                for (var i = 0; i < nodes.length; i++) {
                    if (nodes[i].items && nodes[i].items.length) {
                        recursiveSort(nodes[i].items);
                    }
                }
            }

            $scope.$watch('tabData.sortOrder + tabData.sortType', function() {
                if ($scope.tabData.data && $scope.tabData.data.items) {
                    recursiveSort($scope.tabData.data.items)
                }
            });



            $scope.$watch('journeyFilter.durationStyle', function(newValue) {
                // used to watch the filter select menu . If select all is clicked,
                // uncheck everything else.
                // also updates timeline accordingly.

                if ($scope.journeyFilter.timeLineReady)
                    $scope.journeyFilter.updateTimeline();

            }, true);



            $scope.getAttribute = function() {
                if ($scope.tabData.node.type === 'Task') {
                    return $scope.tabData.taskAttributes;
                } else if ($scope.tabData.node.type === 'State') {
                    return $scope.tabData.stateAttributes;
                }
                return $scope.tabData.serviceAttributes;
            }

            // Parsing the mapping into format that the toolbar will use
            $scope.toolBarFilterOptions = [];

            for (var item in $scope.searchOptions) {
                var newObject = {};
                newObject.label = item;
                newObject.value = $scope.searchOptions[item];
                $scope.toolBarFilterOptions.push(newObject);
            };

            // Model for the toolbar
            $scope.toolbarItems = {
                theme: 'light',
                toolbarContainer: 'toolbar',
                leftButtonContainer: 'call-recording-toolbar-buttons',
                rightButtonContainer: 'call-recording-toolbar-buttons',
                lefttoolbar: [{
                    nonClickable: true,
                    select: {
                        options: "filterOption.value as filterOption.label for filterOption in toolBarFilterOptions",
                        placeholder: "Search Field",
                        value: 'PhoneNumber'
                    }
                }, {
                    nonClickable: true,
                    input: {
                        icon: 'fonticon icon-search',
                        id: 'search-box',
                        className: 'my-search-box',
                        placeholder: "Search",
                        eventHandlers: [{
                            handlerName: "keyup",
                            handler: function(e) {
                                var _event = e || $window.event;
                                var keyCode = _event.keyCode || _event.which;
                                if (keyCode === 13) {
                                    if ($scope.toolbarItems.lefttoolbar[1].input.value !== '') {
                                        $scope.multipleResults = false;
                                        // still searching used to avoid lag where it shows the
                                        // timeline prematurely
                                        $scope.stillSearching = true;
                                        $scope.clientFound = false;
                                        $scope.stateObj.clicked = false;
                                        $scope.stateObj.focusOn = "KPIs";
                                        $scope.showCustomerInfo = false;
                                        $scope.tabData.customerId = null;
                                        var searchItem = $scope.toolbarItems.lefttoolbar[1].input.value;
                                        var theQueryValue = $scope.toolbarItems.lefttoolbar[0].select.value;
                                        $scope.filterFunction(theQueryValue, searchItem);
                                        $scope.searching = true;
                                    }
                                    return false;
                                } else {
                                    return true;
                                }
                            }
                        }],
                        value: ''
                    }
                }],
            };

            // code below for table component in Journey Details. Similar to ngGrid paging. 

            $scope.setData = function(data) {
                $scope.myData = data;

                $scope.totalServerItems = data.length;

                if (!$scope.$$phase) {
                    $scope.$apply();
                }
            };

            //code below used to sort journey detail table
            $scope.sortParameter = 'key';
            $scope.reverse = true;
            $scope.orderJourneyDetails = function(sortParameter) {
                $scope.reverse = ($scope.sortParameter === sortParameter) ? !$scope.reverse : false;
                $scope.sortParameter = sortParameter;
            };

            $scope.stateObj.getData = function() {
                //attached to stateObj so it may be called when a state is clicked.

                var data;
                if ($scope.journeyStats.selectedAService && $scope.stateObj.focusOn !== "state") {
                    data = $scope.formatForGrid($scope.clickedServiceObj.started, $scope.clickedServiceObj.completed, $scope.customServiceInfo)

                    $scope.setData(data);
                } else if ($scope.journeyStats.selectedAService) {
                    data = $scope.formatForGrid($scope.stateObj.started, $scope.stateObj.completed, $scope.stateObj.custom)

                    $scope.setData(data);
                }


            };

            $scope.stateObj.getData();

            $scope.$watch('filterOptions', function(newVal, oldVal) {
                if (newVal !== oldVal) {
                    $scope.stateObj.getData();
                }
            }, true);
            $scope.$watch('stateObj.focusOn', function(newVal, oldVal) {
                if (newVal === 'service' && oldVal === 'state') {
                    // refresh table when we go from state to service in journey details 
                    $scope.stateObj.getData();
                }
            }, true);

            $scope.formatForGrid = function(started, completed, custom) {
                //table takes an array of objects, so this just formats an object to an array of objects
                // using the properties. To change the table headings just rename .key and .value to the intended name.

                var objArray = [];
                var i = 0;
                var startedLabel = "";
                if (completed)
                    startedLabel = " started"

                for (var prop in started) {
                    var tmpObj = {};
                    tmpObj.key = prop + startedLabel;
                    tmpObj.value = started[prop].toString();

                    objArray[i] = tmpObj;
                    i++;
                }

                if (completed) {
                    for (var prop in completed) {
                        var tmpObj = {};
                        tmpObj.key = prop + ' completed';
                        tmpObj.value = completed[prop].toString();

                        objArray[i] = tmpObj;
                        i++;
                    }

                }

                if (custom) {
                    for (var prop in custom) {
                        var tmpObj = {};
                        tmpObj.key = prop;
                        tmpObj.value = custom[prop].toString();

                        objArray[i] = tmpObj;
                        i++;
                    }

                }
                return objArray;
            };
            // table code ends. 

            $scope.selectedCustomer = {};

            $scope.itemClicked = function(selectedItem) {
                $scope.selectedCustomer = selectedItem;
                $scope.resetFilters();
                $scope.journeyFilter.durationStyle = 'both';
                $scope.journeyStats.selectedClient = selectedItem.customer_id; // used to track which customer clicked
                $scope.statesExist = false; // initalize states exist which is used for the interaction timeline						
                $scope.tabData.queryById('customer_id', $scope.selectedCustomer['customer_id'], $scope.customerQueryType);
                $scope.multipleResults = false;
                $scope.showCustomerInfo = true;
                $scope.refreshedForNavbar = false;
            };

            $scope.resizeFix = function() {
                /*
                 * used to fix weird glitch where the blue navbar on the
                 * timeline would go all the way to the left and only resizing
                 * the window will fix.
                 */
                if (!(false || !!document.documentMode)) {
                	var evt = window.document.createEvent('UIEvents'); 
                	evt.initUIEvent('resize', true, false, window, 0); 
                	window.dispatchEvent(evt);
                };
                $scope.refreshedForNavbar = true;
            };

            $scope.openFilterModal = function() {
                $modal.open({
                    templateUrl: 'app/modules/context-services/journey-dashboard/filter-template.html',
                    controller: 'filterCtrl',
                    resolve: {
                        journeyFilter: function() {
                            return $scope.journeyFilter;
                        }
                    }
                });
            };


            $scope.displayOptionsTable = function(data) {
                $scope.customerQueryType = $scope.toolbarItems.lefttoolbar[0].select.value;
                $scope.customerList = data;
                $scope.multipleResults = true;
                for (var i = 0; i < $scope.customerProperties.length; i++) {
                    var showProperty = false;
                    for (var j = 0; j < $scope.customerList.length; j++) {
                        if ($scope.customerList[j][$scope.customerProperties[i].label]) {
                            showProperty = true;
                        }
                    }
                    $scope.customerProperties[i].showProperty = showProperty;
                }
                $scope.stillSearching = false;
                $scope.searching = false;
            };

            $scope.parseValue = function(value, label) {
                if (angular.isArray(value)) {
                    // so that editing value does not affect unParsedValues, we copy. 
                    $scope.unParsedValues[label] = angular.copy(value);

                    var stringified = '';
                    value[0] += ' (main)'
                    for (var i = 0; i < value.length - 1; i++) {
                        stringified += value[i] + ", ";
                    }
                    stringified += value[value.length - 1];
                    return stringified;
                } else {
                    if ($scope.contactsCategoryInfo.indexOf(label) !== -1)
                        $scope.contactInfoList = value;
                    return value;
                }
            };

            $scope.closeTable = function() {
                $scope.multipleResults = false;
                $scope.toolbarItems.lefttoolbar[1].input.value = '';
            };

            $scope.filterFunction = function(queryType, searchText) {
                var callbackFunction = function(resultFound) {
                    $scope.searching = false;
                    if (resultFound.length > 1) {
                        var customers = [];
                        for (var i = 0; i < resultFound.length; i++) {
                            var object = {};
                            object = $scope.getCustomerProperties(resultFound[i]);
                            customers.push(object);
                        }
                        $scope.displayOptionsTable(customers);
                    } else if (resultFound.length == 1) {
                        $scope.selectedCustomer = $scope.getCustomerProperties(resultFound[0]);
                        $scope.showCustomerInfo = true;
                        $scope.tabData.queryById($scope.primaryKey.label, $scope.selectedCustomer[$scope.primaryKey.label], queryType);
                    } else {
                        // If searching through all the fields fail, try using the
                        // searchtext as
                        // a customer_id. [Part of the specifications]
                        if (queryType === '') {
                            queryType = $scope.primaryKey.label;
                            $scope.getCustomerInfo(searchText);
                            $scope.tabData.queryById(queryType, searchText);
                        } else {
                            $scope.queryFeedback = 'No Customer exists with "' + searchText +
                                '" as the ' + getSearchLabel(queryType);
                        }
                    }
                };

                var getSearchLabel = function(item) {
                    var toReturn = '';
                    angular.forEach($scope.mapping, function(value, key) {
                        if (item === value) {
                            toReturn = key;
                        }
                    });
                    return toReturn;
                }

                // if query type is customer id, or anonymous id, just search for
                // services
                // directly else if no query type is given try all possible query
                // options
                // and see if you will get a customer_id. Else, use the exact query type
                // to
                // get a customer_id.
                if (queryType === $scope.primaryKey.label) {
                    $scope.getCustomerInfo(searchText);
                    $scope.tabData.queryById(queryType, searchText);
                    if (!$scope.selectedCustomer[$scope.primaryKey.label]) {
                        $scope.selectedCustomer[$scope.primaryKey.label] = $scope.entityId;
                    }
                } else if (queryType === 'Anonymous ID') {
                    $scope.tabData.queryById(queryType, searchText);
                    $scope.selectedCustomer = {};
                    $scope.selectedCustomer['anonymous_id'] = searchText;
                } else if (queryType === '') {
                    $scope.getAllPossibleResults(searchText, callbackFunction);
                } else {
                    $scope.getResult(searchText, queryType, callbackFunction);
                }
            };

            // Used to fetch customer Information provided the user has the primary
            // key of the customer
            $scope.getCustomerInfo = function(id) {
                var object = {};
                var extensionsArray = [];
                var hasExtensions = false;

                for (var option in $scope.extraQueryOptions) {
                    object[option] = $scope.extraQueryOptions[option];
                }
                if (!$scope.customExEmpty && $scope.extensionsList && $scope.extensionsList.length > 0) { // if custom extensions are defined...
                    for (var extension in $scope.extensionsList) { //loops through extensions list
                        for (var x = 0; x < $scope.customerProperties.length; x++) { //loops through customer properties
                            if ($scope.extensionsList[extension].name == $scope.customerProperties[x].label) { //verify that extension is in customer properties (from configuration.json);
                                hasExtensions = true;
                                extensionsArray.push($scope.extensionsList[extension].name);
                            }
                        }
                        // extensionsArray.push($scope.extensionsList[extension].name);
                    }
                    if (hasExtensions) { //will only add the extensions parameter if there is at least one extenions. Will only query for extensions that are in the user's configuration.json
                        object['extensions'] = extensionsArray.join(',');
                    }
                }

                csApi.queryCustomerProfileById($scope.baseUrl, id, object).then(function(httpRespose) {
                        $scope.selectedCustomer = $scope.getCustomerProperties(httpRespose.data);

                        if (!$scope.selectedCustomer[$scope.primaryKey.label]) {
                            $scope.selectedCustomer[$scope.primaryKey.label] = $scope.entityId;
                        }
                    },
                    function(error) {
                        $scope.queryFeedback = error;
                        toaster.pop(error);
                    });
            };

            // Search for a customer that has the searchText value in the specific
            // queryType field and get the customer_id
            $scope.getResult = function(searchText, queryType, resultHandler) {
                var object = {};
                var extensionsArray = [];
                var hasExtensions = false;

                object[queryType] = searchText;
                for (var option in $scope.extraQueryOptions) {
                    object[option] = $scope.extraQueryOptions[option];
                }
                if (!$scope.customExEmpty && $scope.extensionsList && $scope.extensionsList.length > 0) { // if custom extensions are defined...
                    for (var extension in $scope.extensionsList) { //loops through extensions list
                        for (var x = 0; x < $scope.customerProperties.length; x++) { //loops through customer properties
                            if ($scope.extensionsList[extension].name == $scope.customerProperties[x].label) { //verify that extension is in customer properties (from configuration.json);
                                hasExtensions = true;
                                extensionsArray.push($scope.extensionsList[extension].name);
                            }
                        }
                        // extensionsArray.push($scope.extensionsList[extension].name);
                    }
                    if (hasExtensions) { //will only add the extensions parameter if there is at least one extenions. Will only query for extensions that are in the user's configuration.json
                        object['extensions'] = extensionsArray.join(',');
                    }
                }

                csApi.queryCustomerProfiles($scope.baseUrl, object).then(function(httpRespose) {
                        if (resultHandler) {
                            resultHandler(httpRespose.data);
                        }
                    },
                    function(error) {
                        $scope.queryFeedback = error;
                    });
            };

            // Used to get only the required Customer Properties as specified
            // in the config file for the disambiguation table
            $scope.getCustomerProperties = function(key) {
                var customer = {};
                for (var i = 0; i < $scope.customerProperties.length; i++) {
                    var label = $scope.customerProperties[i].label;
                    if (!$scope.PropertyIsMultivalued(CUSTOM_EXTENSIONS.Multivalued, label))
                        var propertyToBeParsed = key[label];

                    if (propertyToBeParsed === undefined) {
                        // case where we have a custom property defined.
                        for (var j in $scope.extensionsList) {
                            var extension = $scope.extensionsList[j].name;

                            if (key[extension] !== undefined) {
                                if (key[extension].hasOwnProperty(label)) {
                                    var customObj = key[extension];
                                    propertyToBeParsed = customObj[label];
                                    break;
                                } else if (key[extension].constructor === Array && $scope.PropertyIsMultivalued(CUSTOM_EXTENSIONS.Multivalued, extension)) {
                                    customer[extension] = key[extension];
                                    $scope.tableValueExists[$scope.customerProperties[i].label] = false;
                                }
                            }
                        }
                    }

                    if (propertyToBeParsed !== undefined)
                        customer[$scope.customerProperties[i].label] = $scope.parseValue(propertyToBeParsed, $scope.customerProperties[i].label);

                    // if and else below are used to determine if there should be a column made when the search returns more than one customer. 

                    if (customer[$scope.customerProperties[i].label] === undefined && $scope.tableValueExists[$scope.customerProperties[i].label] !== true) {
                        $scope.tableValueExists[$scope.customerProperties[i].label] = false;
                    } else if (customer[$scope.customerProperties[i].label] !== undefined) {
                        if (customer[$scope.customerProperties[i].label].constructor === Array) // case for multivalued, we dont show. 
                            $scope.tableValueExists[$scope.customerProperties[i].label] = false;
                        else
                            $scope.tableValueExists[$scope.customerProperties[i].label] = true;
                    } else {
                        $scope.tableValueExists[$scope.customerProperties[i].label] = true;
                    }
                }
                return customer;
            }

            $scope.PropertyIsMultivalued = function(objArray, property) {
                for (var i in objArray) {
                    if (objArray[i].label === property)
                        return true;
                }
                return false;
            };

            $scope.resetFilters = function() {
                $scope.journeyFilter.statusFilters = ['Select All'];
                $scope.journeyFilter.serviceTypeFilter = ['Select All'];
                $scope.journeyFilter.stateTypeFilter = ['Select All'];

                $scope.journeyFilter.dateFilter = 'Show All';
                $scope.journeyFilter.dateFilterType = "Starting";

                $scope.journeyFilter.fromDate = null;
                $scope.journeyFilter.toDate = null;
            };

            $scope.filterIsApplied = function() {
                if ($scope.journeyFilter.statusFilters[0] === 'Select All' && $scope.journeyFilter.serviceTypeFilter[0] === 'Select All' && $scope.journeyFilter.stateTypeFilter[0] === 'Select All' && ($scope.journeyFilter.search === undefined || $scope.journeyFilter.search.length === 0)) {
                    if ($scope.journeyFilter.toDate === null && $scope.journeyFilter.fromDate === null && $scope.journeyFilter.dateFilter === 'Custom Range')
                        return false; // no filter applied
                    if ($scope.journeyFilter.dateFilter === 'Show All')
                        return false;
                }

                return true;
            };

            $scope.findExtName = function(data) {
                // digs for the extension name in the object.

                if (data.constructor === Array) {
                    // if we have an array (probably when multiple results and the multiple results table is needed)
                    for (var i in data) {
                        var customerobj = data[i]
                        for (var k in $scope.extensionsList) {
                            var extensionName = $scope.extensionsList[k].name;
                            if (customerobj[extensionName] !== undefined)
                                return extensionName;
                        }
                    }
                } else {
                    // it's an object, or one customer only (probably from directed search through customer id)
                    for (var k in $scope.extensionsList) {
                        var extensionName = $scope.extensionsList[k].name
                        if (data[extensionName] !== undefined)
                            return extensionName;
                    }
                }

            };

            // Used to add 's'(pluralize) customer properties in the case that there is
            // more than one item for this property
            $scope.pluralizeProperty = function(property, propertyKey) {
                if (angular.isDefined(property)) {
                    if (property.toString().indexOf(', ') === -1) {
                        return '';
                    } else {

                        if (propertyKey.indexOf('s', propertyKey.length - 1) !== -1) {
                            return 'es';
                        }
                        return 's';
                    }
                } else {
                    return '';
                }
            };

            $scope.anArray = function(data) {
                //checks if variable is an array
                if (data === undefined || data === null)
                    return false;
                else
                    return (data.constructor === Array)

            };

            $scope.objectValuesToArray = function(obj) {
                //turns an object into an array using its values
                var arr = [];
                for (var i in obj) {
                    arr.push(obj[i]);
                }

                return arr;
            };

            //get distribution of services
            $scope.getJourneyDistribution = function() {
                var services = [];
                if ($scope.tabData.data && $scope.tabData.data.items) {
                    services = $scope.tabData.data.items;
                }

                var array = [];

                var createActArray = function(object) {
                    this.label = object.entityString;
                    this.completed = 0;
                    this.active = 1;
                }

                var createCompArray = function(object) {
                    this.label = object.entityString;
                    this.completed = 1;
                    this.active = 0;
                }

                for (var i = 0; i < services.length; i++) {
                    if (services[i].completed) {
                        if (!array.length) {
                            array.push(new createCompArray(services[i]));
                        } else {
                            var bool = false
                            for (var j = 0; j < array.length; j++) {
                                if (services[i].entityString == array[j].label) {
                                    array[j].completed++;
                                    bool = true;
                                }
                            }
                            if (!bool) {
                                array.push(new createCompArray(services[i]));
                            }
                        }
                    } else {
                        if (!array.length) {
                            array.push(new createActArray(services[i]));
                        } else {
                            var bool = false;
                            for (var j = 0; j < array.length; j++) {
                                if (services[i].entityString == array[j].label) {
                                    array[j].active++;
                                    bool = true;
                                }
                            }
                            if (!bool) {
                                array.push(new createActArray(services[i]));
                            }
                        }
                    }
                }

                return array;
            }

            $scope.$watch('stateObj.focusOn', function() {
                $scope.serviceDist = $scope.getJourneyDistribution();
                $scope.allMedia = $scope.queryAllMediaTypeStats();
            })

            $scope.getKPIJourneyProperties = function(KPI) {
                //gets service  related statistics. 
                if (!$scope.refreshedForNavbar)
                    $scope.resizeFix(); // to fix navbar


                var result = $scope.noInfoLabel;

                if (KPI.toLowerCase() === 'total journeys') {
                    result = $scope.journeyStats.nbJourneys;
                } else if (KPI.toLowerCase() === 'avg journey resolution time') {
                    if ($scope.journeyStats.average != 'Cannot calculate')
                        result = $scope.aboutLabel + " " + $scope.journeyStats.average;

                    else if ($scope.journeyStats.activeJourneys > 0 && $scope.journeyStats.completedJourneys === 0)
                        result = $scope.onlyActiveJourneysLabel;

                    else if ($scope.journeyStats.activeJourneys === 0 && $scope.journeyStats.completedJourneys === 0)
                        result = $scope.noJourneysLabel;

                    else
                        result = $scope.journeyStats.average;

                } else if (KPI.toLowerCase() === 'active journeys') {
                    result = $scope.journeyStats.activeJourneys;
                } else if (KPI.toLowerCase() === 'completed journeys') {
                    result = $scope.journeyStats.completedJourneys;
                }

                return result;
            }

            $scope.getKPIStateProperties = function(KPI) {
                // gets state related statistics

                var result = $scope.noInfoLabel;
                var serviceArray = $scope.tabData.data.items;

                // for counting states
                var journeyCounter = 0;
                var activeCounter = 0;
                var completedCounter = 0;

                // for average
                var totalDuration = 0;

                for (var service in serviceArray) {
                    var stateArray = serviceArray[service];
                    activeCounter += stateArray.active_states.length;
                    completedCounter += stateArray.completed_states.length;

                    // below for average resolution time
                    if (stateArray.completed_states.length !== 0 && KPI.toLowerCase() === 'avg state resolution time') {
                        for (var completedState in stateArray.completed_states) {
                            var stateBeginDate = stateArray.completed_states[completedState].started.timestamp;
                            var stateEndDate = stateArray.completed_states[completedState].completed.timestamp;

                            // just some formatting to get the difference cleaner.
                            stateEndDate = moment(stateEndDate).format("YYYY MM DD");
                            stateBeginDate = moment(stateBeginDate).format("YYYY MM DD");

                            stateEndDate = new Date(stateEndDate);
                            stateBeginDate = new Date(stateBeginDate);

                            var stateDuration = stateEndDate - stateBeginDate;
                            totalDuration += stateDuration;
                        }
                    }
                }

                journeyCounter = activeCounter + completedCounter

                if (KPI.toLowerCase() === 'total states') {
                    result = journeyCounter;
                } else if (KPI.toLowerCase() === 'avg state resolution time') {
                    var avgTime = $scope.journeyStats.convertToReadableDate(totalDuration / completedCounter);

                    if (avgTime !== "Cannot calculate" && completedCounter > 0)
                        result = $scope.aboutLabel + " " + avgTime;

                    else if (activeCounter > 0 && completedCounter === 0)
                        result = $scope.onlyActiveStatesLabel;

                    else if (activeCounter === 0 && completedCounter === 0)
                        result = $scope.noStatesLabel;

                    else {
                        result = avgTime;
                    }
                } else if (KPI.toLowerCase() === 'active states') {
                    result = activeCounter;
                } else if (KPI.toLowerCase() === 'completed states') {
                    result = completedCounter;
                } else if (KPI.toLowerCase() === 'avg specific') {

                }

                return result;
            }


            $scope.journeyStats.convertToReadableDate = function(miliTime) {
                // converts miliseconds to a readable format. In hours if less than 24,
                // in days otherwise.

                if (isNaN(miliTime))
                    return $scope.cannotCalculateLabel;

                var result = '';
                var seconds = miliTime / 1000;
                var minutes = seconds / 60;
                var hours = minutes / 60;

                if (minutes < 60) {
                    minutes = Math.round(minutes);
                    result = minutes + ' ' + $scope.minutesLabel;
                } else {
                    if (hours > 24) {
                        var days = Math.round(hours / 24);
                        result = days + ' ' + $scope.daysLabel;

                    } else {
                        hours = Math.round(hours)
                        result = hours + ' ' + $scope.hoursLabel;
                    }
                }

                return result;

            };

            $scope.journeyStats.getTotalStates = function(serviceid) {
                //counts the total states for a given servive 
                var serviceArray = $scope.tabData.data.items;
                for (var service in serviceArray) {
                    var stateArray = serviceArray[service];
                    if (serviceArray[service].service_id === serviceid)
                        return (stateArray.active_states.length + stateArray.completed_states.length);
                }
            };


            $scope.journeyStats.updateDetails = function(clickedService) {
                // updates journey details when a new service is clicked. 
                // Attached to journeyStats so that it can be called from timeline when a service is clicked.
                $scope.clickedServiceObj = clickedService;
                $scope.journeyStats.selectedAService = true;
                $scope.stateObj.clicked = false;
                $scope.stateObj.focusOn = "service";
                $scope.stateObj.id = "";

                $scope.customServiceInfo = undefined; // assume no custom info initially.

                if (!$scope.refreshedForNavbar)
                    $scope.resizeFix(); // to fix navbar

                if (clickedService.entityString)
                    $scope.serviceNameLabel = clickedService.entityString;
                else
                    $scope.serviceNameLabel = clickedService.entityType;

                $scope.currentlySelectedService = $scope.serviceNameLabel;
                $scope.serviceNameLabel = "Timeline for " + $scope.serviceNameLabel;

                $scope.clickedActiveStateLength = clickedService.active_states.length;
                $scope.clickedActiveTasksLength = clickedService.active_tasks.length;

                $scope.stateObj.activeTasksLength = clickedService.active_tasks.length; // might as well assign it to state object incase it gets used

                $scope.clickedDateStarted = moment(clickedService.started.timestamp).format("MMM Do YYYY");
                var startingDate = new Date(clickedService.started.timestamp);

                if (clickedService.completed) {
                    var endingDate = new Date(clickedService.completed.timestamp)

                    $scope.clickedDuration = $scope.journeyStats.convertToReadableDate(Math.abs(endingDate - startingDate));
                    $scope.durationMillis = Math.abs(endingDate - startingDate);
                    $scope.clickedDateCompleted = moment(clickedService.completed.timestamp).format("MMM Do YYYY");

                } else {

                    var endingDate = new Date();
                    $scope.clickedDuration = $scope.journeyStats.convertToReadableDate(Math.abs(endingDate - startingDate));
                    $scope.durationMillis = Math.abs(endingDate - startingDate);
                    $scope.clickedDateCompleted = $scope.serviceNotDoneLabel;

                }

                $scope.clickedCompletedStatesLength = clickedService.completed_states.length;
                $scope.clickedCompletedTasksLength = clickedService.active_tasks.length;
                $scope.stateObj.completedTasksLength = clickedService.active_tasks.length;

                // used to decide whether to show interaction timeline or not.
                $scope.statesExist = $scope.clickedActiveStateLength || $scope.clickedCompletedStatesLength;
                $scope.checkServiceExtension(clickedService.service_id, clickedService.completed !== undefined);
            };

            $scope.checkServiceExtension = function(serviceID, serviceCompleted) {
                // checks start service extension and end service extension
                // which then gets displayed under journey details. 

                var jsonService = {
                    active_tasks: true,
                    completed_tasks: true,
                    active_states: true,
                    completed_states: true,
                    extensions: "*"
                };

                csApi.queryServiceById($scope.baseUrl, serviceID, jsonService).then(function(httpResponse) {
                    var startService = httpResponse.data;

                    $scope.customServiceInfo = startService["customstart"]; // all custom key value pairs in custom. 

                    if (startService.customcomplete !== undefined) {
                        if ($scope.customServiceInfo !== undefined) {
                            for (var attrname in startService.customcomplete) {
                                $scope.customServiceInfo[attrname] = startService.customcomplete[attrname];
                            }
                        } else
                            $scope.customServiceInfo = startService.customcomplete;
                    }

                    $scope.stateObj.getData(); // placed here because checkServiceExtension is asynchronous	
                });
            };


            $scope.getSpecificStateAverage = function(stateInput) {
                var cumulativeStateDuration = 0;
                var state = 0;
                var journey = 0;
                var stateCounter = 0;

                for (journey in $scope.tabData.data.items) {
                    for (state in $scope.tabData.data.items[journey].completed_states) {
                        //get duration of completed states and add it to cumulative duration
                        if ($scope.tabData.data.items[journey].completed_states[state].entityString == stateInput || ($scope.tabData.data.items[journey].entityType == stateInput)) {
                            cumulativeStateDuration += $scope.tabData.data.items[journey].completed_states[state].duration;
                            stateCounter++;
                        }
                    }
                }

                return cumulativeStateDuration / (stateCounter);
            };

            $scope.getSpecificServiceAverage = function(serviceInput) {
                var cumulativeServiceDuration = 0;
                var service = 0;
                var serviceCounter = 0;
                if ($scope.tabData.data) {
                    for (service in $scope.tabData.data.items) {
                        //get duration of completed services and add it to cumulative duration
                        if ($scope.tabData.data.items[service].entityString == serviceInput || ($scope.tabData.data.items[service].entityType == serviceInput)) {
                            if (typeof $scope.tabData.data.items[service].completed !== "undefined")
                                cumulativeServiceDuration += Math.abs(Date.parse($scope.tabData.data.items[service].started.timestamp) - Date.parse($scope.tabData.data.items[service].completed.timestamp));
                            else
                                cumulativeServiceDuration += Math.abs(Date.parse($scope.tabData.data.items[service].started.timestamp) - Date.parse(Date()));
                            serviceCounter++;

                        }
                    }
                }
                return cumulativeServiceDuration / (serviceCounter);
            };

            $scope.queryMediaTypeStats = function(serviceInput) {
                var mediaType = []; //used to store all existing state media types within a service
                if ($scope.tabData.data) {
                    for (var service in $scope.tabData.data.items) {
                        if (($scope.tabData.data.items[service].entityString == serviceInput) || ($scope.tabData.data.items[service].entityType == serviceInput)) {
                            for (var completedstate in $scope.tabData.data.items[service].completed_states) {
                                mediaType.push($scope.tabData.data.items[service].completed_states[completedstate].completed.media_type);
                                mediaType.push($scope.tabData.data.items[service].completed_states[completedstate].started.media_type);
                            }
                            for (var activestate in $scope.tabData.data.items[service].active_states) {
                                mediaType.push($scope.tabData.data.items[service].active_states[activestate].started.media_type);
                            }
                        }
                    }
                }

                var media = []; //used to store media type and it's number of occurences within the service
                var mediaQuantities = []; //array of only the quantities of the media types
                var mediaValues = []; //array of only the media type values

                var mediaConstructor = function(name, amount) {
                    this.value = name;
                    this.quantity = amount;
                }

                for (var j = 0; j < mediaType.length; j++) {
                    var number = mediaType[j];
                    var check = false;
                    if (media.length > 0) {
                        for (var i = 0; i < media.length; i++) {
                            if (number == media[i].value) {
                                media[i].quantity++;
                                check = true;
                            }
                        }
                    }
                    if (!check) {
                        media.push(new mediaConstructor(number, 1));
                    }
                }

                for (item in media) {
                    var counter = 0;
                    for (type in $scope.businessProperties[0].values) {
                        if ($scope.businessProperties[0].values[type].dbid == media[item].value) {
                            mediaQuantities.push(media[item].quantity);
                            mediaValues.push($scope.businessProperties[0].values[type].display_name[0].toUpperCase() + $scope.businessProperties[0].values[type].display_name.slice(1));
                        }
                    }
                    if (media[item].value == undefined) {
                        mediaQuantities.push(media[item].quantity);
                        mediaValues.push('No Media Type Defined');
                    }
                }

                if (JSON.stringify($scope.mediaNumbers) == JSON.stringify(mediaQuantities)) {
                    $scope.mediaDonutConfig.data.labels = mediaValues;
                    $scope.mediaDonutConfig.legend.title = mediaValues;
                    return $scope.mediaNumbers;
                } else {
                    $scope.mediaNumbers = mediaQuantities;
                    $scope.mediaDonutConfig.data.labels = mediaValues;
                    $scope.mediaDonutConfig.legend.title = mediaValues;
                    $scope.donutTimeout = false;
                    $timeout(function() {
                        $scope.donutTimeout = true
                    });
                    return mediaQuantities;
                }
            };

            $scope.queryAllMediaTypeStats = function() {

                var mediaType = []; //used to store all existing state media types within a service

                if ($scope.tabData.data) {
                    for (var service in $scope.tabData.data.items) {
                        for (var completedstate in $scope.tabData.data.items[service].completed_states) {
                            mediaType.push($scope.tabData.data.items[service].completed_states[completedstate].completed.media_type);
                            mediaType.push($scope.tabData.data.items[service].completed_states[completedstate].started.media_type);
                        }
                        for (var activestate in $scope.tabData.data.items[service].active_states) {
                            mediaType.push($scope.tabData.data.items[service].active_states[activestate].started.media_type);
                        }
                    }
                }

                var media = []; //used to store media type and it's number of occurences within the service
                var mediaQuantities = []; //array of only the quantities of the media types
                var mediaValues = []; //array of only the media type values

                var mediaConstructor = function(name, amount) {
                    this.value = name;
                    this.quantity = amount;
                }

                for (var j = 0; j < mediaType.length; j++) {
                    var number = mediaType[j];
                    var check = false;
                    if (media.length > 0) {
                        for (var i = 0; i < media.length; i++) {
                            if (number == media[i].value) {
                                media[i].quantity++;
                                check = true;
                            }
                        }
                    }
                    if (!check) {
                        media.push(new mediaConstructor(number, 1));
                    }
                }

                for (item in media) {
                    var counter = 0;
                    for (type in $scope.businessProperties[0].values) {
                        if ($scope.businessProperties[0].values[type].dbid == media[item].value) {
                            mediaQuantities.push(media[item].quantity);
                            mediaValues.push($scope.businessProperties[0].values[type].display_name[0].toUpperCase() + $scope.businessProperties[0].values[type].display_name.slice(1));
                        }
                    }
                    if (media[item].value == undefined) {
                        mediaQuantities.push(media[item].quantity);
                        mediaValues.push('No Media Type Defined');
                    }
                }

                $scope.mediaDonutConfig.data.labels = mediaValues;
                $scope.mediaDonutConfig.legend.title = mediaValues;
                return mediaQuantities;
            };

            $scope.$watch('clickedServiceObj', function() {
                $scope.bgValues = $scope.returnDistribution();
            })

            $scope.returnDistribution = function() {
                var activeStates = [];
                var compStates = [];

                if ($scope.clickedServiceObj) {
                    activeStates = $scope.clickedServiceObj.active_states;
                    compStates = $scope.clickedServiceObj.completed_states;
                }

                var array = [];

                var createActArray = function(object) {
                    this.label = object.entityString;
                    this.completed = 0;
                    this.active = 1;
                }

                var createCompArray = function(object) {
                    this.label = object.entityString;
                    this.completed = 1;
                    this.active = 0;
                }

                for (var act in activeStates) {
                    if (!array.length) {
                        array.push(new createActArray(activeStates[act]));
                    } else {
                        var bool = false;
                        for (var i = 0; i < array.length; i++) {
                            if (activeStates[act].entityString == array[i].label) {
                                array[i].active++;
                                bool = true;
                            }
                        }
                        if (!bool) {
                            array.push(new createActArray(activeStates[act]));
                        }
                    }
                }

                for (var comp in compStates) {
                    if (!array.length) {
                        array.push(new createCompArray(compStates[comp]));
                    } else {
                        var bool = false
                        for (var i = 0; i < array.length; i++) {
                            if (compStates[comp].entityString == array[i].label) {
                                array[i].completed++;
                                bool = true;
                            }
                        }
                        if (!bool) {
                            array.push(new createCompArray(compStates[comp]));
                        }
                    }
                }
                return array;
            }

            $scope.getServiceDetail = function(title) {

                // takes in a title and returns an appropriate service detail for journey details.
                if ($scope.customServiceInfo !== undefined && $scope.customServiceInfo[title])
                    return $scope.customServiceInfo[title]; //referring to a custom info.

                switch (title.toLowerCase()) { //referring to one of the statistics. 

                    case "active states":
                        return $scope.clickedActiveStateLength;

                    case "completed states":
                        return $scope.clickedCompletedStatesLength;

                    case "completed tasks":
                        return $scope.clickedCompletedTasksLength;

                    case "active tasks":
                        return $scope.clickedActiveTasksLength;

                    case "service started":
                        return $scope.clickedDateStarted;

                    case "service ended":
                        return $scope.clickedDateCompleted;

                    case "duration":
                        return $scope.clickedDuration;

                    case "deviation from average duration":
                        {
                            if ($scope.getSpecificServiceAverage($scope.currentlySelectedService) <= $scope.durationMillis)
                                return "+ " + $scope.journeyStats.convertToReadableDate(Math.abs($scope.getSpecificServiceAverage($scope.currentlySelectedService) - $scope.durationMillis));
                            else
                                return "- " + $scope.journeyStats.convertToReadableDate(Math.abs($scope.getSpecificServiceAverage($scope.currentlySelectedService) - $scope.durationMillis));
                        }
                    default:
                        /*for items in queried object:
				if title == items.name:
					read and return object value
		}*/
                        return $scope.noInfoLabel; // none found 
                }

            };

            $scope.getStateDetail = function(title) {
                // takes in a title and returns an appropriate state detail for state details.	
                if ($scope.stateObj.custom !== undefined && $scope.stateObj.custom[title])
                    return $scope.stateObj.custom[title]; //referring to a custom info.

                switch (title.toLowerCase()) { //referring to one of the statistics. 
                    case "date started":
                        return $scope.stateObj.beginDate.format("MMM Do YYYY");

                    case "date completed":
                    	if (typeof $scope.stateObj.finishDate === 'string') // State not yet completed
                    		return "";
                    	else
                            return $scope.stateObj.finishDate.format("MMM Do YYYY");
                    case "active tasks":
                        return $scope.stateObj.activeTasksCount;

                    case "completed tasks":
                        return $scope.stateObj.completedTasksCount;

                    case "media type":
                        {
                            for (type in $scope.businessProperties[0].values) {
                                if ($scope.businessProperties[0].values[type].dbid == $scope.stateObj.started.media_type) {
                                    return $scope.businessProperties[0].values[type].display_name[0].toUpperCase() + $scope.businessProperties[0].values[type].display_name.slice(1);
                                }
                            }
                            return "No Media Type Defined";
                        }

                    case "duration":
                        return $scope.journeyStats.convertToReadableDate(Math.abs($scope.stateObj.beginDate - $scope.stateObj.finishDate));

                    case "deviation from average duration":
                        {
                            if ($scope.getSpecificStateAverage($scope.stateObj.title) <= Math.abs($scope.stateObj.beginDate - $scope.stateObj.finishDate))
                                return "+ " + $scope.journeyStats.convertToReadableDate(Math.abs($scope.getSpecificStateAverage($scope.stateObj.title) - Math.abs($scope.stateObj.beginDate - $scope.stateObj.finishDate)));
                            else
                            if ($scope.stateObj.finishDate !== "State not yet completed")
                                return "- " + $scope.journeyStats.convertToReadableDate(Math.abs($scope.getSpecificStateAverage($scope.stateObj.title) - Math.abs($scope.stateObj.beginDate - $scope.stateObj.finishDate)));
                            else
                                return $scope.journeyStats.convertToReadableDate(Math.abs($scope.getSpecificStateAverage($scope.stateObj.title) - Math.abs($scope.stateObj.beginDate - $scope.stateObj.finishDate)));
                        }
                    case "duration_bar":
                        { //duration displayed on bar graph
                            if ($scope.stateObj.finishDate == "State not yet completed") {
                                var date = new Date()
                                return Math.abs(Math.round(($scope.stateObj.beginDate - date) / (60 * 60 * 24 * 1000)))
                            } else {
                                return Math.abs(Math.round(($scope.stateObj.beginDate - $scope.stateObj.finishDate) / (60 * 60 * 24 * 1000)));
                            }
                        }
                    default:
                        return $scope.noInfoLabel; // none found 	
                }
            };

            $scope.stateObj.resetStateDetails = function() {
                $scope.stateObj.custom = undefined;
            };


            $scope.getCustomerName = function() {
                var lastName = $scope.selectedCustomer['LastName'] || '';
                var fistName = $scope.selectedCustomer['FirstName'] || '';
                return {
                    key: 'customerName',
                    label: 'Customer Name',
                    value: lastName + ' ' + fistName
                };
            };

            $scope.shouldDisplay = function(key) {

                if (key === $scope.primaryKey.label || key === 'FirstName' || key === 'LastName') {
                    return false;
                } else {
                    return true;
                }
            }

            $scope.formatForContacts = function(label) {

                if ($scope.selectedCustomer[label] === undefined)
                    return false;

                if ($scope.contactsCategoryInfo.indexOf(label) !== -1 && $scope.selectedCustomer[label].indexOf('(main)') !== -1) {
                    // info belongs in contact information, time to format..

                    $scope.contactInfoList = $scope.unParsedValues[label];
                    return true;
                } else if ($scope.contactsCategoryInfo.indexOf(label) !== -1) {
                    $scope.contactInfoList = []; // made into an array so that
                    // ng-repeat does not repeat over
                    // characters.
                    $scope.contactInfoList[0] = $scope.selectedCustomer[label];
                    return true;
                } else
                    return false; // info does not belong in the Contact Information category
            };

            $scope.propertyInThisCategory = function(header, property) {
                // checks to see if property belongs in this category
                return PROFILE_CONFIG.CATEGORY_INFO[property] === header;
            };

            $scope.multiInThisCategory = function(header, property) {
                //checks to see if multivalue belongs to this category
                if (CUSTOM_EXTENSIONS.Multivalued === undefined)
                    return false;
                else
                    return CUSTOM_EXTENSIONS.Multivalued_category[property] === header;
            };

            $scope.getKPIIcon = function(info, header) {
                // gets the appropriate icon using the logic defined in the profileconfig.

                var propertiesList = PROFILE_CONFIG.KPI_ICON_LOGIC[header.toLowerCase()];

                if (propertiesList === undefined)
                    return undefined;

                for (var i in propertiesList) {

                    var properties = propertiesList[i];

                    var min = $scope.getKPIMin(header.toLowerCase(), properties);
                    var max = $scope.getKPIMax(header.toLowerCase(), properties);

                    var value = info;

                    if (isNaN(value)) {
                        var tmpvalue = info.match(/\d+/); // extracts number from string.
                        if (tmpvalue !== undefined && tmpvalue[0])
                            value = value[0]
                        else
                            value = '0';
                    }


                    if (max !== undefined && max >= value && min <= value && properties.icon !== undefined) {
                        return properties.icon;
                    } else if (max === undefined && min <= value && properties.icon !== undefined) {
                        return properties.icon;
                    }

                }

                return '';
            };

            $scope.getKPIColour = function(info, header) {
                //gets the icon colour from the logic defined in the profileconfig.
                var KPIIconColour = '';

                var propertiesList = PROFILE_CONFIG.KPI_ICON_LOGIC[header.toLowerCase()];

                if (propertiesList === undefined)
                    return undefined;

                for (var i in propertiesList) {

                    var properties = propertiesList[i];

                    var min = $scope.getKPIMin(header.toLowerCase(), properties);
                    var max = $scope.getKPIMax(header.toLowerCase(), properties);

                    var value = info;

                    if (isNaN(value)) {
                        var tmpvalue = info.match(/\d+/); // extracts number from string.
                        if (tmpvalue !== undefined && tmpvalue[0])
                            value = value[0]
                        else
                            value = '0';
                    }


                    if (max !== undefined && max >= value && min <= value && properties.icon !== undefined) {
                        return $scope.getArkColour(properties.colour);
                    } else if (max === undefined && min <= value && properties.icon !== undefined) {
                        return $scope.getArkColour(properties.colour);
                    }

                }

                return '';
            };

            $scope.getKPIMin = function(header, properties) {
                //gets the minimum value defined in the profileconfig
                if (properties === undefined)
                    return undefined;

                var range = properties.range;

                if (range !== undefined && range.indexOf('-') !== -1) {
                    var test = range.split("-")[0];
                    return test;
                } else if (range.indexOf('-') === -1)
                    return range; // only a min was defined.

                else
                    return undefined



            };

            $scope.getKPIMax = function(header, properties) {
                //gets the maximum value definedd in profileconfig

                if (properties === undefined)
                    return undefined;

                var range = properties.range;

                if (range !== undefined && range.indexOf('-') !== -1) {
                    return range.split("-")[1];
                } else
                    return undefined;
            };

            //gridster settings for the panel
            $scope.panels = [{
                name: "Main Timeline",
                size: {
                    x: 2,
                    y: 4
                },
                position: [0, 0]
            }, {
                name: "Info",
                size: {
                    x: 1,
                    y: 9
                },
                position: [1, 5]
            }, {
                name: "Interaction Timeline",
                size: {
                    x: 1,
                    y: 9
                },
                position: [1, 5]
            }];

            $scope.gridsterOpts = {
                columns: 2, // the width of the grid, in columns
                pushing: true, // whether to push other items out of the way on move or resize
                floating: true, // whether to automatically float items up so they stack (you can temporarily disable if you are adding unsorted items with ng-repeat)
                swapping: true, // whether or not to have items of the same size switch places instead of pushing down if they are the same size
                width: 'auto', // can be an integer or 'auto'. 'auto' scales gridster to be the full width of its containing element
                colWidth: 'auto', // can be an integer or 'auto'.  'auto' uses the pixel width of the element divided by 'columns'
                rowHeight: 80, // can be an integer or 'match'.  Match uses the colWidth, giving you square widgets.
                margins: [5, 5], // the pixel distance between each widget
                outerMargin: true, // whether margins apply to outer edges of the grid
                minColumns: 1, // the minimum columns the grid must have
                minRows: 2, // the minimum height of the grid, in rows
                maxRows: 100,
                defaultSizeX: 2, // the default width of a gridster item, if not specifed
                defaultSizeY: 1, // the default height of a gridster item, if not specified
                minSizeX: 1, // minimum column width of an item
                maxSizeX: null, // maximum column width of an item
                minSizeY: 3, // minumum row height of an item
                maxSizeY: null, // maximum row height of an item
                resizable: {
                    enabled: true,
                    handles: ['n', 'e', 's', 'w', 'ne', 'se', 'sw', 'nw'],
                    start: function(event, $element, widget) {}, // optional callback fired when resize is started,
                    resize: function(event, $element, widget) {}, // optional callback fired when item is resized,
                    stop: function(event, $element, widget) {
                            if ($("#interaction").height() <= 458) {
                                $scope.panels[2].size.y = 6;
                            }
                        } // optional callback fired when item is finished resizing
                },
                draggable: {
                    enabled: true, // whether dragging items is supported
                    handle: '.toMove', // optional selector for resize handle
                    start: function(event, $element, widget) {}, // optional callback fired when drag is started,
                    drag: function(event, $element, widget) {}, // optional callback fired when item is moved,
                    stop: function(event, $element, widget) {} // optional callback fired when item is finished dragging
                }
            };

            //checking for screen size
            $scope.renderCallback = function() {
                if ($scope.panels.length === 3) {
                    $scope.panels[0].position[0] = 0;
                    $scope.counterForGridster = 1;
                }
            };

            $scope.$watch(function() {
                return window.innerWidth
            }, function(value) {
                if (value < 830) {
                    $scope.gridsterOpts.columns = 1;
                    $scope.panels[0].size.x = 1;
                    $scope.panels[1].size.x = 1;
                    $scope.panels[2].size.x = 1;
                    $scope.panels[0].position[0] = 0;
                    $scope.panels[0].position[1] = 0;
                    $scope.panels[1].position[1] = 0;
                    $scope.panels[2].position[1] = 0;
                } else {
                    $scope.gridsterOpts.columns = 2;
                    $scope.panels[0].size.x = 2;
                    $scope.panels[1].size.x = 1;
                    $scope.panels[2].size.x = 1;
                    $scope.panels[2].position[0] = 1;
                    $scope.panels[1].position[1] = 1;
                }
            });

            $scope.getArkColour = function(colour) {
                // takes a colour and returns an ark equivilent. If there's an # then use that colour.

                colour = colour.toLowerCase();

                if (colour.indexOf("#") === 0)
                    return colour;

                switch (colour) {

                    case "green":
                        return "#4AC764";

                    case "red":
                        return "#EA4F6B";

                    case "orange":
                        return "#F8A740";

                    case "blue":
                        return "#2E69DB";

                    default:
                        return colour; //incase they define something like aliceblue
                }

            };

            // Search all possible queryType fields for the customer that has the
            // searchText in any of the fields. Get these customers and perform the
            // callback with the array.
            $scope.getAllPossibleResults = function(searchText, getAllResultshandler) {
                var resultFound = [];
                var index = 0;

                var callbackFunc = function(data) {
                    index++;
                    angular.forEach(data, function(key, value) {
                        var customer = $scope.getCustomerProperties(key);
                        resultFound.push(customer);
                    });
                    if (index == $scope.optionsToQuery.length && getAllResultshandler) {
                        getAllResultshandler(resultFound);
                    }
                };

                for (var i = 0; i < $scope.optionsToQuery.length; i++) {
                    $scope.getResult(searchText, $scope.optionsToQuery[i], callbackFunc);
                }
            };

            $scope.getFontIcon = function(key) {
                return GLOBAL_PROFILE_EXTENSIONS[key];
            };
        }
    ])
    .filter('excludeUsed', function() {
        return function(input, scope) {
            var i,
                j,
                output = [],
                used;

            for (i = 0; i < input.length; i++) {
                used = false;
                if (input[i] === '' && (scope.$last)) {
                    used = true;
                } else {
                    for (j = 0; j <= scope.$index; j++) {
                        if (input[i] === scope.usedProperties[j] && j !== scope.$index) {
                            used = true;
                            break;
                        }
                    }
                }
                if (!used) {
                    output.push(input[i]);
                }
            }
            return output;
        };
    });
