'use strict';
angular.module('cs.query', []).controller('QueryController', ['$scope', '$timeout', 'navigationBarService', '$location', '$http', 'csApi', '$animate', 'toaster', 'GLOBAL_PROFILE_EXTENSIONS', 'JTimeLineQuery', '$modal', 'loggerService',
    function($scope, $timeout, navigationBarService, $location, $http, csApi, $animate, toaster, GLOBAL_PROFILE_EXTENSIONS, JTimeLineQuery, $modal, loggerService) {

        $animate.enabled(true);

        navigationBarService.initialize();
		
		var filePath = 'url.txt';
		var baseUrl = '';
		
        $scope.entityType;
        $scope.entityLabel;
        $scope.tabData = {};
        $scope.dateSearch = {};
        $scope.queryHistory = [];
        $scope.tabData.ajaxHistory = [];
        $scope.tabData.selectOnRefresh = {};
        $scope.reload = 'true';
        $scope.searchFilterIsolated = false; //toggled when when a service/state is clicked when the filter is being used. This is used to hide the other services/states
        $scope.showHistory = false;
        $scope.multipleResults;
        $scope.mapping = GLOBAL_PROFILE_EXTENSIONS.mapping;
        $scope.extraQueryOptions = GLOBAL_PROFILE_EXTENSIONS.ExtraQueryOptions;
        $scope.customerProperties = GLOBAL_PROFILE_EXTENSIONS.CustomerProperties;
        $scope.queryType = 'Customer ID';
        $scope.clientClicked = false;
        $scope.errorBALabel = "Error: Business attributes query failed"; // Error message label for business attributes
        $scope.searchParameters = {'exactValue': false};
        // filter initialization
        $scope.csFilters = {};
        $scope.csFilters.filterString = "";
        $scope.csFilters.isFiltering = false; // true when any of the filters are used
        $scope.csFilters.statusFilter = 'Select All';
        $scope.csFilters.selectFilter = 'No Filter';
        $scope.csFilters.typeFilter = ['Select All'];
        $scope.csFilters.dateFilter = 'Show All';
        $scope.csFilters.dateFilterType = 'Starting';
        $scope.csFilters.existingServiceTypes = [];
        $scope.csFilters.existingServiceTypes[0] = 'Select All';
        $scope.csFilters.existingStateTypes = [];
        $scope.csFilters.existingStateTypes[0] = 'Select All';
        $scope.csFilters.existingTaskTypes = [];
        $scope.csFilters.existingTaskTypes[0] = 'Select All';
        $scope.filterOptions = [{
            'label': 'Phone Number',
            'value': 'PhoneNumber'
        }, {
            'label': 'Email',
            'value': 'EmailAddress'
        }, {
            'label': 'Customer ID',
            'value': 'Customer ID'
        }, {
            'label': 'Anonymous ID',
            'value': 'Anonymous ID'
        }, {
            'label': 'Service ID',
            'value': 'Service ID'
        }, {
            'label': 'State ID',
            'value': 'State ID'
        }, {
            'label': 'Task ID',
            'value': 'Task ID'
        }];
        $scope.tabsList = [{
            'title': 'Task View',
            'templateUrl': 'app/modules/context-services/tree-view.html'
        }, {
            'title': 'Timeline View',
            'templateUrl': 'app/modules/context-services/timeline-view.html'
        }];

        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.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.getBaseurl();
        
        $scope.csFilters.resetFilters = function(){
        	$scope.csFilters.statusFilter = 'Select All';
        	$scope.csFilters.selectFilter = 'No Filter';
        	$scope.csFilters.typeFilter = ['Select All'];
			
        	$scope.csFilters.dateFilter = 'Show All';
        	$scope.csFilters.dateFilterType = 'Starting';

        	$scope.csFilters.fromDate = null;
        	$scope.csFilters.toDate = null;
	        
        	$scope.csFilters.filterString = "";
        	$scope.csFilters.isFiltering = false;
        	
        	$scope.clickedService = undefined;
            $scope.clickedState = undefined;
            $scope.clickedTask = undefined;
        }

        $scope.csFilters.applyFilters = function(){
        	// return if not filtering
        	if ($scope.csFilters.selectFilter == 'No Filter'){
        		$scope.csFilters.isFiltering = false;
    			return;
    		} else {
    			$scope.csFilters.isFiltering = true;
    		}
        	
        	$scope.clickedService = undefined;
            $scope.clickedState = undefined;
            $scope.clickedTask = undefined;
        	
        	if ($scope.task) {
        		// set filter for querying by task id
                $scope.setFilterShow($scope.task);
                return;
            } else if ($scope.state){
            	// set filter for querying by state id
                $scope.setFilterShow($scope.state);
                var tasks = $scope.state.items;
                $scope.tasks = tasks;
                for (var k = 0; k < tasks.length; k++) {
                    $scope.setFilterShow(tasks[k], $scope.state.filterShow);
                }
                return;
            }
        	
        	// set filter for other queries
        	
        	$scope.states = [];
        	$scope.tasks = [];
        	var services = [];
        	
        	if ($scope.tabData.data && $scope.tabData.data.items) {
                services = $scope.tabData.data.items;
            }
        	
            for (var i = 0; i < services.length; i++) {
            	var service = services[i];
        		$scope.setFilterShow(service); // Apply filter to all services
        		if (service.states){
        			for (var j = 0; j < service.states.length; j++) {
                		var state = service.states[j];
                    	$scope.setFilterShow(state, service.filterShow); // Apply filter to all states of each service
                    	var tasks = state.items;
                    	if (tasks) {
            				for (var k = 0; k < tasks.length; k++) {
            					$scope.setFilterShow(tasks[k], state.filterShow); // Apply filter to all tasks of each state
            				}
            				Array.prototype.push.apply($scope.tasks, tasks);
            			}
                	}
        			Array.prototype.push.apply($scope.states, service.states);
        		}
        		if (service.tasks){
        			for (var j = 0; j < service.tasks.length; j++) {
                		$scope.setFilterShow(service.tasks[j], service.filterShow); // Apply filter to all tasks of each service
                	}
        			Array.prototype.push.apply($scope.tasks, service.tasks);
        		}
        	}
        }
        
        $scope.getQueryHistory = function() {
            return $scope.queryHistory;
        }

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

        $scope.closeTable = function() {
            $scope.clientClicked = false;
            $scope.multipleResults = false;
            $scope.toolbarItems.lefttoolbar[1].input.value = '';
        };
        
        $scope.openFilterModal = function() {
        	$scope.csFilters.queryType = $scope.queryType;
            $modal.open({
                templateUrl: 'app/modules/context-services/developer/filter-template.html',
                controller: 'csFilterCtrl',
                resolve: {
                    csFilters: function() {
                        return $scope.csFilters;
                    }
                }
            });
        };

        $scope.toolbarQueryHandler = function(e) {
            var _event = e || $window.event;
            var keyCode = _event.keyCode || _event.which;
            if (keyCode === 13) {
                $scope.tabData.selectedItem = null;
                $scope.clientClicked = true;
                $scope.queryFeedback = "";
                if ($scope.toolbarItems.lefttoolbar[0].select.value === 'State ID' &&
                		   ($scope.toolbarItems.lefttoolbar[2].input.value === '' || 
                		    $scope.toolbarItems.lefttoolbar[1].input.value === '' )){
                	$scope.queryFeedback = 'Searching for states requires both a state ID and a service ID.';
                } else if ($scope.toolbarItems.lefttoolbar[0].select.value === 'Task ID' && 
                		   ($scope.toolbarItems.lefttoolbar[2].input.value === '' || 
                    		$scope.toolbarItems.lefttoolbar[1].input.value === '' )){
                	$scope.queryFeedback = 'Searching for tasks requires both a task ID and a service ID.';
                } else if ($scope.toolbarItems.lefttoolbar[1].input.value !== '') {
                    $scope.multipleResults = false;
                    $scope.clientFound = false;
                    $scope.entityId = $scope.toolbarItems.lefttoolbar[1].input.value;
                    $scope.queryType = $scope.toolbarItems.lefttoolbar[0].select.value;
                    $scope.serviceId = $scope.toolbarItems.lefttoolbar[2].input.value;
                    $scope.tabData.queryById($scope.queryType, $scope.entityId);
                    $scope.searching = true;
                    $scope.csFilters.resetFilters();
                    $scope.searchText = "";
                    $scope.searchParameters.exactValue = false;
                }
                $scope.$apply();
                return false;
            } else {
                return true;
            }
        };

        $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 filterOptions",
                    value: 'PhoneNumber'

                }
            }, {
                nonClickable: true,
                input: {
                    icon: 'fonticon icon-search',
                    id: 'search-box',
                    placeholder: "Search",
                    eventHandlers: [{
                        handlerName: "keyup",
                        handler: $scope.toolbarQueryHandler
                    }],
                    value: ''

                }
            }, {
                nonClickable: true,
                'title': 'Service ID :',
                'spacer': false,
                input: {
                    icon: 'fonticon icon-search',
                    id: 'context-query',
                    placeholder: "Search",
                    eventHandlers: [{
                        handlerName: "keyup",
                        handler: $scope.toolbarQueryHandler
                    }],
                    value: '',
                },
                class: 'service-id-search-hide',
            }],
            righttoolbar: [{
                'click': function(event) {
                    $scope.showHistory ? $scope.showHistory = false : $scope.showHistory = true;
                },
                'spacer': false,
                'title': 'HTTP Request History'
            }]
        };
        
        $scope.$watch('toolbarItems.lefttoolbar[0].select.value', function() {
        	if ($scope.toolbarItems.lefttoolbar[0].select.value === 'State ID' || $scope.toolbarItems.lefttoolbar[0].select.value === 'Task ID'){
            	$scope.toolbarItems.lefttoolbar[2]['class'] = 'service-id-search';
            } else {
            	$scope.toolbarItems.lefttoolbar[2]['class'] = 'service-id-search-hide';
            }
        });

        $scope.parseValue = function(value) {
            if (angular.isArray(value)) {
                var stringified = '';
                for (var i = 0; i < value.length - 1; i++) {
                    stringified += value[i] + ", ";
                }
                stringified += value[value.length - 1];
                return stringified;
            } else {
                return value;
            }
        };

        $scope.itemClicked = function(selectedItem) {
            $scope.clientClicked = true;
            $scope.selectedCustomer = selectedItem;
            $scope.tabData.queryById('Customer ID', $scope.selectedCustomer['customer_id'], $scope.customerQueryType);
            $scope.multipleResults = false;
            $scope.showCustomerInfo = true;
        };

        $scope.createItem = function(item) {
            $scope.tabData.selectedItem = item;
            $scope.tabData.entityType = null;
            $scope.tabData.entityLabel = null
        };

        $scope.selectEntityType = function(att) {
            $scope.tabData.entityType = att.name;
            $scope.tabData.entityLabel = att.label;
        }

        $scope.displayOptionsTable = function(data) {
            $scope.customerQueryType = $scope.toolbarItems.lefttoolbar[0].select.value;
            $scope.customerList = data;
            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.multipleResults = true;
        };

        $scope.deselectNodes = function() {
            $scope.tabData.timeStarted = undefined;
            $scope.tabData.id = undefined;
            $scope.tabData.type = undefined;
            $scope.tabData.taskAddable = false;
            $scope.tabData.stateAddable = false;
            $scope.tabData.completed = false;
            $scope.tabData.timeCompleted = undefined;
        }

        $scope.tabData.queryById = function(queryType, entityId, customerQuery) {
            if (queryType && entityId) {
                $scope.queryType = queryType;
                $scope.entityId = entityId;
            }

            //reset everything
            $scope.clickedService = undefined;
            $scope.clickedState = undefined;
            $scope.clickedTask = undefined;
            $scope.tabData.data = undefined;
            $scope.tabData.treeData = undefined;
            $scope.deselectNodes();

            //this searching variable is only used for phone/email searches (not to be confused with $scope.searching)
            var searching = false;

            var resultHandler = function(httpResponse) {
                $scope.addHttpRequestHistory(httpResponse);
                var resultFound = httpResponse.data;
                $scope.searching = false;
                if (resultFound.length > 1) {
                    var customers = [];
                    for (var i = 0; i < resultFound.length; i++) {
                        var object = {};
                        object = getCustomerProperties(resultFound[i]);
                        customers.push(object);
                    }
                    $scope.displayOptionsTable(customers);
                } else if (resultFound.length === 1) {
                    $scope.selectedCustomer = getCustomerProperties(resultFound[0]);
                    $scope.showCustomerInfo = true;
                    $scope.tabData.queryById($scope.primaryKey.value, $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.value;
                        $scope.tabData.queryById(queryType, entityId);
                    } else {
                        $scope.queryFeedback = 'No Customer exists with "' + entityId +
                            '" as the ' + getSearchLabel(queryType);
                    }
                }
            };

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

                return toReturn;
            }

            var getCustomerProperties = function(key) {
                var customer = {};
                for (var i = 0; i < $scope.customerProperties.length; i++) {
                    customer[$scope.customerProperties[i].label] = $scope.parseValue(
                        key[$scope.customerProperties[i].label]);
                }
                return customer;
            }

            var jsonService = {
                active_tasks: true,
                completed_tasks: true,
                active_states: true,
                completed_states: true,
                extensions: "customstart,customcomplete"
            };
            $scope.tabData.oldCustomerId = $scope.entityId;
            $scope.tabData.oldQueryType = $scope.queryType;
            if ($scope.queryHistory.indexOf($scope.entityId) < 0) {
                $scope.queryHistory = [$scope.entityId].concat($scope.queryHistory);
            }
            var customerInfo, entityInfo;

            $scope.state = undefined;
            $scope.task = undefined;
            $scope.tabData.data = undefined;

            //searching by category

            if ($scope.queryType === 'Service ID') {
                csApi.queryServiceById($scope.baseUrl, $scope.entityId, jsonService).then(function(res) {
                    entityInfo = res.data;
                    $scope.tabData.data = {
                        items: [$scope.parseItems([entityInfo], $scope.queryType.split(' ')[0])[0]]
                    };

                    if (entityInfo.customer_id) {
                        $scope.tabData.customerId = entityInfo.customer_id;
                    } else {
                        $scope.tabData.isAnon = true;
                        $scope.tabData.customerId = entityInfo.contact_key;
                    }
                    $scope.configureData(res, customerInfo, entityInfo, customerQuery);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                });
            } else if ($scope.queryType === 'State ID') {
                $scope.tabData.customerId = '';
                if (!$scope.serviceId) {
                    $scope.inputClass = 'form-control has-error';
                    $scope.queryFeedback = 'Searching for states requires both a state ID and a service ID.';
                    $scope.$apply();
                    return;
                }
                csApi.queryStateById($scope.baseUrl, $scope.serviceId, $scope.entityId, jsonService).then(function(res) {
                    entityInfo = res.data;
                    $scope.states = null;
                    $scope.state = $scope.parseItems([entityInfo], $scope.queryType.split(' ')[0])[0];
                    $scope.configureData(res, customerInfo, entityInfo, customerQuery);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                });
            } else if ($scope.queryType === 'Task ID') {
                $scope.tabData.customerId = '';
                if (!$scope.serviceId) {
                    $scope.inputClass = 'form-control has-error';
                    $scope.queryFeedback = 'Searching for tasks requires both a task ID and a service ID.';
                    $scope.$apply();
                    return;
                }
                csApi.queryTaskById($scope.baseUrl, $scope.serviceId, $scope.entityId, jsonService).then(function(res) {
                    entityInfo = res.data;
                    $scope.states = null;
                    $scope.tasks = null;
                    $scope.task = $scope.parseItems([entityInfo], $scope.queryType.split(' ')[0])[0];
                    $scope.configureData(res, customerInfo, entityInfo, customerQuery);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                });
            } else if ($scope.queryType === 'Anonymous ID') {
                $scope.idType = 'Anonymous ID';
                $scope.tabData.isAnon = true;
                $scope.tabData.customerId = $scope.entityId;
                csApi.queryCustomerServices($scope.baseUrl, $scope.entityId, $scope.tabData.isAnon, jsonService).then(function(res) {
                    customerInfo = res.data;
                    $scope.configureData(res, customerInfo, entityInfo, customerQuery);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                });
            } else if ($scope.queryType === 'EmailAddress' || $scope.queryType === 'PhoneNumber') {
                searching = true;
                var object = {};
                object[queryType] = entityId;
                for (var option in $scope.extraQueryOptions) {
                    object[option] = $scope.extraQueryOptions[option];
                }
                csApi.queryCustomerProfiles($scope.baseUrl, object).then(function(response) {
                    resultHandler(response);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                    $scope.queryFeedback = 'Unable to connect to contact server.';
                });
            } else {
                $scope.idType = 'Customer ID';
                $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.configureData(res, customerInfo, entityInfo, customerQuery);
                }, function(res) {
                    $scope.queryErrorHandler(res, customerQuery);
                });
            }
        };

        $scope.addHttpRequestHistory = function(httpResponse, customAction) {
            var action = 'Query ' + $scope.queryType;
            if (customAction) {
                action = customAction;
            }
            var url = "";
            var method = "";
            if (httpResponse.config !== undefined){
            	url = httpResponse.config.url;
            	method = httpResponse.config.method;
            }
            if (httpResponse.status >= 200 && httpResponse.status < 300){
            	$scope.tabData.ajaxHistory.push({
            		'action': action,
            		'path': url,
            		'data': httpResponse.data,
            		'method': method,
            		'status': httpResponse.status + ' (' + httpResponse.statusText + ')',
            		'time': Date(),
            		'selected': false
            	});
            } else {
            	$scope.tabData.ajaxHistory.push({
            		'action': action,
            		'path': url,
            		'method': method,
            		'status': httpResponse.status + ' (' + httpResponse.statusText + ')',
            		'time': Date(),
            		'selected': false
            	});
            }
            loggerService.logHttpRequest(
            		action, 
            		url, 
            		httpResponse.data, 
            		method, 
            		httpResponse.status + ' (' + httpResponse.statusText + ')',
            		Date()
            );
            
        };

        //the reason we need a repeated error handler is because when query by customer name/anon name, the error is sent back as a success
        //this $scope.queryErrorHandler deals with the errors for query by service id, state id, and task id
        $scope.queryErrorHandler = function(httpResponse, customerQuery) {
            $scope.addHttpRequestHistory(httpResponse);
            if (httpResponse.status === 0) {
                $scope.queryFeedback = 'Couldn\'t connect to Context Services.';
            } else if (customerQuery === 'EmailAddress') {
                $scope.queryFeedback = 'Couldn\'t find any services associated with the customer with this email.';
            } else if (customerQuery === 'PhoneNumber') {
                $scope.queryFeedback = 'Couldn\'t find any services associated with the customer with this phone number.';
            } else if ($scope.queryType === 'State ID'){
            	 $scope.queryFeedback = 'Couldn\'t find any states associated with the state ID and service ID.';
            } else if ($scope.queryType === 'Task ID'){
            	$scope.queryFeedback = 'Couldn\'t find any tasks associated with the task ID and service ID.';
            } else {
                $scope.queryFeedback = 'Couldn\'t find any services associated with the ' + $scope.queryType.substring(0, 1).toLowerCase() + $scope.queryType.substring(1) + '.';
            }
            $scope.searching = false;
            $scope.clientFound = false;
            return;
        }

        //this function is ran after the callback from csApi calls (from queryById)
        $scope.configureData = function(httpResponse, customerInfo, entityInfo, customerQuery, searching) {
            //adds to HTTP Request History list
            $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': $scope.queryType,
                    'subheading': ': ' + $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;
            } else if (entityInfo) {
                $scope.tabData.isAnon = entityInfo.customer_id ? false : true;
                $scope.rawData = entityInfo;
                $scope.tabData.maxChildren = 0;
                $scope.inputClass = 'form-control';
                $scope.queryFeedback = '';
            } else if (searching) {
                $scope.inputClass = 'form-control has-error';
                $scope.$apply();
                return;
            } else {
                //outputs errors of incorrect data was found
                $scope.inputClass = 'form-control has-error';
                if (httpResponse.status === 0) {
                    $scope.queryFeedback = 'Couldn\'t connect to Context Services.';
                } else if (customerQuery === 'EmailAddress') {
                    $scope.queryFeedback = 'Couldn\'t find any services associated with the customer with this email.';
                } else if (customerQuery === 'PhoneNumber') {
                    $scope.queryFeedback = 'Couldn\'t find any services associated with the customer with this phone number.';
                } else {
                    $scope.queryFeedback = 'Couldn\'t find any services associated with the ' + $scope.queryType.substring(0, 1).toLowerCase() + $scope.queryType.substring(1) + '.';
                }
                $scope.searching = false;
                $scope.clientFound = false;
                return;
            }
            $scope.clientFound = true;
            $scope.searching = false;
            $scope.tabData.treeData = [$scope.tabData.data];
            if ($scope.tabData.node && $scope.tabData.refreshTree) {
                $scope.tabData.refreshTree();
            }
            $scope.csFilters.applyFilters(); // apply filters in csFilters
        }

        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.tabData.dispositionAttributes = {
                'Service': {},
                'Task': {},
                'State': {}
        };
        $scope.tabData.dispositionDescriptions = {
                'Service': {},
                'Task': {},
                'State': {}
        };

        $scope.getData = function() {
						
			csApi.getBusinessAttributesRaw($scope.baseUrl).then(function(res) {
                
			$scope.businessProperties = res.data
            if (Object.keys($scope.businessProperties).length != 0)
				$scope.showUI = true;
            else {
                $scope.showUI = false;
                $scope.errorBALabel = "Error: No business attributes found";
            }
                    	
            $scope.addHttpRequestHistory(res, 'Get Business Attributes');

			if (res.status != 200) {
				$location.url('..');
            }
            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.tabData.serviceAttributes[$scope.businessProperties[i].values[j].name].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].name].label = $scope.businessProperties[i].values[j].display_name;
                            	} else {
                                    $scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].dbid] = {};
                                    $scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].dbid].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.serviceAttributes[$scope.businessProperties[i].values[j].dbid].label = $scope.businessProperties[i].values[j].display_name;
                            	}
                            	$scope.csFilters.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.tabData.taskAttributes[$scope.businessProperties[i].values[j].name].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].name].label = $scope.businessProperties[i].values[j].display_name;
                            	} else {
                                    $scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].dbid] = {};
                                    $scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].dbid].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.taskAttributes[$scope.businessProperties[i].values[j].dbid].label = $scope.businessProperties[i].values[j].display_name;
                            	}
                            	$scope.csFilters.existingTaskTypes[j + 1] = $scope.businessProperties[i].values[j].display_name; // so we can filter off types.
                            }
                        } 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.tabData.stateAttributes[$scope.businessProperties[i].values[j].name].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].name].label = $scope.businessProperties[i].values[j].display_name;
                            	} else {
                            		$scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].dbid] = {};
                                    $scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].dbid].name = $scope.businessProperties[i].values[j].name;
                                    $scope.tabData.stateAttributes[$scope.businessProperties[i].values[j].dbid].label = $scope.businessProperties[i].values[j].display_name;
                            	}
                            	$scope.csFilters.existingStateTypes[j + 1] = $scope.businessProperties[i].values[j].display_name; // so we can filter off types.
                            }
                        } 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.disposition') + 1) {
                            for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                            	if ($scope.businessProperties[i].map_name){
                            		$scope.tabData.dispositionAttributes['Service'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                            		$scope.tabData.dispositionDescriptions['Service'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].description;
                            	} else {
                                    $scope.tabData.dispositionAttributes['Service'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                    $scope.tabData.dispositionDescriptions['Service'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].description;
                            	}
                            }
                        }
                        if ($scope.businessProperties[i].cv_attributes.indexOf('Task.disposition') + 1) {
                            for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                            	if ($scope.businessProperties[i].map_name){
                            		$scope.tabData.dispositionAttributes['Task'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                            		$scope.tabData.dispositionDescriptions['Task'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].description;
                            	} else {
                                    $scope.tabData.dispositionAttributes['Task'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                    $scope.tabData.dispositionDescriptions['Task'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].description;
                            	}
                            }
                        }
                        if ($scope.businessProperties[i].cv_attributes.indexOf('State.disposition') + 1) {
                            for (var j = 0; j < $scope.businessProperties[i].values.length; j++) {
                            	if ($scope.businessProperties[i].map_name){
                            		$scope.tabData.dispositionAttributes['State'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].display_name;
                            		$scope.tabData.dispositionDescriptions['State'][$scope.businessProperties[i].values[j].name] = $scope.businessProperties[i].values[j].description;
                            	} else {
                                    $scope.tabData.dispositionAttributes['State'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].display_name;
                                    $scope.tabData.dispositionDescriptions['State'][$scope.businessProperties[i].values[j].dbid] = $scope.businessProperties[i].values[j].description;
                            	}
                            }
                        }

                        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.clear = function() {
            toaster.clear();
        };

        $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.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 && $scope.tabData.serviceAttributes[nodes[j].entityType]) {
                    nodes[j].entityString = $scope.tabData.serviceAttributes[nodes[j].entityType].label ? $scope.tabData.serviceAttributes[nodes[j].entityType].label + ' ' : '';
                } else if (nodes[j].entityType === cn.state_type && $scope.tabData.stateAttributes[nodes[j].entityType]) {
                    nodes[j].entityString = $scope.tabData.stateAttributes[nodes[j].entityType].label ? $scope.tabData.stateAttributes[nodes[j].entityType].label + ' ' : '';
                } else if (nodes[j].entityType === cn.task_type && $scope.tabData.taskAttributes[nodes[j].entityType]) {
                    nodes[j].entityString = $scope.tabData.taskAttributes[nodes[j].entityType].label ? $scope.tabData.taskAttributes[nodes[j].entityType].label + ' ' : '';
                } else {
                    nodes[j].entityString = '(' + 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;

                //parseItems goes through every single item (service&state&task). This function uses the selectOnRefresh object to reselect the item that was last selected before the requeue
                //selectOnRefresh object is set in service-create.js, state-create.js, and task-create.js
                if (nodes[j].service_id == $scope.tabData.selectOnRefresh.serviceId) {
                    if (nodes[j].type === 'Service') {
                        $scope.selectService(nodes[j]);
                    } else if (nodes[j].type === 'State' && nodes[j].state_id === $scope.tabData.selectOnRefresh.stateId) {
                        $scope.selectState(nodes[j]);
                    } else if (nodes[j].type === 'Task' && nodes[j].task_id === $scope.tabData.selectOnRefresh.taskId) {
                        $scope.selectTask(nodes[j]);
                    }
                }

                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 + ')';
                    nodes[j].started.media_type_display = $scope.tabData.mediaAttributes[nodes[j].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 + ')';
                    nodes[j].completed.media_type_display = $scope.tabData.mediaAttributes[nodes[j].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 + ')';
                    nodes[j].started.resource_type_display = $scope.tabData.resourceAttributes[nodes[j].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 + ')';
                    nodes[j].completed.resource_type_display = $scope.tabData.resourceAttributes[nodes[j].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 + ')';
                    nodes[j].started.application_type_display = $scope.tabData.applicationAttributes[nodes[j].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 + ')';
                    nodes[j].completed.application_type_display = $scope.tabData.applicationAttributes[nodes[j].type][nodes[j].completed.application_type] || "";
                }
                if (nodes[j].disposition){
                	nodes[j].disposition_display = $scope.tabData.dispositionAttributes[nodes[j].type][nodes[j].disposition];
                }
                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].states = states.slice(0);
                    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].tasks) {
                                        states[l].tasks = [tasks[k]];
                                    } else {
                                        states[l].tasks.push(tasks[k]);
                                    }
                                    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].tasks) {
                                nodes[j].tasks = [tasks[k]];
                            } else {
                                nodes[j].tasks.push(tasks[k]);
                            }
                            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 (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());
        }


        $scope.flatSort = function(nodes) {
            if (nodes) {
                return nodes.sort(compareTime);
            }
        }

        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.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;
        };

        $scope.setFilterShow = function(item, showParent){
        	// set filterShow, using csFilters values to filter
        	// showParent is the filterShow value of the parent of item
        	if (showParent === undefined){
        		showParent = false;
        	}
        	
        	if (!item){
        		return;
        	}
        	
        	// Filter by service/state/task types
        	if ($scope.csFilters.selectFilter != "No Filter"){
        		if (item.type !== $scope.csFilters.selectFilter){
        			// If item's type (service, state, or task) is not selected, show only when its parent is shown
        			item.filterShow = showParent;
        			return;
        		} else if ($scope.csFilters.typeFilter[0] !== "Select All" && $scope.csFilters.typeFilter.indexOf(item.entityString.slice(0,-1)) == -1){
        			// Item's type (service type, state type, or task type) is not in filter list
        			item.filterShow = false;
        			return;
        		}
        	
        		// Filter by status types
        		if ($scope.csFilters.statusFilter != "Select All"){
        			if ($scope.csFilters.statusFilter == "Completed" && !item.completed){
        				item.filterShow = false; // completed item not displayed
        				return;
        			} else if ($scope.csFilters.statusFilter == "Active" && item.completed){
        				item.filterShow = false; // active item not displayed
        				return;
        			}
        		}
        	
        		// Filter Date/Time
        		if (!$scope.durationFilter(item.started, item.completed)){
        			item.filterShow = false;
        			return;
        		}
        	}
        	
        	item.filterShow = true;
        };
        
        $scope.durationFilter = function (startObj, endObj) {
        	/*	This function filters based of if the startObj and endObj
        		fit within the interval the user decided. There would always be a startObj
        		but there does not have to be an endObj (status is 'active')*/
        	
        	if ($scope.csFilters.dateFilter === "Show All"){
				return true;
			}
        	
        	var startDate = new Date(startObj.timestamp);
			startObj.date = startDate.toISOString();
			var endDate;
        	if (endObj != undefined){
        		var endDate = new Date(endObj.timestamp);
        		endObj.date = endDate.toISOString();
        	}
			
			if($scope.csFilters.dateFilter === "This Month"){
				
				var startingThisMonth = moment().format("MM YYYY") === moment(startObj.date).format("MM YYYY");
				
				if (endObj !== undefined)
					var endingThisMonth = moment().format("MM YYYY") === moment(endObj.date).format("MM YYYY");
				else
					var endingThisMonth = false;

				return $scope.startEndSwitch(startingThisMonth, endingThisMonth);
			} else if($scope.csFilters.dateFilter === "Last Month"){
				var lastMonth =  moment(moment().subtract(1,'month')._d).format("MM YYYY"); 
				
				// same code as This Month filter. 
				
				var startingLastMonth = lastMonth === moment(startObj.date).format("MM YYYY");
				
				if (endObj !== undefined)
					var endingLastMonth = lastMonth === moment(endObj.date).format("MM YYYY");
				else
					var endingLastMonth = false;

				return $scope.startEndSwitch(startingLastMonth, endingLastMonth);
			} else if($scope.csFilters.dateFilter === "Last 90 Days"){
				var ninetyDaysAgo = moment(moment().subtract(90,'day')._d).format("YYYY MM DD");
				var today = moment().format("YYYY MM DD");
				var startingLast90Days = $scope.dateInBetween(ninetyDaysAgo, today, moment(startObj.date).format("YYYY MM DD"));
				
				if (endObj !== undefined)
					var endingLast90Days = $scope.dateInBetween(ninetyDaysAgo, today, moment(endObj.date).format("YYYY MM DD"));
				else
					var endingLast90Days = false;

				return $scope.startEndSwitch(startingLast90Days, endingLast90Days);		
			} else if($scope.csFilters.dateFilter === "This Year"){
				// similar to this month; 
				
				var startingThisYear = moment().format("YYYY") === moment(startObj.date).format("YYYY");
				
				if (endObj !== undefined)
					var endingThisYear = moment().format("YYYY") === moment(endObj.date).format("YYYY");
				else
					var endingThisYear = false;

				return $scope.startEndSwitch(startingThisYear, endingThisYear);
			} else if($scope.csFilters.dateFilter === "Last Year"){
				// similar to last month; 
				var lastYear =  moment(moment().subtract(1,'year')._d).format("YYYY"); 
				
				// same code as This Year filter. 
				
				var startingLastYear = lastYear === moment(startObj.date).format("YYYY");
				
				if (endObj !== undefined)
					var endingLastYear = lastYear === moment(endObj.date).format("YYYY");
				else
					var endingLastYear = false;

				return $scope.startEndSwitch (startingLastYear, endingLastYear);
			} else {
				// custom range.
				var startDate = moment($scope.csFilters.fromDate).format();
				var endDate = moment($scope.csFilters.toDate).format();
				var startingInBetween = $scope.dateInBetween(startDate, endDate, moment(startObj.date).format());
				
				if (endObj !== undefined)
					var endingInBetween = $scope.dateInBetween(startDate, endDate, moment(endObj.date).format());
				else
					var endingInBetween = false;
				return $scope.startEndSwitch (startingInBetween, endingInBetween);
		
			}
			return false;
		}
        
        $scope.startEndSwitch = function (startCondition, endCondition){
			//decides what to return based off if user selected starting, ending, or both.
			
			switch ($scope.csFilters.dateFilterType){
			case ('Starting'):
				return startCondition;

			case ('Ending'):
				return endCondition !== undefined  ? endCondition : startCondition;
			
			case ('Starting and Ending'):
				return endCondition !== undefined  ? endCondition && startCondition : startCondition;
			
			default:
				return endCondition !== undefined  ? endCondition || startCondition : startCondition;
		
			}
			
		}
        
        $scope.dateInBetween = function (startDate, endDate, comparingDate) {
        	/*  takes comparingDate and returns true if it is in between startDate and endDate.
        		Written to make the filter more readable. 
        	 	if the user does not put a date, it will result in Invalid Date in moment, which we treat as no filter. */
        					
        		if (startDate === "Invalid date")
        			var afterStartDate = true;
        		else
        			var afterStartDate = comparingDate >= startDate;
        			
        		if (endDate === "Invalid date")
        			var beforeEndDate = true;
        		else
        			var beforeEndDate = comparingDate <= endDate
        			
        		return ( afterStartDate && beforeEndDate) ;			
        };
        
        $scope.setSearchShow = function(item, string) {
        	// lowercase string
        	// set show for searching (case insensitive)
        	
            if ($scope.searchParameters.exactValue){
            	// exact match
            	var keys = Object.keys(item);
            	for (var i = 0; i < keys.length; i++){
            		var key = keys[i];
            		if (key == '$$hashKey'){
            			continue;
            		}
            		if (typeof item[key] === 'string' && item[key].toLowerCase().trim() === string){
    					item.searchShow = true;
    					return;
    				}
            	}
            	if (item.started){
            		keys = Object.keys(item.started);
            		for (var i = 0; i < keys.length; i++){
        				if (item.started[keys[i]].toString().toLowerCase().trim() === string){
        					item.searchShow = true;
        					return;
        				}
            		}
        		}
        		if (item.completed){
        			keys = Object.keys(item.completed);
        			for (var i = 0; i < keys.length; i++){
        				if (item.completed[keys[i]].toString().toLowerCase().trim() === string){
        					item.searchShow = true;
        					return;
        				}
        			}
        		}
            } else {
            	// partial match
            	var keys = Object.keys(item);
            	for (var i = 0; i < keys.length; i++){
            		var key = keys[i];
            		if (key == '$$hashKey'){
            			continue;
            		}
            		if (typeof item[key] === 'string' && item[key].toLowerCase().trim().indexOf(string) != -1){
    					item.searchShow = true;
    					return;
    				}
            	}
            	if (item.started){
            		keys = Object.keys(item.started);
            		for (var i = 0; i < keys.length; i++){
            			var key = keys[i];
        				if (item.started[key].toString().toLowerCase().trim().indexOf(string) != -1){
        					item.searchShow = true;
        					return;
        				}
            		}
        		}
        		if (item.completed){
        			keys = Object.keys(item.completed);
        			for (var i = 0; i < keys.length; i++){
        				var key = keys[i];
        				if (item.completed[key].toString().toLowerCase().trim().indexOf(string) != -1){
        					item.searchShow = true;
        					return;
        				}
        			}
        		}
            }
            item.searchShow = false;
        };

        $scope.searchText = '';
        $scope.isSearching = false;
        $scope.states = [];
        $scope.tasks = [];
        
        $scope.applySearch = function(val){
        	if (val === undefined){
        		return;
        	}
        	$scope.searchFilterIsolated = false;

            var value = val.toLowerCase();

            if (value.length > 0)
                $scope.isSearching = true;
            else {
                $scope.isSearching = false;
                return;
            }

            if ($scope.task) {
                $scope.setSearchShow($scope.task, value);
            } else if ($scope.state) {
                $scope.setSearchShow($scope.state, value);

                var tasks = $scope.state.items;
                $scope.tasks = tasks;
                for (var k = 0; k < tasks.length; k++) {
                    $scope.setSearchShow(tasks[k], value);
                }
            } else {
                var allTasks = []
                var allStates = [];
                var services = [];
                if ($scope.tabData.data && $scope.tabData.data.items) {
                    services = $scope.tabData.data.items;
                }
                for (var i = 0; i < services.length; i++) {
                    $scope.setSearchShow(services[i], value);

                    //searches through all active/completed states of each service and determines if they match search filter
                    //appends all states to 'states' array
                    if (services[i].active_states) {
                    	for (var j = 0; j < services[i].active_states.length; j++) {
                            $scope.setSearchShow(services[i].active_states[j], value);
                        }
                        Array.prototype.push.apply(allStates, services[i].active_states);
                    }
                    
                    if (services[i].completed_states) {
                    	for (var j = 0; j < services[i].completed_states.length; j++) {
                            $scope.setSearchShow(services[i].completed_states[j], value);
                        }
                        Array.prototype.push.apply(allStates, services[i].completed_states);
                    }

                    //searches through all tasks (including state level tasks) and determines if they match search filter
                    //appends all tasks to 'tasks' array
                    if (services[i].active_tasks) {
                    	for (var j = 0; j < services[i].active_tasks.length; j++) {
                            $scope.setSearchShow(services[i].active_tasks[j], value);
                        }
                        Array.prototype.push.apply(allTasks, services[i].active_tasks);
                    }
                    if (services[i].completed_tasks) {
                    	for (var j = 0; j < services[i].completed_tasks.length; j++) {
                            $scope.setSearchShow(services[i].completed_tasks[j], value);
                        }
                        Array.prototype.push.apply(allTasks, services[i].completed_tasks);
                    }
                }
                $scope.tasks = allTasks;
                $scope.states = allStates;
            }
        };

        $scope.$watch('searchText', function(val) {
            $scope.applySearch(val);
        });
        
        $scope.$watch('searchParameters', function() {
            $scope.applySearch($scope.searchText);
        }, true);


        //Selects items (changes the data to be displayed)
        $scope.selectService = function(service) {
            if ($scope.isSearching) { //if the search filter is being used and a service is clicked, makes this the only viewable service when clicked
                $scope.searchFilterIsolated = true;
            }
            $scope.isSearching = false;
            $scope.clickedService = service;
            $scope.clickedState = undefined;
            $scope.clickedTask = undefined;
            $scope.tabData.node = service;
        };

        $scope.selectState = function(state) {
            if ($scope.isSearching && !$scope.searchFilterIsolated) { //if the search filter is being used and searchFilterIsolated is not already set (eg, if a service isn't being isolated from the view, isolate the state that is clicked)
                $scope.searchFilterIsolated = true;
                $scope.clickedService = undefined;
            }
            $scope.isSearching = false;
            $scope.clickedState = state;
            $scope.clickedTask = undefined;
            $scope.tabData.node = state;
            $scope.getExtension(state);
        };

        $scope.selectTask = function(task) {
            $scope.tabData.node = task;
            $scope.clickedTask = task;
            $scope.getExtension(task);

        };

        $scope.resetSearchFilter = function() {
            $scope.searchText = '';
            $scope.clickedService = undefined;
            $scope.clickedState = undefined;
            $scope.clickedTask = undefined;
        }

        //getting customer or service by id will not return any extensions for states/tasks. This method is used to get extensions whenever a state or task has been clicked
        $scope.getExtension = function(item) { //item can be either a state object or a task object
            var response, queryType;
            if (item.type == 'State') {
            	queryType = "State ID";
                response = csApi.queryStateById($scope.baseUrl, item.service_id, item.state_id, {
                    extensions: "customstart,customcomplete"
                });
            } else { //if its not a state, its a task
            	queryType = "Task ID";
                response = csApi.queryTaskById($scope.baseUrl, item.service_id, item.task_id, {
                    extensions: "customstart,customcomplete"
                });
            }

            response.then(successCallback(queryType), errorCallback(queryType));

            function successCallback(queryType) {
            	return function(res){
            		$scope.tabData.node.customstart = res.data.customstart;
            		$scope.tabData.node.customcomplete = res.data.customcomplete;
            		$scope.addHttpRequestHistory(res, "Query " + queryType);
            	}
            }

            function errorCallback(queryType) {
            	return function(err){
            		toaster.pop("Unable to get extensions");
            		$scope.addHttpRequestHistory(err, "Query " + queryType);
            	}
            }
        }

        $scope.formatKey = function(key, splitBy, replaceWith) {
            if (!key) {
                return '';
            }
            if (typeof(key) !== 'string') {
                key = angular.toJson(key);
            }
            var splitkey = key.split(splitBy);
            var outkey = splitkey[0].substring(0, 1).toUpperCase() + splitkey[0].substring(1);
            for (var i = 1; i < splitkey.length; i++) {
                outkey += replaceWith;
                outkey += splitkey[i];
            }
            return outkey;
        }

        $scope.tabData.delete = function(node) {
            $scope.tabData.node = node;
            $modal.open({
                templateUrl: 'app/modules/context-services/developer/delete-confirmation.html',
                controller: 'DeleteController',
                resolve: {
                    queryControllerData: function() {
                        return $scope;
                    }
                }
            });
        };

        $scope.isString = function(arg) {
            return angular.isString(arg);
        }
    }
]);
