(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metGridPaging', [
        'urls', 'localize', 'inventoryGridConfig', 'host', '$window',
        function (metUrls, metLocalize, metInventoryGrid, host, $window) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryGridPagingHtml'),
                scope: {
                    updateResults: '&',
                    isBottom: '@',
                    loading: '=',
                    showPaging: '=',
                    label: '@'
                },
                link: function (scope, element, attrs) {
                    scope.messages = {
                        of: metLocalize('messages', 'of'),
                        totalTools: metLocalize('fieldNames', 'totalTools'),
                        tools: metLocalize('fieldNames', 'tools'),
                        resultsPerPage: metLocalize('messages', 'resultsPerPage')
                    };
                    
                    scope.totalResults = 0;
                    scope.startNumber = 0;
                    scope.pageNumbers = [];
                    scope.currentPage = 1;
                    scope.totalPages;
                    scope.endNumber;
                    scope.showForwardPageSet = true;
                    scope.showPreviousPageSet = true;
                    scope.resultsPerPage = metInventoryGrid.resultsPerPage;

                    var userAgent = $window.navigator.userAgent;
                    var browsers = { chrome: /chrome/i, safari: /safari/i, firefox: /firefox/i };
                    var notIe = false;
                    for (var key in browsers) {
                        if (browsers[key].test(userAgent)) {
                            notIe = true;
                        }
                    };
                    scope.resultsPerPageOptions = notIe === false ? [10, 25, 50] : [10, 25, 50, 100, 200];

                    scope.changeResultsPerPage = function (resultOption) {
                        scope.resultsPerPage = resultOption;
                        metInventoryGrid.setResultsPerPage(resultOption);
                        scope.updateResults();
                    }
                    
                    scope.$on('grid-updated', function (event, args) {
                        scope.totalResults = args.totalResults;
                        scope.startNumber = args.startNumber;
                        scope.currentPage = args.currentPage;
                        var element = document.getElementById('totalTools');
                        if (element) {
                            metLocalize('fieldNames', 'totalTools').promise.then(function (val) {
                                element.innerHTML = val + '<br/><span>' + scope.totalResults + '</span>';
                            });
                        }
                        getEndNumber(args.resultsPerPage);

                        if (scope.showPaging) {
                            scope.showForwardPageSet = true;
                            scope.showPreviousPageSet = true;
                            getPageNumbers();
                        }
                    });

                    function getEndNumber(resultsPerPage) {
                        var endNumber = scope.startNumber - 1 + resultsPerPage;
                        if (endNumber > scope.totalResults) {
                            endNumber = scope.totalResults;
                        }
                        scope.endNumber = endNumber;
                    }

                    function getPageNumbers() {
                        scope.pageNumbers = [];
                        scope.totalPages = parseInt(scope.totalResults / metInventoryGrid.resultsPerPage);
                        if ((scope.totalResults % metInventoryGrid.resultsPerPage) > 0) {
                            scope.totalPages++;
                        }

                        var startPage = (parseInt((scope.currentPage - 1) / 10) * 10) + 1;
                        if (startPage === 1) {
                            scope.showPreviousPageSet = false;
                        }

                        var endPage = startPage + 9;
                        if (endPage >= scope.totalPages) {
                            scope.showForwardPageSet = false;
                            endPage = scope.totalPages;
                        }
                        for (var i = startPage; i <= endPage; i++) {
                            scope.pageNumbers.push(i);
                        }
                    }

                    scope.goToPage = function (pageNumber) {
                        metInventoryGrid.pageIndex = pageNumber - 1;
                        scope.updateResults({ isPaging: true });
                    }

                    scope.previousPageSets = function () {
                        var firstPageNumber = scope.pageNumbers[0] - 1;
                        scope.goToPage(firstPageNumber);
                    }

                    scope.forwardPageSets = function () {
                        var lastPageNumber = scope.pageNumbers[scope.pageNumbers.length - 1] + 1;
                        scope.goToPage(lastPageNumber);
                    }

                    scope.goTo = function () {
                        var inputElement = document.getElementById('pageNumber');
                        var pageNumber = parseInt(inputElement.value);
                        var inRange = function() {
                            return pageNumber <= scope.totalPages && pageNumber > 0;
                        }

                        if (inRange()) {
                            scope.goToPage(pageNumber);
                        }
                        else {
                            if (pageNumber > scope.totalPages) {
                                scope.goToPage(scope.totalPages);
                            }
                            else {
                                scope.goToPage(1);
                            }
                        }
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var app = angular.module('oneKeyApp');

    app.service('transfers', ['$resource', 'urls',
        function ($resource, metUrls) {
            var transfer = $resource(metUrls('toolTransferApi').concat('/transfer'), {}, {
                'save': {
                    method: 'POST'
                }
            });

            var getAll = $resource(metUrls('toolTransferApi'),
                {},
                {
                    'query': {
                        method: 'GET',
                    isArray: true
                }
            });

            return {
                getAll: function (successCallback, errorCallback) {
                    return getAll.query({}, successCallback, errorCallback);
                },
                transfer: function (request, successCallback, errorCallback) {
                    return transfer.save(request, successCallback, errorCallback);
                }
            };
        }
    ]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('locations', ['$resource', 'urls', function ($resource, metUrls) {

        var api = $resource(metUrls('placeApi').concat('/:placeId'),
            {
                placeId: '@placeId'
            },
            {
                'update': { method: 'PUT' },
                'query': { method: 'GET', isArray: false },
                'search': {
                    method: 'GET',
                    url: metUrls('placeApi').concat('/search')
                },
                'migrate': {
                    method: 'POST',
                    isArray: true,
                    url: metUrls('placeApi').concat('/migrate')
                },
                'counts': {
                    method: 'GET',
                    url: metUrls('placeApi').concat('/counts')
                }
            }
        );

        return {
            getAll: function (options, success, error) {
                return api.query(options, success, error);
            },
            getLocation: function (placeId, success, error) {
                return api.get({ placeId: placeId }, success, error);
            },
            update: function (location, success, error) {
                return api.update(location, success, error);
            },
            create: function (location, success, error) {
                return api.save(location, success, error);
            },
            remove: function (location, success, error) {
                return api.remove({ placeId: location.placeId }, success, error);
            },
            search: function (placeFilters, successCallback, errorCallback) {
                return api.search(
                    placeFilters,
                    successCallback,
                    errorCallback
                );
            },
            migrate: function (migrateRequest, successCallback, errorCallback) {
                return api.migrate(
                    migrateRequest,
                    successCallback,
                    errorCallback
                );
            },
            counts: function(successCallback, errorCallback) {
                return api.counts(successCallback, errorCallback);
            }
        };
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('trades', ['$resource', 'urls', function ($resource, metUrls) {

        var resource = $resource(metUrls('tradeApi').concat('/:divisionId'),
            {
                divisionId: '@divisionId'
            },
            {
                'update': { method: 'PUT' },
                'query': { method: 'GET', isArray: false }
            }
        );

        return {
            getAll: function (options, success, error) {
                return resource.query(options, success, error);
            },
            getTrade: function (tradeId, success, error) {
                return resource.get({ tradeId: tradeId }, success, error);
            },
            update: function (trade, success, error) {
                return resource.update(trade, success, error);
            },
            create: function (trade, success, error) {
                return resource.save(trade, success, error);
            },
            remove: function (trade, success, error) {
                return resource.remove({ divisionId: trade.divisionId }, success, error);
            }
        };
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('people', ['$resource', 'urls', function ($resource, metUrls) {

        var resource = $resource(metUrls('peopleApi').concat('/:personId'),
            {
                personId: '@personId'
            },
            {
                'update': { method: 'PUT' },
                'query': { method: 'GET', isArray: false }
            }
        );

        return {
            getAll: function (options, success, error) {
                return resource.query(options, success, error);
            },
            getPerson: function (personId, success, error) {
                return resource.get({ personId: personId }, success, error);
            },
            update: function (person, success, error) {
                return resource.update(person, success, error);
            },
            create: function (person, success, error) {
                return resource.save(person, success, error);
            },
            remove: function (person, success, error) {
                return resource.remove({ personId: person.personId }, success, error);
            }
        };
    }]);
}());

(function () {
    'use strict';

    var app = angular.module('oneKeyApp');

    app.service('manufacturers', ['$resource', 'urls', function ($resource, metUrls) {
        var resource = $resource(metUrls('manufacturersApi').concat('/:manufacturerId'),
            {
                manufacturerId: '@manufacturerId'
            },
            {
                'update': {
                    method: 'PUT'
                },
                'query': {
                    method: 'GET',
                    isArray: false,
                    params: {
                        'includeGlobalManufacturers': true
                    }
                }
            });

        return {
            getAll: function (success, error) {
                return resource.query(null, success, error);
            },
            get: function (manufacturerId, success, error) {
                return resource.get({ manufacturerId: manufacturerId }, success, error);
            },
            update: function (manufacturer, success, error) {
                return resource.update(manufacturer, success, error);
            },
            create: function (manufacturer, success, error) {
                return resource.save(manufacturer, success, error);
            },
            remove: function (manufacturer, success, error) {
                return resource.remove({ manufacturerId: manufacturer.manufacturerId }, success, error);
            }
        };
    }]);
}());

(function() {
    'use strict';

    var app = angular.module('oneKeyApp');

    app.service('userItems', ['$resource', 'urls',
        function($resource, metUrls) {

            var resource = $resource(
                metUrls('userItemsApi').concat('/:id'), {
                    id: '@id'
                }, {
                    restore: {
                        method: 'POST',
                        url: metUrls('userItemsApi').concat('/:id/restore'),
                        params: {
                            id: '@id'
                        }
                    },
                    'search': {
                        method: 'GET',
                        url: metUrls('userItemsApi').concat('/search')
                    },
                    history: {
                        method: 'GET',
                        url: metUrls('userItemsApi').concat('/history/:userItemId'),
                        params: {
                            userItemId: '@userItemId'
                        }
                    }
                }
            );

            return {
                get: function(userItemId, successCallback, errorCallback) {
                    return resource.get({
                            id: userItemId
                        },
                        successCallback,
                        errorCallback
                    );
                },
                update: function(userItem, successCallback, errorCallback) {
                    return resource.save(
                        userItem,
                        successCallback,
                        errorCallback
                    );
                },
                search: function(userItemFilters, successCallback, errorCallback) {
                    return resource.search(
                        userItemFilters,
                        successCallback,
                        errorCallback
                    );
                },
                create: function(userItem, successCallback, errorCallback) {
                    return resource.save(
                        userItem,
                        successCallback,
                        errorCallback
                    );
                },
                remove: function (itemId, successCallback, errorCallback) {
                    return resource.remove({
                        id: itemId
                        },
                        successCallback,
                        errorCallback
                    );
                },
                restore: function (itemId, successCallback, errorCallback) {
                    return resource.restore({
                        id: itemId
                        },
                        successCallback,
                        errorCallback
                    );
                },
                history: function (userItemId, successCallback, errorCallback) {
                    return resource.history({
                        userItemId: userItemId
                    },
                        successCallback,
                        errorCallback
                    );
                }
            };
        }
    ]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('inventoryFilters', ['$filter', '$rootScope', 'localize', function ($filter, $rootScope, metLocalize) {
        var service = {};
        service.filters = [];
        service.availableFilters = { locationIds: [], manufacturerIds: [], personIds: [], tradeIds: [], statusIds: [], categoryIds: [] };
        service.selectedFilters = [];
        service.oneKeyOnly = false;
        service.tickOnly = false;
        service.searchRequest = {};
        service.hasChanges = false;
        service.searchTerm = "";
        service.selectedFilterCount = 0;
        service.messages = {
            missing: metLocalize('fieldNames', 'itemStatus_Missing')
        }

        service.filtersForTransfersDashboard = {placeIds: [], personIds: [], divisionIds: []}; 

        if (localStorage.getItem("selectedFilters")) {
            service.selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));
        }

        service.createFilters = function (itemFieldFactory) {
            service.filters.push(createFilter("place", "placeId", "list", itemFieldFactory.locations, service.availableFilters.placeIds, 'placeName', 'placeId'));
            service.filters.push(createFilter("lastSeen", "lastSeen", "date"));
            service.filters.push(createFilter("manufacturer", "manufacturerId", "list", itemFieldFactory.manufacturers, service.availableFilters.manufacturerIds, 'manufacturerName', 'manufacturerId'));
            service.filters.push(createFilter("person", "PersonId", "list", itemFieldFactory.people, service.availableFilters.personIds, 'personName', 'personId'));
            service.filters.push(createFilter("division", "divisionId", "list", itemFieldFactory.trades, service.availableFilters.tradeIds, 'divisionName', 'divisionId'));
            service.filters.push(createFilter("maintenance", "maintenanceNeeded", "bool"));
            service.filters.push(createFilter("status", "itemStatus", "list", itemFieldFactory.statuses, service.availableFilters.statusIds, "statusName", "statusId"));
            service.filters.push(createFilter("price", "price", "list", itemFieldFactory.values, [1, 2, 3, 4, 5], 'label', 'id'));
            service.filters.push(createFilter("purchaseDate", "datePurchased", "date"));
            service.filters.push(createFilter("unseen", "daysUnseen", "date"));
            service.filters.push(createFilter("upcomingService", "upcomingService", "date"));
            service.filters.push(createFilter("pastDueService", "pastDueService", "bool"));
            service.filters.push(createFilter("outsideGeofence", "outsideGeofence", "bool"));
            service.filters.push(createFilter("category", "category", "list", itemFieldFactory.parentCategories, service.availableFilters.categoryIds, 'categoryName', 'categoryId'));
        }        

        $rootScope.$on("list-updated", function (event, args) {
            var filter = findFilter(args.name);
            if (filter) {
                    filter.items = args.items;
            }
        });
        
        function createFilter(name, labelName, filterType, items, enabledItems, itemLabelProperty, itemIdProperty, index) {
            return {
                name: name,
                label: labelName,
                filterType: filterType,
                items: items,
                enabledItems: enabledItems,
                itemLabelProperty: itemLabelProperty,
                itemIdProperty: itemIdProperty
            };
        }

        service.closeAllFilters = function () {
            _.forEach(service.filters, function (value) {
                value.isOpened = false;
            });
        }


        service.updateAvailableFilters = function(filtersAvailable) {
            service.availableFilters = filtersAvailable;
            setEnabledItems("place", service.availableFilters.placeIds);
            setEnabledItems("manufacturer", service.availableFilters.manufacturerIds);
            setEnabledItems("person", service.availableFilters.personIds);
            setEnabledItems("division", service.availableFilters.tradeIds);
            setEnabledItems("status", service.availableFilters.statusIds);
            setEnabledItems("category", service.availableFilters.categoryIds);
        }

        function setEnabledItems(filterName, enabledItems) {
            var filter = findFilter(filterName);
            if (filter) {
                filter.enabledItems = enabledItems
            }
        }

        function findFilter(filterName) {
            return $filter('filter')(service.filters, { name: filterName })[0];
        }

        service.nukeFilters = function() {
            localStorage.removeItem('selectedFilters');
            localStorage.removeItem('oneKeyOnly');
            localStorage.removeItem('transferFrom');
            localStorage.removeItem('tickOnly');
        }

        service.addSelectedFilter = function (filterName, id, label, isQuickFilter, value) {
            service.hasChanges = true;
            var selectedFilter = findSelectedFilter(id, filterName);
            var newFilter = { id: id, label: label, filterName: filterName, isSaved: false, isSelected: true, isQuickFilter: isQuickFilter, value: value };
            if (selectedFilter) {
                var filterToRemove = $filter('filter')(filtersToRemove, { id: selectedFilter.id, filterName: selectedFilter.filterName })[0];
                var filterIndex = filtersToRemove.indexOf(filterToRemove);
                if (filterIndex >= 0) {
                    filtersToRemove.splice(filterIndex, 1);
                }
            } else {
                service.selectedFilters.push(newFilter);
                service.selectedFilterCount += 1;
            }
        }
        
        var filtersToRemove = [];
        service.removeSelectedFilter = function (filterName, id) {
            var selectedFilter = findSelectedFilter(id, filterName);
            if (selectedFilter) {
                service.hasChanges = true;
                filtersToRemove.push(selectedFilter);
                service.selectedFilterCount -= 1;
            }
        }

        function findSelectedFilter(id, filterName) {
            return $filter('filter')(service.selectedFilters, { id: id, filterName: filterName })[0];
        }

        service.removeAllFilters = function () {
            var selected = service.selectedFilters.slice();
            _.forEach(selected, function (element) {
                service.quickRemoveFilter(element);
            });

            // Uncheck the quick filters
            var quickFilters = document.getElementsByClassName('quick-filter');
            _.forEach(quickFilters, function (filter) {
                    filter.children[0].checked = false;
            });

            // Make sure the marked missing side nav goes away as well
            // since we mark that if quick filter for marked missing is checked.
            var sideNavElement = document.getElementById(service.messages.missing.value);
            if (sideNavElement !== null) {
                sideNavElement.checked = false;
            }
            service.selectedFilterCount = 0;
        }

        service.hasFilters = function () {
            return service.selectedFilters.length > 0;
        }

        service.quickRemoveFilter = function (selectedFilter) {
            var filterIndex = service.selectedFilters.indexOf(selectedFilter);
            service.selectedFilters.splice(filterIndex, 1);
            localStorage.removeItem("maintenance");

            switch (selectedFilter.filterName) {
                case "oneKeyOnly": 
                    service.oneKeyOnly = false;
                    break;
                case "tickOnly":                    
                    service.tickOnly = false;
                    break;
                default:
                    clearFilter(selectedFilter.filterName, selectedFilter.id);
                    break;
            }
            localStorage.setItem("selectedFilters", JSON.stringify(service.selectedFilters));
            localStorage.setItem("oneKeyOnly", service.oneKeyOnly);
            localStorage.setItem("tickOnly", service.tickOnly);
        }

        function clearFilter(filterName, id) {
            var filter = findFilter(filterName);
            switch (filter.filterType) {
                case "list":
                    _.forEach(filter.items, function (value, index) {
                        if (value[filter.itemIdProperty] === id) {
                            value.isSelected = false;
                        }
                    });
                    break;
                case "date":
                    filter.value = undefined;
                    break;
                case "bool":
                    filter.value = undefined;
                    break;
            }
        }

        var oneKey = localStorage.getItem("oneKeyOnly");
        if (oneKey) { service.oneKeyOnly = oneKey; }

        var tick = localStorage.getItem("tickOnly");
        if (tick) { service.tickOnly = tick; }

        service.updateFilterResults = function () {
            _.forEach(filtersToRemove, function (value) {
                var filterIndex = service.selectedFilters.indexOf(value);
                service.selectedFilters.splice(filterIndex, 1);
            });
            localStorage.setItem("selectedFilters", JSON.stringify(service.selectedFilters));
            filtersToRemove = [];

            _.forEach(service.selectedFilters, function (value) {
                value.isSaved = true;
            });

            service.searchRequest.searchTerm = service.searchTerm;
            service.searchRequest.oneKeyOnly = service.oneKeyOnly;
            service.searchRequest.tickOnly = service.tickOnly;
            service.searchRequest.places = getSelectedIds("place");
            service.searchRequest.manufacturers = getSelectedIds("manufacturer");
            service.searchRequest.people = getSelectedIds("person");
            service.searchRequest.divisions = getSelectedIds("division");
            service.searchRequest.itemStatuses = getSelectedIds("status");
            service.searchRequest.priceRanges = getSelectedIds('price');
            service.searchRequest.daysSinceLastSeen = getFilterValue('lastSeen');
            service.searchRequest.daysSincePurchaseDate = getFilterValue('purchaseDate');
            service.searchRequest.maintanenceNeeded = getFilterValue('maintenance');
            service.searchRequest.daysUnseen = getFilterValue('unseen');
            service.searchRequest.pastDueService = getFilterValue('pastDueService');
            service.searchRequest.outsideGeofence = getFilterValue('outsideGeofence');
            service.searchRequest.daysTillUpcomingService = getFilterValue('upcomingService');
            service.searchRequest.categories = getSelectedIds("category");
            service.hasChanges = false;
            localStorage.setItem("oneKeyOnly", service.searchRequest.oneKeyOnly);
            localStorage.setItem("tickOnly", service.searchRequest.tickOnly);

            service.filtersForTransfersDashboard.placeIds = service.searchRequest.places;
            service.filtersForTransfersDashboard.personIds = service.searchRequest.people;
            service.filtersForTransfersDashboard.divisionIds = service.searchRequest.divisions;

            $rootScope.$broadcast('updated-Results', service.filtersForTransfersDashboard);
        }

        function getSelectedIds(filterName) {
            var filter = findFilter(filterName);
            var items = [];
            var filteredItems = [];
            var selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));

            if (filter) {
                items = $filter('filter')(filter.items, { isSelected: true }).map(function (e) { return e[filter.itemIdProperty] });
            }
            
            if (items.length === 0) {
                filteredItems = $filter('filter')(selectedFilters, { isSelected: true, filterName: filterName }).map(function (e) { return e['id'] });
                if (filteredItems.length > 0)
                    return filteredItems;
            }

            return items;
        }

        function getFilterValue(filterName) {
            var filter = findFilter(filterName);
            var selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));

            var filterItem = selectedFilters.filter(function (item) {
                return item.filterName === filterName;
            })

            if (filterItem.length > 0) {
                return filterItem[0].value;
            }

            if (localStorage.getItem("maintenance") && localStorage.getItem("maintenance") !== "undefined") {
                filter.value = localStorage.getItem("maintenance");
            }
            return filter ? filter.value : undefined;
        }

        return service;
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('inventoryGridConfig', ['$filter', '$rootScope', 'localize', 'metLocalStorage', 'featureToggle',
    function ($filter, $rootScope, metLocalize, metLocalStorage, featureToggle) {
        var service = {};

        service.loadedGroups = [];
        service.gridSort = metLocalStorage.getGridSort();
        service.allItemsSelected = false;
        service.totalResults = 0;
        service.resultsPerPage = metLocalStorage.getResultsPerPage();
        service.pageIndex = 0;
        service.groupBy = 0;
        service.availableFilters = [];

        var messages = {
            available: metLocalize('fieldNames', 'itemStatus_Available'),
            damaged: metLocalize('fieldNames', 'itemStatus_Damaged'),
            missing: metLocalize('fieldNames', 'itemStatus_Missing'),
            retired: metLocalize('fieldNames', 'itemStatus_Retired'),
        }

        service.gridUpdated = function (response, isPaging) {
            service.loadedGroups.splice(0, service.loadedGroups.length);
            _.forEach(response.groupedItems, function (group, index) {
                service.loadedGroups.push(group);
                group.selected = service.allItemsSelected || service.selectedGroupIds.indexOf(group.id) != -1;
                service.allItemsSelected = true;
                _.forEach(group.items, function (item, index) {
                    item.selected = service.selectedItemIds.indexOf(item.id) != -1;
                    if (!item.selected) {
                        service.allItemsSelected = false;
                        group.selected = false;
                    }

                    switch (item.statusId) {
                        case 0:
                            item.status = messages.available.value;
                            break;
                        case 1:
                            item.status = messages.missing.value;
                            break;
                        case 2:
                            item.status = messages.damaged.value;
                            break;
                        case 3:
                            item.status = messages.retired.value;
                            break;
                    }
                });
            });
            service.totalResults = response.totalCount;
            service.availableFilters = response.availableFilters;
            var startNumber = service.getSkipTotal() + 1;
            var pageNumber = service.pageIndex + 1;
            $rootScope.$broadcast("grid-updated", { isPaging: isPaging, totalResults: service.totalResults, startNumber: startNumber, currentPage: pageNumber, resultsPerPage: service.resultsPerPage, availableFilters: service.availableFilters });
        }

        service.bulkUpdateGridProperties = function (itemProperty, value) {
            _.forEach(service.loadedGroups, function (group, index) {
                _.forEach(group.items, function (item, index) {
                    if (item.selected) {
                        item[itemProperty] = value;
                    }
                });
            });
        }

        service.selectedGroupIds = [];
        service.selectedItemIds = [];
        service.selectedLocationIds = [];
        function addIdToList(list, id) {
            var listIndex = list.indexOf(id);
            if (listIndex == -1) {
                list.push(id);
            }            
        }

        function removeIdFromList(list, id) {
            var listIndex = list.indexOf(id);
            if (listIndex > -1) {
                list.splice(listIndex, 1);
            }            
        }

        service.selectedFieldCount = 0;
        service.selectedGroupIds = [];
        service.updateSelectedFields = function () {
            service.selectedFieldCount = 0;
                _.forEach(service.loadedGroups, function (group, index) {
                    var count = 0;
                    if (group.selected) {
                        count = group.count;
                        addIdToList(service.selectedGroupIds, group.id);
                        _.forEach(group.items, function (item, index) {
                            if (item.selected) {
                                addIdToList(service.selectedItemIds, item.id);
                            }
                        })
                    } else {
                        removeIdFromList(service.selectedGroupIds, group.id);
                        _.forEach(group.items, function (item, index) {
                            if (item.selected) {
                                count++;
                                addIdToList(service.selectedItemIds, item.id);
                                addIdToList(service.selectedLocationIds, item.id + "|" + item.placeId);
                            } else {
                                removeIdFromList(service.selectedItemIds, item.id);
                                removeIdFromList(service.selectedLocationIds, item.id + "|" + item.placeId);
                            }
                        });
                    }
                    service.selectedFieldCount += count;
                });
                service.selectedFieldCount = service.selectedItemIds.length;
        }

        service.selectAll = function () {
            _.forEach(service.loadedGroups, function (group, index) {
                group.selected = service.allItemsSelected;
                _.forEach(group.items, function (item, index) {
                    item.selected = service.allItemsSelected;
                    addIdToList(service.selectedItemIds, item.id);
                    addIdToList(service.selectedLocationIds, item.id + "|" + item.placeId);
                });
            });
            service.updateSelectedFields();
        }

        service.setResultsPerPage = function(results) {
            metLocalStorage.setResultsPerPage(results);
            service.resultsPerPage = results;
        }

        service.headerValues = [
            createHeaderValue("inventoryToolNumber", "toolNumber", "small", true),
            createHeaderValue("inventoryGridModelDescription", "description", "large", true),
            createHeaderValue("serialNumber", "serialNumber", "large", true),
            createHeaderValue("barcodeId", "barcodeId", 'medium', false),
            createHeaderValue("manufacturerId", "manufacturer", "medium", false),
            createHeaderValue("categoryId", "category", "medium", true),
            createHeaderValue("placeId", "place", "small", true),
            createHeaderValue("personId", "person", "small", true),
            createHeaderValue("divisionId", "trade", "small", false),
            createHeaderValue("itemStatus", "status", "small", false),
            createHeaderValue("lastSeen", "lastSeen", "medium", true),
            createHeaderValue("coinCellLevel", "coinCell", "large", false),
            createHeaderValue("price", "price", "small", false),
            createHeaderValue("datePurchased", "purchaseDate", "medium", false),
            createHeaderValue("purchaseLocation", "purchaseLocation", "large", false),
        ];

        featureToggle.getAll()
            .then(function (response) {
                service.enableBarcode = response.inventorybarcode;
                if (!service.enableBarcode) {
                    service.headerValues.splice(3, 1);
                }
            });

        service.columnIsVisible = function (columnName) {
            var column = $filter('filter')(service.headerValues, { columnName: columnName })[0];
            return column ? column.isVisible : false;
        }

        service.getSkipTotal = function () {
            return service.resultsPerPage * service.pageIndex;
        }

        function createHeaderValue(labelValue, columnName, width, visible) {
            var isSorted = service.gridSort.field == columnName;
            var isDescending = isSorted && service.gridSort.isDescending;
            var hasIcon = columnName == "description";
            var columnInfo = metLocalStorage.getColumnInfo(columnName, visible);
            var header = {
                label: metLocalize('fieldNames', labelValue), columnName: columnName, isVisible: columnInfo.visible,
                isSorted: isSorted, sortDescending: isDescending, hasIcon: hasIcon
            };

            switch (width) {
                case "large":
                    header.isLarge = true;
                    break;
                case "medium":
                    header.isMedium = true;
                    break;
                default:
                    header.isSmall = true;
                    break;
            }

            return header;
        }

        return service;
    }]);
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('categories', ['$resource', 'urls', function($resource, metUrls) {
        
        var resource = $resource(metUrls('categoryApi').concat('/:categoryId'),
        {
            categoryId: '@categoryId'
        }, 
        {
            'update': {
                method: 'PUT'
            },
            'query': {
                method: 'GET',
                isArray: false
            }
        });

        return {
            getAll: function (options, success, error) {
                return resource.query(options, success, error);
            },
            getCategory: function(categoryId, success, error) {
                return resource.get({
                    categoryId: categoryId
                }, success, error);
            },
            update: function(category, success, error) {
                return resource.update(category, success, error);
            },
            create: function(category, success, error) {
                return resource.save(category, success, error);
            },
            remove: function(category, success, error) {
                return resource.remove({
                    categoryId: category.categoryId
                }, success, error);
            }
        };
    }]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('itemStatuses', ['$resource', 'urls', function ($resource, metUrls) {

        var resource = $resource(metUrls('statusApi'),
        { },
        {
            'query': {
                method: 'GET',
                isArray: false
            }
        });

        return {
            getAll: function (success, error) {
                return resource.query({}, success, error);
            }
        };
    }]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metBoolFilter', [
        'urls', 'localize', 'inventoryFilters',
        function (metUrls, metLocalize, metInventoryFilters) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryBoolFilterHtml'),
                scope: true,
                link: function (scope, element, attrs) {
                    scope.boolMessages = {
                        yesLabel: metLocalize('commands', 'yes'),
                        noLabel: metLocalize('commands', 'no'),
                        selectedTrueLabel: metLocalize('messages', 'MaintenanceNeeded'),
                        selectedFalseLabel: metLocalize('messages', 'NoMaintenanceNeeded')
                    }

                    scope.modalChanged = function () {
                        if (scope.filter.value != undefined) {
                            var selectedLabel = scope.filter.value == true ? scope.boolMessages.selectedTrueLabel.value : scope.boolMessages.selectedFalseLabel.value;
                            metInventoryFilters.addSelectedFilter(scope.filter.name, 1, selectedLabel);
                        } else {
                            metInventoryFilters.removeSelectedFilter(scope.filter.name, 1);
                        }
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metDateRangeFilter', [
        'urls', 'localize', 'inventoryFilters',
        function (metUrls, metLocalize, metInventoryFilters) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryDateRangeFilterHtml'),
                scope:true,
                link: function (scope, element, attrs) {
                    var filterLabel = "";
                    switch (scope.filter.name) {
                        case "lastSeen":
                            filterLabel = "lastSeenRange";
                            break;
                        case "purchaseDate":
                            filterLabel = "purchaseDateRange";
                            break;
                    }

                    scope.dateMessages = {
                        filterLabel: metLocalize('messages', filterLabel),
                        sevenDays: metLocalize('fieldNames', "lastSevenDays"),
                        thirtyDays: metLocalize('fieldNames', "lastThirtyDays"),
                        sixtyDays: metLocalize('fieldNames', "lastSixtyDays"),
                        ninetyDays: metLocalize('fieldNames', "lastNinetyDays"),
                    };

                    scope.modalChanged = function () {
                        var label = scope.dateMessages.filterLabel.value.replace("{0}", scope.filter.value);
                        if (scope.filter.value != undefined) {
                            metInventoryFilters.addSelectedFilter(scope.filter.name, 1, label);
                        } else {
                            metInventoryFilters.removeSelectedFilter(scope.filter.name, 1);
                        }
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metFilters', [
        '$filter', 'urls', 'localize', 'itemFieldFactory', 'inventoryFilters',
        function ($filter, metUrls, metLocalize, metItemFields, metInventoryFilters) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryFiltersHtml'),
                scope: {
                    updateResults: '&',
                    showHideFilters: '&',
                    region: '=',
                    categories: '&',
                    oneKey: '&'
                },
                link: function (scope, element, attrs) {
                    scope.filterMessages = {
                        update: metLocalize('commands', 'update'),
                        closeFilters: metLocalize('commands', 'closeFilters'),
                        clearAll: metLocalize('commands', 'ClearAll'),
                        oneKey: metLocalize('titles', 'oneKey'),
                        oneKeyText: metLocalize('titles', 'oneKeyText'),
                        oneKeyOnly: $('#oneKeyOnlyString').val(),
                        oneKeyOnlyText: metLocalize('fieldNames', 'oneKeyOnlyText'),
                        tickOnly: $('#tickString').val(),
                        tickOnlyText: metLocalize('fieldNames', 'tickOnlyText')
                    }

                    scope.showHideOneKeyFilter = function () {
                        var isOpened = scope.oneKey.isOpened;
                        scope.oneKey.isOpened = !isOpened;
                    }
                   
                    var priceItems = [
                        { id: 1, label: $('#lessThanFiftyString').val() },
                        { id: 2, label: $('#fiftyToHundredString').val() },
                        { id: 3, label: $('#hundredToTwoFiftyString').val() },
                        { id: 4, label: $('#twoFiftyToFiveHundredString').val() },
                        { id: 5, label: $('#aboveFiveHundredString').val() }
                    ]

                    metItemFields.values = priceItems;
                    metInventoryFilters.createFilters(metItemFields);
                    scope.filters = metInventoryFilters.filters;
                    scope.itemFields = metItemFields;
                    metInventoryFilters.closeAllFilters();
                    scope.inventoryFilters = metInventoryFilters;

                    scope.oneKeyOnlyChanged = function (id) {
                        if (id) {
                            scope.toggleCheckbox(document.getElementById(id));
                        }

                        if (scope.inventoryFilters.oneKeyOnly) {
                            metInventoryFilters.addSelectedFilter("oneKeyOnly", 1, scope.filterMessages.oneKeyOnly);
                        } else {
                            metInventoryFilters.removeSelectedFilter("oneKeyOnly", 1);
                        }
                    }

                    scope.tickOnlyChanged = function (id) {
                        if (id) {
                            scope.toggleCheckbox(document.getElementById(id));
                        }

                        if (scope.inventoryFilters.tickOnly) {
                            metInventoryFilters.addSelectedFilter("tickOnly", 1, scope.filterMessages.tickOnly);
                        } else {
                            metInventoryFilters.removeSelectedFilter("tickOnly", 1);
                        }
                    }

                    scope.toggleCheckbox = function (checkbox) {
                        checkbox.click();
                    }

                    scope.updateFilterResults = function () {
                        scope.updateResults();
                    }

                    scope.removeAllFilters = function () {
                        metInventoryFilters.removeAllFilters();
                        metInventoryFilters.nukeFilters();
                        scope.updateResults();
                    }

                    scope.init = true;

                    scope.selectedFilterItems = JSON.parse(localStorage.getItem("selectedFilters"));

                    scope.initialize = function () {
                        if (scope.selectedFilterItems != null) {
                            for (var i = 0; i < scope.selectedFilterItems.length; i++) {
                                if (scope.selectedFilterItems[i].filterName == "oneKeyOnly") {
                                    scope.inventoryFilters.oneKeyOnly = true;
                                }
                                if (scope.selectedFilterItems[i].filterName == "tickOnly") {
                                    scope.inventoryFilters.tickOnly = true;
                                }
                            }
                        }
                    }
                    scope.initialize();
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metFilterSelector', [
        '$filter', 'urls', 'localize', 'dates', 'inventoryFilters',
        function ($filter, metUrls, metLocalize, metDates, metInventoryFilters) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryFilterSelector'),
                scope: {
                    filter: '=metFilter',
                },
                link: function (scope, element, attrs) {
                    scope.filterLabel = metLocalize('fieldNames', scope.filter.label);
                    scope.datePickerOptions = metDates.getDatePickerOptions();

                    scope.showHideFilter = function () {
                        var isOpened = scope.filter.isOpened;
                        scope.filter.isOpened = !isOpened;
                    }

                    scope.selectedFilters = JSON.parse(localStorage.getItem("selectedFilters"));

                    scope.showSelectedLabel = false;
                    scope.selectedLabel = function () {
                        var label = "";
                        switch (scope.filter.filterType) {
                            case "list":
                                if (scope.selectedFilters.length != 0) {
                                    label = $filter('filter')(scope.selectedFilters, { isSelected: true, filterName: scope.filter.name }).length.toString();
                                    break;
                                }
                                label = $filter('filter')(scope.filter.items, { isSelected: true }).length.toString();
                                break;
                            case "date":
                            case "bool":
                                if (scope.selectedFilters.length != 0) {
                                    label = $filter('filter')(scope.selectedFilters, { isSelected: true, filterName: scope.filter.name }).length.toString();
                                    break;
                                }
                                if (scope.selectedFilters.length == 0) {
                                    label = scope.filter.value == undefined ? "0" : "1";
                                    break;
                                }
                                label = scope.filter.value == undefined ? "0" : "1";
                                break;
                        }

                        scope.showSelectedLabel = label.length > 0 && label != "0";
                        return label;
                    }

                    scope.updateSelectedLabel = function (label) {
                        scope.selectedLabel = label;
                    }
                    
                    scope.labelClicked = function (item) {
                        item.isSelected = !item.isSelected;
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metItemFilter', [
        '$filter', 'urls', 'inventoryFilters', 'localize',
        function ($filter, metUrls, metInventoryFilters, metLocalize) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryItemFilterHtml'),
                scope: {
                    filter: '='
                },
                link: function (scope, element, attrs) {
                    scope.messages = {
                        search: metLocalize('commands', 'search'),
                    }

                    scope.labelClicked = function (item) {
                        if (!scope.isDisabled(item[scope.filter.itemIdProperty])) {
                            item.isSelected = !item.isSelected;
                            scope.itemChange(item);
                        }
                    }

                    scope.itemChange = function (item) {
                        if (item.isSelected) {
                            metInventoryFilters.addSelectedFilter(scope.filter.name, item[scope.filter.itemIdProperty], item[scope.filter.itemLabelProperty]);
                        } else {
                            metInventoryFilters.removeSelectedFilter(scope.filter.name, item[scope.filter.itemIdProperty]);
                        }
                    }

                    scope.selectedFilterItems = JSON.parse(localStorage.getItem("selectedFilters"));

                    scope.isDisabled = function (id) {
                        if (scope.filter.enabledItems !== undefined) {
                            return scope.filter.enabledItems.indexOf(id) == -1;
                        }
                    }

                    scope.initialize = function (item) {
                        for (var i = 0; i < scope.selectedFilterItems.length; i++) {
                            if (item[scope.filter.itemLabelProperty] == scope.selectedFilterItems[i].label ) {
                                item.isSelected = scope.selectedFilterItems[i].isSelected;
                            }
                        }
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metQuickFilters', [
        '$filter', 'urls', 'localize', 'itemFieldFactory', 'inventoryFilters', 'featureToggle',
        function ($filter, metUrls, metLocalize, metItemFields, metInventoryFilters, featureToggle) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryQuickFiltersHtml'),
                scope: {
                    updateResults: '&',
                    showHideFilters: '&',
                    region: '=',
                    categories: '&'
                },
                link: function (scope, element, attrs) {
                    scope.filterMessages = {
                        markedMissing: metLocalize('fieldNames', 'markedMissing'),
                        unseen: metLocalize('fieldNames', 'unseenFiveDays'),
                        upcomingService: metLocalize('fieldNames', 'upcomingService'),
                        pastDueService: metLocalize('fieldNames', 'pastDueService'),
                        oneKeyItem: metLocalize('messages', 'oneKeyItem'),
                        seenOutsideGeofence: metLocalize('messages', 'seenOutsideGeofence'),
                        needsService: metLocalize('messages', 'needsService')
                    }
                    featureToggle.getAll()
                        .then(function (response) {
                            scope.enableGeofence = response.geofence;
                        });
                    scope.markedMissing = function () {
                        var element = document.getElementById("markedMissing");
                        var sideNavElement = document.getElementById("status_1");
                        if (element.checked) {
                            metInventoryFilters.addSelectedFilter("status", 1, "Missing", true);
                            sideNavElement.checked = true;
                        } else {
                            metInventoryFilters.removeSelectedFilter("status", 1);
                            sideNavElement.checked = false;
                        }
                        setTimeout(function () { scope.updateResults();}, 300);
                    }

                    scope.upcomingService = function () {
                        var element = document.getElementById("hasUpcomingService");
                        if (element.checked) {
                            metInventoryFilters.addSelectedFilter("maintenance", 1, "maintenanceNeeded", true, true);
                        } else {
                            metInventoryFilters.removeSelectedFilter("maintenance", 1);
                        }
                        setTimeout(function () { scope.updateResults(); }, 300);
                    }

                    scope.unseen = function () {
                        var element = document.getElementById("unseen");
                        if (element.checked) {
                            metInventoryFilters.addSelectedFilter("unseen", 1, "unseen", true, 5);
                        } else {
                            metInventoryFilters.removeSelectedFilter("unseen", 1);
                        }
                        setTimeout(function () { scope.updateResults(); }, 300);
                    }

                    scope.outsideGeofence = function () {
                        var element = document.getElementById("outsideGeofence");
                        if (element.checked) {
                            metInventoryFilters.addSelectedFilter("outsideGeofence", 1, "outsideGeofence", true, true);
                        } else {
                            metInventoryFilters.removeSelectedFilter("outsideGeofence", 1);
                        }
                        setTimeout(function () { scope.updateResults(); }, 300);
                    }


                    scope.updateFilterResults = function () {
                        scope.updateResults();
                    }

                    scope.init = true;

                    scope.selectedFilterItems = JSON.parse(localStorage.getItem("selectedFilters"));

                    scope.initialize = function () {

                        if (scope.selectedFilterItems !== null) {
                            for (var i = 0; i < scope.selectedFilterItems.length; i++) {
                                if ("Missing" === scope.selectedFilterItems[i].label) {
                                    var missingElement = document.getElementById("markedMissing");
                                    missingElement.checked = true;
                                }
                                if ("maintenanceNeeded" === scope.selectedFilterItems[i].label) {
                                    var upcomingServiceElement = document.getElementById("hasUpcomingService");
                                    upcomingServiceElement.checked = true;
                                }
                                if ("pastDueService" === scope.selectedFilterItems[i].label) {
                                    var pastDueServiceElement = document.getElementById("pastDueService");
                                    pastDueServiceElement.checked = true;
                                }
                                if ("unseen" === scope.selectedFilterItems[i].label) {
                                    var unseenElement = document.getElementById("unseen");
                                    unseenElement.checked = true;
                                }
                                if ("outsideGeofence" === scope.selectedFilterItems[i].label) {
                                    var outsideGeofenceElement = document.getElementById("outsideGeofence");
                                    outsideGeofenceElement.checked = true;
                                }
                            }
                        }
                    }

                    scope.initialize();
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metSelectedFilters', [
        '$filter', 'urls', 'inventoryFilters',
        function ($filter, metUrls, metInventoryFilters) {
            return {
                restrict: 'E',
                replace: true,
                scope: {
                    selectedFilters: '=',
                    updateResults: '&'
                },
                templateUrl: metUrls('inventorySelectedFiltersHtml'),
                link: function (scope, element, attrs) {

                    scope.showSelectedFilters = function () {
                        return $filter('filter')(scope.selectedFilters, { isSaved: true });
                    }

                    scope.quickRemoveFilter = function (selectedFilter) {
                        metInventoryFilters.quickRemoveFilter(selectedFilter);
                        setTimeout(function () { scope.updateResults(); }, 500);
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.factory('itemFieldFactory', ['$rootScope', 'categories', 'trades', 'people', 'locations', 'manufacturers', 'itemStatuses',
        function ($rootScope, metCategories, metTrades, metPeople, metLocations, metManufacturers, metStatuses) {

        var service = {};
        service.categories = [];
        service.parentCategories = [];
        service.nullCategory = {};
        service.locations = [];
        service.nullLocation = {};
        service.people = [];
        service.nullPerson = {};
        service.manufacturers = [];
        service.trades = [];
        service.nullTrade = {};
        service.statuses = [];
        service.values = [];

        service.init = function () {
            this.loadCategories();
            this.loadTrades();
            this.loadPeople();
            this.loadLocations();
            this.loadManufacturers();
            this.loadStatuses();
        };
        
        service.loadCategories = function () {
            metCategories.getAll({
                includeUncategorized: true
            },
                function (data) {
                    var categories = [];
                    service.parentCategories = [];
                    _.forEach(data.items, function (category) {
                        category.displayName = category.categoryName;
                        categories.push(category);
                        service.parentCategories.push(category);
                        _.forEach(category.childCategories, function (childCategory) {
                            childCategory.displayName = childCategory.categoryName;
                            childCategory.categoryName = "--  " + childCategory.categoryName; // <--- COMPLETE HACK, but will do for now until we decide exact UI
                            categories.push(childCategory);
                        });
                    });

                    service.categories = categories;
                    $rootScope.$broadcast("list-updated", { name: "category", items: service.categories });
                });
            service.nullCategory = _.findWhere(service.categories, {
                categoryId: -1
            });
        }

        service.loadTrades = function () {
            metTrades.getAll({
                includeUnspecified: true
            },
                function (data) {
                    _.forEach(data.items, function (trade) {
                        service.trades = data.items;
                    });

                    $rootScope.$broadcast("list-updated", { name: "division", items: service.trades });
                });

            service.nullTrade = _.findWhere(service.trades, {
                divisionId: -1
            });
        }

        service.loadPeople = function () {
            metPeople.getAll({
                includeUnspecified: true
            },
                function (data) {
                    _.forEach(data.items, function (person) {
                        service.people = data.items;
                    });

                    $rootScope.$broadcast("list-updated", { name: "person", items: service.people });
                });
            service.nullPerson = _.findWhere(service.people, {
                personId: -1
            });
        }

        service.loadLocations = function () {
            metLocations.getAll({
                includeUnspecified: true,
                forAssignment: true
            },
                function (data) {
                    _.forEach(data.items, function (value) {
                        service.locations = data.items;
                    });

                    $rootScope.$broadcast("list-updated", { name: "place", items: service.locations });
                });
            service.nullLocation = _.findWhere(service.locations, {
                placeId: -1
            });
        }

        service.loadManufacturers = function () {
            metManufacturers.getAll(function (data) {
                _.forEach(data.items, function (value) {
                    service.manufacturers = data.items;
                });

                $rootScope.$broadcast("list-updated", { name: "manufacturer", items: service.manufacturers });
            });
        };

        service.loadStatuses = function () {
            metStatuses.getAll(function (data) {
                _.forEach(data.items, function (value) {
                    service.statuses = data.items;
                });

                $rootScope.$broadcast("list-updated", { name: "status", items: service.statuses });
            });
        };

        return service;
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.controller('historyController', [
        '$scope', '$rootScope', '$timeout', '$modal', '$log', '$window', 'localize', 'notify', 'transfers', 'dates',

        function notificationsController($scope, $rootScope, $timeout, $modal, $log, $window, localize, notify, transfers, metDates) {
            $scope.loading = true;
            $scope.updating = false;

            $scope.transferHeaders = [
                { label: localize('fieldNames', 'TransferDate') },
                { label: localize('fieldNames', 'TransferFromPlace') },
                { label: localize('fieldNames', 'TransferTo') },
                { label: localize('fieldNames', 'TotalItems') }
            ];

            $scope.unspecified = localize('titles', 'unassigned');
			 
            $scope.transfers = [];
            $scope.isSelected = false;
            $scope.sortType = '';
            $scope.sortReverse = false;

            $scope.empty = function () {
                return $scope.transfers === null || $scope.transfers.length === 0;
            };

            $scope.toggleSelected = function (header) {
                _.forEach($scope.transferHeaders,
                    function(value) {
                        value.selected = false;
                    });
            	$scope.sortType = $scope.getSortType(header.label);
            	$scope.sortReverse = !$scope.sortReverse;
            	header.selected = true;
            };

            $scope.getSortType = function (header) {
                var str = '';
                var result = header.value;
                switch (result) {
            		case $scope.transferHeaders[0].label.value:
                        str = 'transferredOn';
            			break;
            		case $scope.transferHeaders[1].label.value:
                        str = 'fromPlaces';
            			break;
            		case $scope.transferHeaders[2].label.value:
                        str = 'tos';
            			break;
            		case $scope.transferHeaders[3].label.value:
                        str = 'count';

            	}
            	return str;
            };

            $scope.timeZone = new jstz.determine().name();

            $scope.generate = function (baseUrl, id) {
                var url = baseUrl + '?Id=' + id + '&timeZone=' + $scope.timeZone;
                document.cookie = "Authorization=Bearer " + localStorage.getItem('access_token') + ";path=/";
                $window.location.href = url;

            };

            $scope.initialize = function () {
                var success = function (response) {
                    $scope.transfers = response;
                    for (var i = 0; i < $scope.transfers.length; i++) {
                        
                        if ($scope.transfers[i].fromLocationName === null) {
                            $scope.transfers[i].fromLocationName = $scope.unspecified.value;
                        }
                        if ($scope.transfers[i].toLocationName === null) {
                            $scope.transfers[i].toLocationName = $scope.unspecified.value;
                        }
                        if ($scope.transfers[i].fromPlaceNames && $scope.transfers[i].fromPlaceNames.length > 0) {
                            $scope.transfers[i].fromPlaces = $scope.transfers[i].fromPlaceNames.join(', ');
                        } else {
                            $scope.transfers[i].fromPlaces = $scope.transfers[i].fromLocationName;
                        }
                        var tranferTos = [];
                        if ($scope.transfers[i].toLocationName) {
                            tranferTos.push($scope.transfers[i].toLocationName);
                        }
                        if ($scope.transfers[i].toPersonName) {
                            tranferTos.push($scope.transfers[i].toPersonName);
                        }
                        if ($scope.transfers[i].toDivisionName) {
                            tranferTos.push($scope.transfers[i].toDivisionName);
                        }
                        if ($scope.transfers[i].toStatusName) {
                            tranferTos.push($scope.transfers[i].toStatusName);
                        }
                        $scope.transfers[i].tos = tranferTos.join(', ');

                        $scope.transfers[i].transferredOnLocal = metDates.convertUtcToLocal($scope.transfers[i].transferredOn, metDates.date(true));
                    }
                    $scope.toggleSelected($scope.transferHeaders[0]);
                    $scope.loading = false;
                };

                var error = function () {
                    $scope.loading = false;
                };

                transfers.getAll(success, error);
            };
        }
    ]);
}());
(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.controller('transfersController',
        [
            '$scope', '$rootScope', '$modal', '$window', 'localize', 'itemStatuses',
            'notify', 'transfers', 'locations', 'categories', 'trades', 'people', 'urls', '$templateCache',
            'itemFieldFactory', 'inventoryFilters', 'userItems', 'inventoryGridConfig', '$http', '$filter', 'authService',
            function transfersController($scope,
                $rootScope,
                $modal,
                $window,
                localize,
                itemStatuses,
                notify,
                transfers,
                locations,
                categories,
                trades,
                people,
                metUrls,
                $templateCache,
                metItemFieldFactory,
                metInventoryFilters,
                metUserItems,
                metInventoryGrid,
                $http,
                $filter,
                authService
            ) {
                var buildRequest = function() {
                    var ids = $scope.selectedItems.map(function(x) { return x.id });

                    if (!$scope.selectedToPlace) {
                        notify.error($scope.messages.transferToPlaceMissing.value);
                        return {
                            success: false
                        };
                    }
                    var request = {
                        ToPlaceId: $scope.selectedToPlace.placeId,
                        FromPlaceId: $scope.selectedItems[0].placeId,
                        MakeSignable: true,
                        UserItemIds: ids
                    };

                    if ($scope.selectedToDivision && $scope.selectedToDivision.divisionId !== '') {
                        request.ToTradeId = $scope.selectedToDivision.divisionId;
                    }

                    if ($scope.selectedToPerson && $scope.selectedToPerson.personId !== '') {
                        request.ToPersonId = $scope.selectedToPerson.personId;
                    }

                    if ($scope.selectedToStatus && $scope.selectedToStatus.statusId !== '') {
                        request.ToStatusId = $scope.selectedToStatus.statusId;
                    }

                    return {
                        success: true,
                        request: request
                    };
                };

                $scope.completed = {
                    id: ''
                };

                $scope.loading = {
                    categories: true,
                    locations: true,
                    trades: true,
                    people: true,
                    transfers: false,
                    statuses: false,
                    searches: {
                        from: false
                    },
                    disable: function() {
                        return this.isLoading();
                    },
                    isLoading: function() {
                        return this.categories || this.locations || this.transfers || this.people || this.trades;
                    }
                };

                $scope.updating = false;
                $scope.locations = [];
                $scope.categories = [];
                $scope.trades = [];
                $scope.people = [];
                $scope.statuses = [];
                $scope.totalResults = 0;
                $scope.resultsPerPage = metInventoryGrid.resultsPerPage;
                $scope.pageIndex = 0;

                if (authService.isAuthenticated()) {
                    metItemFieldFactory.init();
                }
                
                $scope.inventoryFilters = metInventoryFilters;
                $scope.selectedFilters = metInventoryFilters.selectedFilters;
                $scope.inventoryItems = [];
                $scope.selectedToStatus = null;
                $scope.selectedToDivision = null;
                $scope.selectedToPerson = null;
                $scope.selectedToPlace = null;
                $scope.selectAll = false;
                $scope.totalItems = 0;
                $scope.selectedTos = {};
                $scope.totalFilters = 0;
                $scope.submitting = false;
                $scope.searchTerm = "";

                $scope.messages = {
                    of: localize('messages', 'of'),
                    item: localize('messages', 'item'),
                    items: localize('messages', 'items'),
                    noSearchResults: localize('messages', 'TransferToContainerEmpty'),
                    error: localize('messages', 'unexpectedError'),
                    success: localize('messages', 'ToolTransferSuccessful'),
                    descriptionLabel: localize('fieldNames', 'itemDescription'),
                    toolNumberLabel: localize('fieldNames', 'toolNumber'),
                    modelLabel: localize('fieldNames', 'inventoryGridModelNumber'),
                    transferFromLocationMissing: localize('messages', 'TransferFromLocationMissing'),
                    transferToPlaceMissing: localize('messages', 'transferToPlaceMissing'),
                    transferItemsMissing: localize('messages', 'TransferItemsMissing'),
                    division: localize('fieldNames', 'divisionId'),
                    place: localize('fieldNames', 'placeId'),
                    searchOrAdd: localize('commands', 'searchOrAdd'),
                    person: localize('fieldNames', 'personId'),
                    status: localize('fieldNames', 'itemStatus'),
                    searchForItems: localize('commands', 'searchForItems'),
                    results: localize('fieldNames', 'results'),
                    noTransferOptions: localize('messages', 'noTransferOptions'),
                    setStatus: localize('commands', 'setStatus'),
                    selectedItems: localize('fieldNames', 'selectedItems'),
                    clearAll: localize('commands', 'clearAll'),
                    submit: localize('commands', 'submit')
                };

                $scope.transfer = function() {
                    $scope.submitting = true;
                    var model = buildRequest();
                    if (!model.success) {
                        $scope.submitting = false;
                        return;
                    }

                    var success = function(transfer) {
                        $scope.loading.transfers = false;
                        $('#ajax-loading').hide();
                        $scope.refreshItemList();
                        $scope.clearAll();
                        $scope.submitting = false;

                        $scope.completed.id = transfer.id;
                        var modalInstance = $modal.open({
                            template: $templateCache.get('success.html'),
                            size: 'md',
                            scope: $scope
                        });
                    };

                    var failure = function() {
                        $('#ajax-loading').hide();
                        notify.error($scope.messages.error.value);
                        $scope.loading.transfers = false;
                        $scope.submitting = false;
                    };

                    $('#ajax-loading').show();
                    var request = model.request;
                    transfers.transfer(request, success, failure);
                };

                var transferId = function() {
                    if ($scope.completed.id) {
                        return $scope.completed.id;
                    }
                    return null;
                };

                $scope.timeZone = new jstz.determine().name();

                $scope.showHideFilters = showHideFilters;
                $scope.filtersExpanded = false;

                function showHideFilters() {
                    $scope.filtersExpanded = !$scope.filtersExpanded;
                }

                $scope.generate = function(baseUrl) {
                    var id = transferId();
                    var url = baseUrl + '?Id=' + id + '&timeZone=' + $scope.timeZone;
                    document.cookie = "Authorization=Bearer " + localStorage.getItem('access_token') + ";path=/";
                    $window.location.href = url;

                };

                $scope.refreshItemList = function(isFilter, userItemId) {
                    $scope.totalFilters = angular.copy($scope.inventoryFilters.selectedFilterCount);
                    $scope.inventoryFilters.updateFilterResults();
                    var filters = $scope.inventoryFilters.searchRequest;
                    filters.searchTerm = $scope.searchTerm;
                    filters.take = metInventoryGrid.resultsPerPage;
                    filters.skip = getSkipTotal(isFilter);
                    if (userItemId !== -1 && !isNaN(userItemId)) {
                        filters.itemId = userItemId;
                    }

                    metUserItems.search(filters,
                        function(response) {
                            $scope.inventoryFilters.updateAvailableFilters(response.availableFilters);
                            var startNumber = isFilter ? 1 : getSkipTotal() + 1;
                            var pageNumber = isFilter ? 1 : metInventoryGrid.pageIndex + 1;
                            $rootScope.$broadcast("grid-updated",
                                {
                                    isPaging: true,
                                    totalResults: response.totalCount,
                                    startNumber: startNumber,
                                    currentPage: pageNumber,
                                    resultsPerPage: $scope.resultsPerPage
                                });
                            $scope.inventoryItems = response.groupedItems[0].items;
                            if (userItemId !== -1 && !isNaN(userItemId)) {
                                var selectedItem = $filter('filter')($scope.inventoryItems, { id: userItemId }, true)[0];
                                toggleCheckBox(selectedItem);
                            }
                            $scope.totalItems = response.totalCount;
                            setPageNumberText(pageNumber);
                        });
                    localStorage.setItem("selectedFilters", JSON.stringify([]));
                    $scope.filtersExpanded = false;
                }

                $scope.searchKeyUp = function($event) {
                    if ($event.keyCode === 13) {
                        $scope.refreshItemList();
                    }
                }

                $scope.toggleCheckBox = toggleCheckBox;
                $scope.selectedItems = [];

                function toggleCheckBox(item) {
                    if (item === 'header') {
                        $scope.selectAll = !$scope.selectAll;
                        if ($scope.selectAll) {
                            var filters = $scope.inventoryFilters.searchRequest;
                            filters.skip = 0;
                            filters.take =
                                100000; // Setting to 100,000 becuase that amount of tools is really high and I need to get all tools.
                            metUserItems.search(filters,
                                function(response) {
                                    $scope.selectedItems = response.groupedItems[0].items;
                                    $scope.totalItems = response.totalCount;
                                });
                        }
                        else {
                            $scope.selectedItems = [];
                        }
                        return;
                    }
                    var idx = $scope.selectedItems.map(function(x) { return x.id; }).indexOf(item.id);
                    if (idx > -1) {
                        $scope.selectedItems.splice(idx, 1);
                        $scope.selectAll = false;
                    }
                    else {
                        $scope.selectedItems.push(item);
                    }
                };

                $scope.selectedToString = "";

                function toCSV(obj, separator) {
                    var arr = [];

                    for (var key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            arr.push(obj[key]);
                        }
                    }

                    return arr.join(separator || ", ");
                }

                $scope.onStatusSelect = function(item) {
                    $scope.selectedToStatus = item;
                    $scope.selectedTos.selectedToStatus = $scope.selectedToStatus.statusName;
                    $scope.selectedToString = toCSV($scope.selectedTos);
                };

                $scope.onPersonSelect = function(item) {
                    $scope.selectedToPerson = item;
                    $scope.selectedTos.selectedToPerson = $scope.selectedToPerson.personName;
                    $scope.selectedToString = toCSV($scope.selectedTos);
                };

                $scope.onPlaceSelect = function(item) {
                    $scope.selectedToPlace = item;
                    $scope.selectedTos.selectedToPlace = $scope.selectedToPlace.placeName;
                    $scope.selectedToString = toCSV($scope.selectedTos);
                };

                $scope.onDivisionSelect = function(item) {
                    $scope.selectedToDivision = item;
                    $scope.selectedTos.selectedToDivision = $scope.selectedToDivision.divisionName;
                    $scope.selectedToString = toCSV($scope.selectedTos);
                };

                $scope.clearAll = clearAll;

                function clearAll() {
                    $scope.selectAll = false;
                    $scope.selectedItems = [];
                };

                $scope.exists = exists;

                function exists(item) {
                    if ($scope.selectAll) {
                        return true;
                    }
                    return $scope.selectedItems.map(function(x) { return x.id; }).indexOf(item.id) > -1;
                };

                function getSkipTotal(isFilter) {
                    if (isFilter) {
                        metInventoryGrid.pageIndex = 0;
                    };
                    return $scope.resultsPerPage * metInventoryGrid.pageIndex;
                };

                function setPageNumberText(pageNumber) {
                    var element = document.getElementById('pageNumber');
                    if (element) {
                        element.value = pageNumber;
                    };
                };

                $scope.loadPaging = function() {
                    setTimeout(function() {
                            var startNumber = getSkipTotal() + 1;
                            var pageNumber = metInventoryGrid.pageIndex + 1;
                            $rootScope.$broadcast("grid-updated",
                                {
                                    isPaging: true,
                                    totalResults: $scope.totalItems,
                                    startNumber: startNumber,
                                    currentPage: pageNumber,
                                    resultsPerPage: $scope.resultsPerPage
                                });
                        },
                        100);
                };

                $scope.initialize = function (placeId, userItemId) {
                    $scope.inventoryFilters.tickOnly = false;
                    $scope.inventoryFilters.oneKeyOnly = false;
                    $('#ajax-loading').remove();
                    //if (authService.isAuthenticated()) {
                        locations.getAll({ includeUnspecified: true },
                            function (data) {
                                $scope.loading.locations = false;
                                $scope.locations = data.items;
                                if (placeId !== -1 && !isNaN(placeId)) {
                                    var selectedPlace = $filter('filter')($scope.locations, { placeId: placeId }, true)[0];
                                    if (selectedPlace) {
                                        $scope.onPlaceSelect(selectedPlace);
                                    }
                                }
                            },
                            function (e) {
                                $scope.loading.locations = false;
                            });
                        $scope.refreshItemList(false, userItemId);

                        categories.getAll({ includeUncategorized: true },
                            function (data) {
                                $scope.loading.categories = false;
                                $scope.categories = [];
                                _.forEach(data.items,
                                    function (category) {
                                        $scope.categories.push(category);
                                        _.forEach(category.childCategories,
                                            function (childCategory) {
                                                childCategory.categoryName =
                                                    "--  " +
                                                    childCategory
                                                        .categoryName; // <--- COMPLETE HACK, but will do for now until we decide exact UI
                                                $scope.categories.push(childCategory);
                                            });
                                    });
                            },
                            function (e) {
                                $scope.loading.categories = false;
                            });

                        trades.getAll({ includeUnspecified: true },
                            function (data) {
                                $scope.trades = data.items;
                                $scope.loading.trades = false;
                            },
                            function (e) {
                                $scope.loading.trades = false;
                            });

                        people.getAll({ includeUnspecified: true },
                            function (data) {
                                $scope.people = data.items;
                                $scope.loading.people = false;
                            },
                            function (e) {
                                $scope.loading.people = false;
                            });

                        itemStatuses.getAll(
                            function (data) {
                                $scope.statuses = data.items;
                                $scope.loading.statuses = false;
                            },
                            function () {
                                $scope.loading.statuses = false;
                            });

                        $scope.selectedItemCount = 0;
                        $scope.transferFrom = localStorage.getItem('transferFrom');
                    //}
                    
                };
            }
        ]);
}());

