(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.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.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('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 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 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 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 (module) {
    function reportingService($http, $q, urls) {
        return {
            getStates: function () {
                var url = urls('baseApiUrl').concat('/reports/states');
                var deferred = $q.defer();
                $http.get(url)
                    .success(deferred.resolve)
                    .error(deferred.reject);

                return deferred.promise;
            },

            getStatesByCountryCode: function (code) {
                var url = urls('statesByCountry').concat('/' + code);
                var deferred = $q.defer();
                $http.get(url).success(deferred.resolve).error(deferred.reject);
                return deferred.promise;
            },
            
            getCountries: function () {
                var url = urls('baseApiUrl').concat('/reports/countries');
                var deferred = $q.defer();
                $http.get(url)
                    .success(deferred.resolve)
                    .error(deferred.reject);

                return deferred.promise;
            },

            getUserProfile: function(){
                var url = urls('baseApiUrl').concat('/reports/profile');
                var deferred = $q.defer();
                $http.get(url)
                    .success(deferred.resolve)
                    .error(deferred.reject);

                return deferred.promise;
            },

            getCrimperEvents: function(filters){
                var url = urls('baseApiUrl')
                    .concat('/crimpers/events?' + filters.beginDate + '&' + filters.crimperType + '&' + filters.endDate + '&' + filters.itemInstancIds);
                var deferred = $q.defer();
                $http.get(url)
                    .success(deferred.resolve)
                    .error(deferred.reject);

                return deferred.promise;
            }
        };
    }
    module.factory('reportingService', reportingService);
    reportingService.$inject = ['$http', '$q', 'urls'];
}(angular.module('oneKeyApp')));
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.filter("append", function () {
        return function (array, addOption) {
            if (!angular.isArray(array)) {
                return array;
            }
            if (!addOption) {
                return array;
            }

            return [addOption].concat(array);
        };
    });
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    //pushes empty values to the end of an orderBy, instead of the beginning.
    oneKeyApp.filter("emptyToEnd", function () {
        return function (array, key) {
            if (!angular.isArray(array)) {
                return array;
            }
            if (angular.isArray(key)) {
                return array;
            }

            if (_.startsWith(key, '-')) {
                key = _.trimLeft(key, '-');
            }

            var present = array.filter(function (item) {
                return item[key];
            });
            var empty = array.filter(function (item) {
                return !item[key] || item[key] == '' || item[key] == null;
            });
            return present.concat(empty);
        };
    });
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    //formats end of line marks as <br/>
    oneKeyApp.filter("eolToBr", function () {
        return function (data) {
            if (!data) {
                return data;
            }
            return data.replace(/\r?\n/g, '<br/>');
        };
    });
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.filter('moment', function () {
        return function (dateString, format) {
            if (!_.isString(dateString) && !_.isDate(dateString)) {
                return dateString;
            }
            if (dateString == '') {
                return dateString;
            }

            return moment(dateString).format(format);
        };
    });
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.filter('momentUtc', function () {
        return function (dateString, format) {
            if (!_.isString(dateString) && !_.isDate(dateString)) {
                return dateString;
            }
            if (dateString == '') {
                return dateString;
            }

            return moment.utc(dateString).local().format(format);
        };
    });
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    //overrides number filter to not include commas.
    oneKeyApp.filter('numberNoCommas', ['$filter',
        function ($filter) {
            var standardNumberFilterFn = $filter('number');
            return function (value, places) {
                if (value && !isNaN(value)) {
                    return standardNumberFilterFn(value, places).replace(/,/g, '');
                }
                return '';
            }
        }
    ]);
}());


(function (module) {
    'use strict';

    module.filter('rawHtml', ['$sce', function ($sce) {
        return function (val) {
            return $sce.trustAsHtml(val);
        };
    }]);

}(angular.module('oneKeyApp')));

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    // Creates a C# like string format that parameterizes the string with numeric curly brace format. ie. {0}
    // This filter was from https://www.npmjs.com/package/angularjs-filters but pulled out independently
    oneKeyApp.filter("stringFormat", [function () {
        return function (str) {
            if (!str || arguments.length <= 1) return str;
            var args = arguments;
            for (var i = 1; i < arguments.length; i++) {
                var reg = new RegExp("\\{" + (i - 1) + "\\}", "gm");
                str = str.replace(reg, arguments[i]);
            }
            return str;
        }
    }
    ]);
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('crimpers', [
        '$resource', 'urls', function($resource, metUrls) {

            var searchResource = $resource(metUrls('baseApiUrl').concat('/crimpers'));
            var incidentsResource = $resource(metUrls('baseApiUrl').concat('/crimpers/events'));
            var addResource = $resource(metUrls('crimpersAdd'));
            var milwaukeeDefaultUrl = metUrls('milwaukeeDefault');
            var companyInfoResource = $resource(metUrls('baseApiUrl').concat('/crimpers/update-profile'),
                null,
                {
                    'update': { method: 'PUT' }
                });

            return {
                
                getCrimpers: function (filters, callback) {
                    return searchResource.get(filters, callback);
                },
                getDefaultImage: function() {
                    return milwaukeeDefaultUrl;
                },
                getCrimperIncidents: function (itemInstanceIds,
                    beginDate,
                    endDate,
                    crimperType,
                    callback) {
                    return incidentsResource.get({
                        itemInstanceIds: itemInstanceIds,
                        beginDate: beginDate,
                        endDate: endDate,
                        crimperType: crimperType
                    }, callback);
                },
                createReport: function(report, callback, error) {
                    return addResource.save(report, callback, error);
                },
                saveCompanyInfo: function (companyInformation) {
                    return companyInfoResource.update(companyInformation);
                }
            };
        }
    ]);
}());
(function () {
    'use strict';

    angular.module('oneKeyApp')
        .directive('alertFrequency', alertFrequency);

    alertFrequency.$inject = ['$timeout', 'dates', 'language', 'localize', 'notify', 'inventory', 'notifications', '$rootScope'];

    function alertFrequency($timeout, metDates, metLanguage, localize, metNotify, metInventory, metAlerts, $rootScope) {

        var directive = {
            link: link,
            replace: true,
            scope: {
                itemDetails: '=',
                item: '=',
                serviceDate: '=',
                frequency: '=',
                serviceDateAlert: '=?'
            },
            restrict: 'EA',
            templateUrl: '/OneKeyScripts/app/directives/inventory/grid/alertFrequency.html'
        };
        return directive;

        function link(scope) {
            init();
            var iconLink = $('#calendartarget');
            scope.workingModel = scope.itemDetails;
            scope.isOpen = true;
            scope.selectedFrequency = null;
            scope.messages = {
                save: localize('commands', 'save'),
                cancel: localize('commands', 'cancel'),
                edit: localize('commands', 'edit'),
                repeats: localize('commands', 'repeats'),
                recurringAlerts: localize('commands', 'recurringAlerts'),
                selectDate: localize('commands', 'selectDate')
            };

            scope.alertFrequencyOptions = [];

            localize('messages', 'never').promise.then(function (val) {
                scope.alertFrequencyOptions[0] = val;
            });
            
            localize('messages', 'monthly').promise.then(function (val) {
                scope.alertFrequencyOptions[1] = val;
            });
            
            localize('messages', 'quarterly').promise.then(function (val) {
                scope.alertFrequencyOptions[2] = val;
            });
            
            scope.monthly = localize('messages', 'semiAnnually').promise.then(function (val) {
                scope.alertFrequencyOptions[3] = val;
            });
            
            scope.monthly = localize('messages', 'annually').promise.then(function (val) {
               scope.alertFrequencyOptions[4] = val;
            });

            var originalDate = scope.itemDetails.serviceDate;
            var originalFrequency = scope.itemDetails.serviceAlertFrequency;
            var defaultOrToday = isNullOrUndefined(scope.serviceDate) ? moment().today : scope.serviceDate;
            var currentDate = moment().startOf('day');
            var minDate = currentDate.toISOString();

            // Doing this to tackle the issue where the UserItem already has a Service Reminder date in the past
            if (defaultOrToday <= minDate) {
                $('#serviceDatePicker').datetimepicker({
                    inline: true,
                    format: metDates.date(false),
                    showClear: true,
                    minDate: minDate
                }).show();
            }

            scope.picker = $('#serviceDatePicker').datetimepicker({
                inline: true,
                sideBySide: false,
                debug: false,
                keepOpen: false,
                locale: metLanguage.getLocale(),
                defaultDate: defaultOrToday,
                format: metDates.date(false),
                showClear: true,
                minDate: minDate
            });
            
            scope.showDatePicker = true;
            scope.showFrequencyPicker = false;
            scope.toggle = toggle;
            scope.submit = submit;
            
            if (isNullOrUndefined(scope.selected)) {
                scope.selected = 0;
            };

            function toggle(shouldClose) {

                if (scope.selectedFrequency === null) {
                    scope.selectedFrequency = scope.alertFrequencyOptions[scope.itemDetails.serviceAlertFrequency];
                }

                if (localStorage.getItem('alert')) {
                    scope.selectedFrequency = localStorage.getItem('alert');
                    localStorage.removeItem('alert');
                }
                if (isNullOrUndefined(shouldClose)) {
                    shouldClose = false;
                }
                if (shouldClose) {
                    scope.isOpen = true;
                    hideContainer();
                } else {
                    scope.showDatePicker = !scope.showDatePicker;
                    scope.showFrequencyPicker = !scope.showFrequencyPicker;
                }
            }

            function submit() {
                scope.isOpen = true;

                if (scope.selectedFrequency !== null) {
                    localStorage.setItem('alert', scope.selectedFrequency);
                }

                var serviceDate = scope.picker.data().date;
                scope.itemDetails.serviceAlertFrequency = scope.selectedFrequency !== null
                        ? scope.alertFrequencyOptions.indexOf(scope.selectedFrequency)
                        : scope.itemDetails.serviceAlertFrequency;

                scope.itemDetails.serviceDate = serviceDate.length > 0 ? moment(serviceDate, metDates.date(false)).format(metDates.api) : null;

                scope.itemDetails.manufacturerId = scope.itemDetails.manufacturer.manufacturerId;
                scope.itemDetails.categoryId = scope.itemDetails.category.categoryId;
                scope.itemDetails.locationId = scope.itemDetails.location.locationId;
                scope.itemDetails.placeId = scope.itemDetails.place.placeId;
                scope.itemDetails.divisionId = scope.itemDetails.division.divisionId;
                scope.itemDetails.personId = scope.itemDetails.person.personId;


                if (scope.itemDetails.hasServiceDateAlert) {
                    metAlerts.dismiss(scope.serviceDateAlert.id,
                        function (response) {
                            $rootScope.$broadcast('alert-deleted', response);
                        }
                    );
                }
                metInventory.update(scope.itemDetails,
                    function (data) {
                        scope.itemDetails = data;
                        var unacknowledgedAlerts = [];
                        if (scope.itemDetails.notifications.length > 0) {
                            unacknowledgedAlerts = $.grep(scope.itemDetails.notifications, function (notification) { return notification.acknowledgedOn === null; });
                        }
                        if (scope.item.alertCount !== unacknowledgedAlerts.length) {
                            $rootScope.$broadcast('update-notifications-count', {});
                            scope.item.alertCount = unacknowledgedAlerts.length;
                        }
                    }, function (error) {
                        scope.itemDetails.serviceDate = originalDate;
                        scope.itemDetails.serviceAlertFrequency = originalFrequency;
                        metNotify.error(error.data.message);
                        $timeout(function () {
                            if (scope.itemDetails.serviceAlertFrequency === 0 || isNullOrUndefined(scope.itemDetails.serviceAlertFrequency)) {
                                $('#serviceDateAndFrequency').css('display', 'none');
                            }

                        }, 200);
                       
                        console.log(error.data.message);
                    }
                );
                hideContainer();
            }

            iconLink.click(function () {
                scope.isOpen = !scope.isOpen;
                return scope.isOpen ? hideContainer() : showContainer();
            });

            function showContainer() {
                $('#serviceAlertContainer').css('display', 'block');
            }

            function hideContainer() {
                $('#serviceAlertContainer').css('display', 'none');
            }

            function isNullOrUndefined(obj) {
                return obj === null || obj === undefined;
            };

            function init() {
                hideContainer();
            }
        }
    };

})();
(function (module) {
    'use strict';

    var metAddEdit = function ($compile, urls, localize, dates, serviceRecords, metNotify, $modal, modalOptionsService, $filter, metServiceRecordUploads) {

        return {
            restrict: 'E',
            replace: true,
            templateUrl: '/OneKeyScripts/app/directives/inventory/grid/metAddEdit.directive.html',
            scope: {
                item: '=',
                selectedRecord: '=?',
                serviceRecordItems: '=',
                emptyServiceRecords: '=?',
                hasUploads: '=',
                reloadRecords: '&'
            },
            link: function (scope, element, attrs) {
                scope.messages = {
                    date: localize('fieldNames', 'date'),
                    cost: localize('fieldNames', 'cost'),
                    save: localize('fieldNames', 'save'),
                    serviceRecord: localize('fieldNames', 'serviceRecord'),
                    servicedBy: localize('fieldNames', 'servicedBy'),
                    notes: localize('fieldNames', 'notes'),
                    addRecord: localize('commands', 'addRecord'),
                    edit: localize('commands', 'edit'),
                    add: localize('commands', 'add'),
                    view: localize('commands', 'view'),
                    serviceDate: localize('fieldNames', 'serviceDateLabel'),
                    serviceType: localize('fieldNames', 'serviceType'),
                    cancel: localize('commands', 'cancel'),
                    required: localize('validation', 'requiredError'),
                    addRecordConversational: localize('commands', 'addRecordConversational'),
                    editView: localize('commands', 'edit_View'),
                    uploadedItems: localize('fieldNames', 'uploadedItems'),
                    delete: localize('commands', 'delete'),
                    deleteConfirm: localize('messages', 'deleteUploadConfirm'),
                    attachFiles: localize('fieldNames', 'attachFiles'),
                    attachText: localize('messages', 'attachText'),
                    uploads: localize('fieldNames', 'uploads'),
                    serviceDateRequired: localize('messages', 'serviceDateRequired')
                };
                scope.epochStart = moment('1970-01-01T00:00:00.000').format();
                scope.serviceRecord = {};
                scope.datePickerOptions = dates.getDatePickerOptions('bottom');
                scope.statuses = scope.item.statuses;
                scope.serviceTypes = [];
                scope.selectedType = {};
                scope.getContainer = getContainer;
                scope.hideAddDialog = hideAddDialog;
                scope.isEdit = false;
                scope.dateFormat = dates.date(true);
                scope.serviceUploadRecordChanged = false;

                if (scope.selectedRecord !== undefined) {
                    scope.serviceRecord = scope.selectedRecord;
                    scope.serviceRecord.date = $filter('date')(scope.serviceRecord.date, dates.date(true));
                    scope.isEdit = true;
                }
                else {
                    var today = moment().format();
                    scope.serviceRecord.date = $filter('date')(today, dates.date(true));
                    scope.serviceRecord.cost = 0;
                }

                scope.save = function () {
                    var serviceDate = scope.isEdit ? document.querySelector('#serviceDateInputEdit').value : document.querySelector('#serviceDateInputAdd').value;

                    if (serviceDate.length <= 0) {
                        metNotify.error(scope.messages.serviceDateRequired.value);
                        return;
                    }
                    scope.serviceRecord.userItemId = scope.item.id;
                    scope.serviceRecord.typeId = scope.selectedType.id;
                    scope.serviceRecord.notes = document.querySelector('#serviceRecordNoteText').value;

                    if (!scope.isEdit) {
                        scope.serviceRecord.date = serviceDate.length > 0 ? moment(serviceDate, dates.date(false)).format(dates.api) : moment().format(dates.getDatePickerOptions().format);
                        if (scope.serviceRecord.date < scope.epochStart) {
                            scope.serviceRecord.date = scope.epochStart;
                        }
                        serviceRecords.create(scope.serviceRecord,
                            function (data) {
                                scope.refreshServiceRecords(false);
                            },
                            function (data) {
                                openModal();
                            });
                    } else {
                        // Needed in the case someone uploads something before saving their record.
                        if (scope.selectedRecord === undefined) {
                            scope.selectedRecord = scope.serviceRecord;
                        }

                        scope.selectedRecord.date = serviceDate.length > 0 ? moment(serviceDate, dates.date(false)).format(dates.api) : moment().format(dates.getDatePickerOptions().format);
                        if (scope.selectedRecord.date < scope.epochStart) {
                            scope.selectedRecord.date = scope.epochStart;
                        }
                        serviceRecords.update(scope.selectedRecord,
                            function () {
                                scope.refreshServiceRecords(false);
                            },
                            function () {
                                openModal();
                            });
                    }

                };

                scope.cancel = function () {
                    scope.refreshServiceRecords(false);
                }

                serviceRecords.getTypes(function (data) {
                    scope.serviceTypes = data;
                    scope.selectedType = getSelectedDataType(data);
                }, function () {
                    openModal();
                });

                scope.delete = function (id) {
                    metServiceRecordUploads.remove(id, function () {
                        scope.refreshServiceRecords(true);
                    });
                };

                scope.update = function (userItemResource) {
                    scope.serviceUploadRecordChanged = true;
                    userItemResource.title = userItemResource.uploadTitle;
                    metServiceRecordUploads.update(userItemResource, function () {
                        scope.refreshServiceRecords();
                    });
                };

                function openModal() {
                    $modal.open(modalOptionsService.generalErrorModalOptions);
                }

                function getSelectedDataType(data) {
                    if (scope.selectedRecord) {
                        var selectedDataType = data.filter(function (type) {
                            return type.id === scope.selectedRecord.typeId;
                        });
                        return selectedDataType[0];
                    }
                    return data[3];
                }
                scope.isNumberKey = function ($event) {
                    if (isNaN(String.fromCharCode($event.keyCode)) && $event.which !== 8 && $event.which !== 46) {
                        $event.preventDefault();
                    }
                }

                scope.refreshServiceRecords = function (isEdit) {
                    serviceRecords.getAllByUserItemId(scope.item.id,
                        function (response) {
                            scope.serviceRecordItems = response;
                            if (scope.isEdit) {
                                scope.serviceRecord.serviceRecordUploads = $.grep(scope.serviceRecordItems,
                                        function(record) { return record.id === scope.serviceRecord.id })[0].serviceRecordUploads;
                                scope.hasUploads = scope.serviceRecord.serviceRecordUploads.length > 0;
                                scope.serviceRecord.date = $filter('date')(scope.serviceRecord.date, dates.date(true));
                                scope.serviceRecord.cost =
                                    scope.serviceRecord.cost === null ? 0 : scope.serviceRecord.cost;

                                for (var z = 0; z < scope.serviceRecord.serviceRecordUploads.length; z++) {
                                    scope.serviceRecord.serviceRecordUploads[z].createdOnLocal = dates.convertUtcToLocal(scope.serviceRecord.serviceRecordUploads[z].createdOn, scope.dateFormat);
                                }
                            }

                            for (var i = 0; i < scope.serviceRecordItems.length; i++) {
                                scope.serviceRecordItems[i].localDate = $filter('date')(scope.serviceRecordItems[i].date, dates.date(true));
                                scope.serviceRecordItems[i].cost =
                                    scope.serviceRecordItems[i].cost === null ? 0 : scope.serviceRecordItems[i].cost;
                            }

                            if (!isEdit && isEdit !== undefined) {
                                var container = getContainer();
                                hideAddDialog(container);
                            }
                            scope.emptyServiceRecords = scope.serviceRecordItems.length <= 0;

                            if (scope.serviceUploadRecordChanged) {
                                scope.selectedRecord = scope.serviceRecord;
                            }
                        },
                        function () {
                        });
                };

                function getContainer() {
                    return element.parents('#itemDetails');
                }

                function hideAddDialog(container) {
                    container.children().css('display', 'block');
                    $('#oneKeyAddEditContainer').remove();
                }

                function showAddDialog(container) {
                    container.children().css('display', 'none');
                    $('#oneKeyAddEditContainer').css('display', 'block');
                }
            }
        }
    };

    metAddEdit.$inject = ['$compile', 'urls', 'localize', 'dates', 'serviceRecords', 'notify', '$modal', 'modalOptionsService', '$filter', 'serviceRecordUploads'];
    module.directive('metAddEdit', metAddEdit);

}(angular.module('oneKeyApp')));
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metGrid', [
        '$filter', 'urls', 'localize', 'userItems', 'metLocalStorage', 'inventoryFilters', 'inventoryGridConfig', 'notify', '$stateParams', 'notifications',
        function ($filter, metUrls, metLocalize, metUserItems, metLocalStorage, metInventoryFilters, metInventoryGrid, metNotify, $stateParams, metNotifications) {
           return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryGridHtml'),
                scope: {
                    loading: '=',
                    refreshGrid: '=',
                    userItemId: '=',
                    tickUrl: '@'
               },
               link: function (scope, element, attrs) {
                    scope.refreshGrid = refreshGrid;

                    if ($stateParams.success !== null && $stateParams.success !== undefined) {
                        scope.refreshGrid(false);
                    }
                    scope.noInventory = scope.loadedGroups && scope.loadedGroups[0].items.length === 0;
                    scope.loadedGroups = metInventoryGrid.loadedGroups;
                   scope.messages = {
                       howToActiviateToolSecurity: metLocalize('messages', 'howToActiviateToolSecurity'),
                       addItemButton: metLocalize('commands', 'addItemButton'),
                       noInventory: metLocalize('messages', 'noInventory'),
                       emptyInventoryText: metLocalize('messages', 'emptyInventoryText'),
                       noResults: metLocalize('messages', 'noResults'),
                       noResultsForFilters: metLocalize('messages', 'noResultsForFilters'),
                       clearFilters: metLocalize('commands', 'clearFilters')
                   };

                    scope.collapseAllItems = function () {
                        _.forEach(scope.loadedGroups, function (group, index) {
                            _.forEach(group.items, function (item, index) {
                                item.isExpanded = false;
                            });
                        });
                    }

                    scope.selectGroupItems = function (groupId) {
                        metInventoryGrid.allItemsSelected = false;
                        var selectedGroup = $filter('filter')(scope.loadedGroups, { id: groupId })[0];
                        if (selectedGroup) {
                            _.forEach(selectedGroup.items, function (item, index) {
                                item.selected = selectedGroup.selected;
                            });
                        }
                        metInventoryGrid.updateSelectedFields();
                    }

                    scope.hasFilters = metInventoryFilters.hasFilters();
                    scope.hasSearchTerm = metInventoryFilters.searchTerm.length > 0;

                    scope.clearFilters = function () {
                        metInventoryFilters.removeAllFilters();
                        metInventoryFilters.searchTerm = '';
                        scope.refreshGrid();
                    }

                    function refreshGrid (isPaging) {
                        scope.loading = true;
                        if (!isPaging) {
                            metInventoryGrid.pageIndex = 0;
                            metInventoryFilters.updateFilterResults();
                            metInventoryGrid.allItemsSelected = false;
                            metInventoryGrid.selectAll();
                        }
                        scope.hasFilters = metInventoryFilters.hasFilters();
                        scope.hasSearchTerm = metInventoryFilters.searchTerm.length > 0;
                        var oneKey = localStorage.getItem("oneKeyOnly");
                        var tick = localStorage.getItem("tickOnly");

                        var filters = metInventoryFilters.searchRequest;
                        if (oneKey) { filters.oneKey = oneKey; }
                        if (tick) { filters.tick = tick; }
                        filters.sortField = metInventoryGrid.gridSort.field;
                        filters.sortDescending = metInventoryGrid.gridSort.isDescending;
                        filters.take = metInventoryGrid.resultsPerPage;
                        filters.groupBy = metInventoryGrid.groupBy;
                        filters.skip = metInventoryGrid.getSkipTotal();

                        if (scope.userItemId > 0) {
                            filters.itemId = scope.userItemId;
                        }

                        metUserItems.search(filters, function (response) {
                            metInventoryFilters.updateAvailableFilters(response.availableFilters, isPaging);
                            metInventoryGrid.gridUpdated(response);
                            scope.loadedGroups = metInventoryGrid.loadedGroups;
                            _.forEach(scope.loadedGroups,
                                function(group) {
                                    _.forEach(group.items,
                                        function(item) {
                                            item.alertCount = $filter('filter')(scope.notifications,
                                                { userItemId: item.id, acknowledgedOn: null }).length;
                                        });
                                });
                            scope.loading = false;
                            // Sending custom dimension for inventory size to google analytics.
                            var tracker = ga.getAll()[0];
                            console.log('tracker before set');
                            var gaInventoryBucket = "0";
                            if (metInventoryGrid.totalResults > 0 && metInventoryGrid.totalResults <= 9) {
                                gaInventoryBucket = "1-9";
                            } else if (metInventoryGrid.totalResults >= 10 && metInventoryGrid.totalResults <= 99) {
                                gaInventoryBucket = "10-99";
                            } else if (metInventoryGrid.totalResults >= 100 && metInventoryGrid.totalResults <= 999) {
                                gaInventoryBucket = "100-999";
                            } else if (metInventoryGrid.totalResults >= 1000) {
                                gaInventoryBucket = "1000+";
                            } else {
                                gaInventoryBucket = "0";
                            }
                            tracker.set('dimension1', gaInventoryBucket);
                            console.log(tracker.get('dimension1'));
                            ga('send', 'event', 'inventorySize', 'loadedInventory');
                            
                            scope.noInventory = metInventoryGrid.totalResults === 0;
                            if (scope.userItemId > 0) {
                                _.forEach(scope.loadedGroups, function (group) {
                                    _.forEach(group.items, function (item) {
                                        item.isExpanded = true;
                                    });
                                });
                            }
                        });

                        var quickFilters = document.getElementsByClassName('met-filter-chip');

                        if (quickFilters.length > 0) {
                            _.forEach(quickFilters, function (quickFilter) {
                                var disp = quickFilter.style.display;
                                quickFilter.style.display = 'none';
                                setTimeout(function () {
                                    quickFilter.removeAttribute('style');
                                }, 15);
                            })
                        }
                    }

                    scope.notifications = [];

                    function init() {
                        metNotifications.getAll(function(response) {
                            scope.notifications = response.items;
                        }, function(error) {
                            scope.notifications = [];
                        });

                        scope.refreshGrid();

                        if (localStorage.getItem('displayHowToActiviateToolSecurity')) {
                            localStorage.removeItem('displayHowToActiviateToolSecurity');

                            setTimeout(function () {
                                // firing off a bit later to give the page a bit more time to load.
                                metNotify.success(scope.messages.howToActiviateToolSecurity.value);
                            }, 500);
                        }
                    }
                    init();
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metGridConfig', [
        '$window', 'urls', 'localize', 'inventoryGridConfig', 'metLocalStorage', 'host',
        function ($window, metUrls, metLocalize, metInventoryGrid, metLocalStorage, host) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('inventoryGridConfigHtml'),
                scope: {
                    updateResults: '&'
                },
                link: function (scope, element, attrs) {
                    scope.messages = {
                        resultsPerPage: metLocalize('messages', 'resultsPerPage'),
                        addRemoveGridColumns: metLocalize('messages', 'addRemoveGridColumns'),
                        gridGrouping: metLocalize('messages', 'gridGrouping'),
                        selectEightOptions: metLocalize('commands', 'selectEightOptions'),
                        configureColumns: metLocalize('commands', 'configureColumns')
                    }
                    scope.host = host;
                    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.hasOwnProperty(key)) {
                            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();
                    }
;
                    if (localStorage.getItem('column')) {
                        scope.defaultChecked = localStorage.getItem('column');
                    }
                    else {
                        scope.defaultChecked = 7;
                    }
                    scope.limitColumns = 8;

                    scope.columns = metInventoryGrid.headerValues;
                    scope.changeColumns = function (column, isVisible, $event) {
                        if (localStorage.getItem('column')) {
                            scope.defaultChecked = localStorage.getItem('column');
                        }
                        column.isVisible = isVisible;
                        if (column.isVisible) {
                            scope.defaultChecked++;
                        }
                        else {
                            scope.defaultChecked--;
                        }
                        localStorage.setItem('column', scope.defaultChecked);
                        metLocalStorage.setColumnInfo(column.columnName, { visible: isVisible });
                        $event.stopPropagation();
                    }

                    scope.propagation = function ($event) {
                        $event.stopPropagation();
                    }

                    scope.groupByOptions = [
                        { id: 0, label: metLocalize('messages', 'noGridGrouping'), },
                        { id: 1, label: metLocalize('fieldNames', 'categoryId') },
                        { id: 2, label: metLocalize('fieldNames', 'placeId') },
                        { id: 3, label: metLocalize('fieldNames', 'manufacturerId') },
                        { id: 4, label: metLocalize('fieldNames', 'itemStatus') },
                        { id: 5, label: metLocalize('fieldNames', 'personId') },
                        { id: 6, label: metLocalize('fieldNames', 'divisionId') },
                    ];

                    scope.selectedGroupBy = scope.groupByOptions[0];
                    scope.changeGroupBy = function (groupBy) {
                        scope.selectedGroupBy = groupBy;
                        metInventoryGrid.groupBy = groupBy.id;
                        scope.updateResults();
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metGridHeaders', [
        'urls', 'localize', 'metLocalStorage', 'inventoryGridConfig',
        function (metUrls, metLocalize, metLocalStorage, metInventoryGrid) {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: metUrls('inventoryGridHeadersHtml'),
                scope: {
                    refreshGrid: '&'
                },
                link: function (scope, element, attrs) {
                    scope.gridConfig = metInventoryGrid;
                    scope.headerValues = metInventoryGrid.headerValues;

                    scope.setSortColumn = function (header) {
                        _.forEach(scope.headerValues, function (value, index) {
                            value.isSorted = false;
                            value.sortDescending = false;
                        });

                        if (metInventoryGrid.gridSort.field !== header.columnName) {
                            metInventoryGrid.gridSort.field = header.columnName;
                            metInventoryGrid.gridSort.isDescending = false;
                        } else {
                            metInventoryGrid.gridSort.isDescending = !metInventoryGrid.gridSort.isDescending;
                        }

                        metLocalStorage.setGridSort(metInventoryGrid.gridSort);
                        scope.refreshGrid();
                        header.isSorted = true;
                        header.sortDescending = metInventoryGrid.gridSort.isDescending;

                        setTimeout(function () {
                            var ua = window.navigator.userAgent;

                            var msie = ua.indexOf("MSIE"); // older versions of IE
                            var trident = ua.indexOf('Trident/'); // IE 11
                            var edge = ua.indexOf('Edge/'); // Microsoft Edge

                            if (trident > -1 || edge > -1 || msie > -1) // If Internet Explorer or edge
                            {
                                var tableOffset = $("#inventoryTable").offset().top;
                                var $header = $("#inventoryTable > thead").clone();
                                var $fixedHeader = $("#header-fixed").append($header);
                                $("#header-fixed th").each(function (index) {
                                    var index2 = index;
                                    $(this).width(function (index2) {
                                        return $("#inventoryTable th").eq(index).width();
                                    });
                                });
                                $("#header-fixed").width($("#inventoryTable").width());
                                $(window).bind("scroll", function () {
                                    var offset = $(this).scrollTop();

                                    if (offset >= tableOffset && $fixedHeader.is(":hidden")) {
                                        $fixedHeader.show();
                                    }
                                    else if (offset < tableOffset) {
                                        $fixedHeader.hide();
                                    }
                                });
                            }
                        }, 3000);
                    }

                    scope.selectAll = function () {
                        metInventoryGrid.selectAll();
                    }
                }
            };
        }
    ]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metGridItem', [
        '$window', 'urls', 'localize', 'metLocalStorage', 'dates', 'inventoryGridConfig', 'inventory',
        function ($window, metUrls, metLocalize, metLocalStorage, metDates, metGridConfig, metInventory) {
            return {
                restrict: 'A',
                replace: true,
                templateUrl: metUrls('inventoryGridItemHtml'),
                scope: {
                    item: '=metItem',
                    group: '=metGroup',
                    collapseAll: '&metCollapseAll'
                },
                link: function (scope, element, attrs) {
                    scope.dateTimeFormat = metDates.shortDateTime(true);
                    scope.dateFormat = metDates.date(true);
                    scope.messages = {
                        oneKeyItem: metLocalize('messages', 'oneKeyItem')
                    }

                    scope.itemSelected = function ($event) {
                        $event.stopPropagation();
                        metGridConfig.allItemsSelected = false;
                        scope.group.selected = false;
                        metGridConfig.updateSelectedFields();
                    }


                    var isFrench = function () {
                    	var current = $window.location.pathname;
                    	return current.indexOf('/fr') > -1;
                    };
                    
                    scope.showColumn = function (columnName) {
                        return metGridConfig.columnIsVisible(columnName);
                    }

                    scope.expandGridItem = function () {
                        var isExpanded = !scope.item.isExpanded;
                        scope.collapseAll();
                        scope.item.isExpanded = isExpanded;
                    }

					var detailsUrl = metUrls('inventoryDetails').concat('/' + scope.item.id);
				    scope.goToDetails = function () {
						$window.location.href = detailsUrl;
                    }

                    scope.lastSeenDate = metDates.convertUtcToLocal(scope.item.lastSeen);
                    scope.hasMessages = false;
                    scope.coinCellMessage;
                    scope.serviceMessage;
                    scope.toolLockedMessage;
                    var init = function() {
                        scope.hasMessages = scope.item.coinCellAlert > 0 || scope.item.serviceAlert > 0 || scope.item.isLocked == true || scope.item.statusId > 0;

                        if (scope.item.coinCellAlert == 2) {
                            scope.toolLockedMessage = metLocalize('messages', 'toolLocked');
                        }
                        
                        if (scope.item.location == null) {
                        	scope.item.location = metLocalize('titles', 'unassigned').value;
                        }
                        if (scope.item.person == null) {
                        	scope.item.person = metLocalize('titles', 'unassigned').value;
                        }
                        if (scope.item.trade == null) {
                        	scope.item.trade = metLocalize('titles', 'unassigned').value;
                        }

                        switch (scope.item.coinCellAlert) {
                            case 1:
                                scope.coinCellMessage = metLocalize('messages', 'coinCellWarning').value;
                                break;
                            case 2:
                                scope.coinCellMessage = metLocalize('messages', 'coinCellAlert').value;
                                break;
                        }

                        switch (scope.item.serviceAlert) {
                            case 1:
                                scope.serviceMessage = metLocalize('messages', 'serviceWarning').value;
                                break;
                            case 2:
                                scope.serviceMessage = metLocalize('messages', 'serviceAlert').value;
                                break;
                        }
                    }

                    init();
                }
            };
        }
    ]);
}());
(function () {
    "use strict";
    var oneKeyApp = angular.module('oneKeyApp');
    oneKeyApp.directive('metGridItemDetails', [
        '$state', '$window', 'urls', 'localize', 'items', 'dates', 'inventory', 'userItems', 'manufacturers', 'locations', 'people', 'trades', 'itemFieldFactory', 'addFormModel', '$filter', '$modal', 'modalOptionsService', 'notifications', 'categories',
        function ($state, $window, metUrls, metLocalize, metItems, metDates, metInventory, metUserItems, metManufacturers, metLocations, metPeople, metTrades, metItemFields, addFormModel, filter, $modal, modalOptionsService, metAlerts, metCategories) {

            return {
                restrict: 'A',
                replace: true,
                templateUrl: metUrls('inventoryGridItemDetailsHtml'),
                scope: {
                    item: '=metItem',
                    locations: '&',
                    people: '&',
                    trades: '&',
                    statuses: '&',
                    tickUrl: '@'
                },
                link: function (scope, element, attrs) {
                    scope.locations = [];
                    scope.trades = [];
                    scope.people = [];
                    scope.selectedPlace = {};
                    scope.selectedPerson = {};
                    scope.selectedDivision = {};
                    scope.states = $state.get();
                    scope.isValidModelNumber = false;
                    scope.datePickerOptions = metDates.getDatePickerOptions('bottom');
                    scope.detailEditView = false;
                    scope.purchaseInfoView = true;
                    scope.tabSelectedIndex = {index: 0};
                    scope.notesView = false;
                    scope.uploadsView = false;
                    scope.itemFields = metItemFields;
                    scope.serviceDatePicker = '';
                    scope.timeFromEntry = '';
                    scope.loading = true;
                    scope.selectedStatus = {};
                    scope.lastSeenText = "";
                    scope.showOverviewPanel = false;
                    scope.address = "";
                    scope.imageUploadUrl = metUrls('imagesUserItemsApi');
                    scope.filter = filter;
                    scope.serviceDateByRegion = null;
                    scope.notificationList = [];
                    scope.itemDetails = [];
                    scope.itemDetails.hasServiceDateAlert = false;
                    scope.isLatestScanned = false;
                    scope.setSelectedStatus = setSelectedStatus;
                    scope.messages = {
                        lastLocation: metLocalize('commands', 'lastLocation'),
                        viewDetails: metLocalize('commands', 'viewDetails'),
                        noNotifications: metLocalize('commands', 'noNotifications'),
                        toolNumber: metLocalize('fieldNames', 'inventoryToolNumber'),
                        status: metLocalize('fieldNames', 'itemStatus'),
                        itemDetails: metLocalize('fieldNames', 'itemDetails'),
                        person: metLocalize('fieldNames', 'personId'),
                        location: metLocalize('fieldNames', 'location'),
                        place: metLocalize('fieldNames', 'placeId'),
                        division: metLocalize('fieldNames', 'divisionId'),
                        serviceDate: metLocalize('fieldNames', 'serviceDate'),
                        itemValue: metLocalize('fieldNames', 'itemValue'),
                        coinCellLeft: metLocalize('fieldNames', 'coinCellLeft'),
                        itemWasAdded: metLocalize('messages', 'itemWasAdded'),
                        lastSeen: metLocalize('fieldNames', 'lastSeen'),
                        lastScanned: metLocalize('messages', 'lastScanned'),
                        year: metLocalize('messages', 'year'),
                        years: metLocalize('messages', 'years'),
                        month: metLocalize('messages', 'month'),
                        months: metLocalize('messages', 'months'),
                        day: metLocalize('messages', 'day'),
                        days: metLocalize('messages', 'days'),
                        toolHistory: metLocalize('fieldNames', 'toolHistory'),
                        noAddressFound: metLocalize('messages', 'noAddressFound'),
                        itemOverview: metLocalize('fieldNames', 'itemOverview'),
                        serviceRecord: metLocalize('fieldNames', 'serviceRecord'),
                        purchaseInformation: metLocalize('fieldNames', 'purchaseInformation'),
                        purchaseInfo: metLocalize('fieldNames', 'purchaseInfo'),
                        addPurchaseInfo: metLocalize('messages', 'addPurchaseInfo'),
                        notes: metLocalize('fieldNames', 'notes'),
                        alerts: metLocalize('titles', 'alerts'),
                        edit: metLocalize('fieldNames', 'edit'),
                        brand: metLocalize('fieldNames', 'manufacturer'),
                        modelNumber: metLocalize('fieldNames', 'modelNumber'),
                        serialNumber: metLocalize('fieldNames', 'serialNumber'),
                        description: metLocalize('fieldNames', 'itemDescription'),
                        save: metLocalize('commands', 'save'),
                        cancel: metLocalize('commands', 'cancel'),
                        toolPhoto: metLocalize('fieldNames', 'toolPhoto'),
                        category: metLocalize('fieldNames', 'categoryId'),
                        objectiveData: metLocalize('fieldNames', 'objectiveData'),
                        track: metLocalize('messages', 'track'),
                        trackMessage: metLocalize('messages', 'trackMessage'),
                        learnMore: metLocalize('commands', 'learnMore'),
                        seenByOneKey: metLocalize('messages', 'seenByOneKey'),
                        editItem: metLocalize('messages', 'editItem'),
                        oneKey: metLocalize('titles', 'oneKey'),
                        lastSync: metLocalize('fieldNames', 'lastSyncedOn'),
                        resources: metLocalize('fieldNames', 'resources'),
                        duplicate: metLocalize('messages', 'duplicate'),
                        uploads: metLocalize('fieldNames', 'uploads'),
                        itemSn: metLocalize('fieldNames', 'itemSn'),
                        tickSn: metLocalize('fieldNames', 'tickSn'),
                        manufacturer: metLocalize('fieldNames', 'manufacturerId'),
                        add: metLocalize('commands', 'add'),
                        searchOrAdd: metLocalize('commands', 'searchOrAdd'),
                        addPersonOption: metLocalize('commands', 'addPersonOption'),
                        addLocationOption: metLocalize('commands', 'addLocationOption'),
                        addDivisionOption: metLocalize('commands', 'addDivisionOption'),
                        addCategoryOption: metLocalize('commands', 'addCategoryOption'),
                        addManufacturerOption: metLocalize('commands', 'addManufacturerOption'),
                        noResultsFound: metLocalize('messages', 'noResultsFound'),
                        pendingLock: metLocalize('messages', 'pendingLock'),
                        itemLocked: metLocalize('messages', 'itemLocked'),
                        addPlaceOption: metLocalize('commands', 'addPlaceOption'),
                        outsideGeofence: metLocalize('messages', 'outsideGeofence'),
                        barcode: metLocalize('messages', 'barcodeDisplay'),
                        requiredError: metLocalize('validation', 'requiredError')
                    };

                    scope.seenOutsideGeofence = false;
                    scope.firstLetterStatusGroupFn = function (item) {
                        return item.statusName.charAt(0).toUpperCase();
                    };
                    scope.firstLetterDivisionGroupFn = function (item) {
                        return item.divisionName.charAt(0).toUpperCase();
                    };
                    scope.firstLetterPersonGroupFn = function (item) {
                        return item.personName.charAt(0).toUpperCase();
                    };
                    scope.firstLetterPlaceGroupFn = function (item) {
                        return item.placeName.charAt(0).toUpperCase();
                    };
                    scope.firstLetterCategoryGroupFn = function (item) {
                        return item.categoryName.charAt(0).toUpperCase();
                    };
                    scope.firstLetterManufacturerGroupFn = function (item) {
                        return item.manufacturerName.charAt(0).toUpperCase();
                    };
                    scope.orderFilterFn = function (groups) {
                        return groups;
                    };

                    scope.duplicateItem = function (item) {
                        addFormModel.manufacturer = item.manufacturer;
                        addFormModel.modelNumber = item.modelNumber;
                        addFormModel.description = item.itemDescription;
                        addFormModel.category = item.category;
                        addFormModel.division = item.division;
                        addFormModel.imageAlternates = item.imageAlternates;
                        addFormModel.value = item.price;
                        $state.go('add-new', {fromState: 'existing', productId: item.productId});
                    };

                    scope.setEdit = function (isEdit, isCancel) {
                        scope.detailEditView = isEdit;
                        if (isCancel) {
                            init(isCancel);
                            return;
                        }
                        $('#serialNumberEditContainer').removeClass('md-input-invalid');
                    };

                    scope.setResourcesView = function (isPurchase, isNotes, isUploadsView) {
                        scope.purchaseInfoView = isPurchase;
                        scope.notesView = isNotes;
                        scope.uploadsView = isUploadsView;
                    };

                    scope.saveDetails = function () {
                        scope.saveForm();
                    };

                    scope.onDropDownOpenClose = function(isOpen, dropDown) {
                        var dropDownNames = ['uisStatus', 'uisPlaces', 'uisPersons', 'uisDivisions'];
                        var inputId = dropDown.$select.searchInput[0].id;
                        var elLabel = document.querySelector('#'.concat(inputId).concat('Label'));
                        var elOuterDiv = document.querySelector('#'.concat(inputId).concat('Select'));
                        var nextInputIdIndex = dropDownNames.indexOf(inputId) + 1;

                        var nextSelect = function(index) {
                            return dropDownNames[index]
                                ? document.querySelector("[input-id='" + dropDownNames[index] + "']")
                                : null;
                        }(nextInputIdIndex);
                        
                        if (isOpen) {
                            elLabel.style.visibility = 'hidden';
                            elOuterDiv.style.display = 'block';
                            if (nextSelect) {
                                nextSelect.style.visibility = 'hidden';
                            }
                        }
                        else {
                            elLabel.style.visibility = 'visible';
                            elOuterDiv.style.display = 'none';
                            if (nextSelect) {
                                nextSelect.style.visibility = 'visible';
                            }
                        }
                    }

                    scope.triggerAddNewPlace = function (place) {
                        createPlaceModal(place);
                    }

                    scope.triggerAddNewPerson = function (person) {
                        createPersonModal(person);
                    }

                    scope.triggerAddNewDivision = function (division) {
                        createDivisionModal(division);
                    }

                    scope.loadItems = function () {
                        metLocations.getAll({includeUnspecified: true, forAssignment: true}, function (data) {
                            scope.locations = data.items;
                        });

                        metTrades.getAll({includeUnspecified: true}, function (data) {
                            scope.trades = data.items;
                        });

                        metPeople.getAll({includeUnspecified: true}, function (data) {
                            scope.people = data.items;
                        });

                        metManufacturers.getAll({includeUnspecified: true}, function (data) {
                            scope.manufacturers = data.items;
                            var newManufacturer = {
                                manufacturerName: scope.messages.addManufacturerOption.value,
                                manufacturerId: -2
                            };
                            scope.manufacturers.unshift(newManufacturer);
                        });

                        metItemFields.loadStatuses();
                        getCategories();

                        scope.statuses = metItemFields.statuses;

                        metAlerts.getItemNotifications(scope.item.id,
                            function (data) {
                                scope.notificationList = data.items;
                                var result = $.grep(scope.notificationList, function (alert) { return alert.notificationType === 'ServiceDateAlert'; });
                                if (result.length > 0) {
                                    scope.itemDetails.hasServiceDateAlert = true;
                                    scope.serviceDateAlert = result[0];
                                }
                            });
                    };

                    scope.getDetailsUrl = function () {
                        $window.location.href = metUrls('inventoryDetails').concat('/' + scope.item.id);
                    };

                    scope.$watch('selectedPlace.placeName', function (newValue, oldValue) {
                        if (newValue === oldValue || oldValue === undefined || scope.loading) {
                            return;
                        }
                        scope.setSelectedPlace(newValue);
                        scope.saveForm();
                    });

                    scope.$watch('selectedPerson.personName', function (newValue, oldValue) {
                        if (newValue === oldValue || oldValue === undefined || scope.loading) {
                            return;
                        }
                        scope.setSelectedPerson(newValue);
                        scope.saveForm();
                    });

                    scope.$watch('selectedDivision.divisionName', function (newValue, oldValue) {
                        if (newValue === oldValue || oldValue === undefined || scope.loading) {
                            return;
                        }
                        scope.setSelectedDivision(newValue);
                        scope.saveForm();
                    });

                    scope.$watch('itemDetails.category', function (newValue, oldValue) {
                        if (newValue === oldValue || oldValue === undefined || scope.loading) {
                            return;
                        }
                        var category = scope.categories.filter(function (obj) {
                            return obj.categoryName === newValue;
                        });
                        if (category.length > 0) {
                            scope.itemDetails.category = category[0];
                            scope.item.category = scope.getCategoryName(category[0]);
                        }
                        if (newValue.categoryId === -2) {
                            createCategoryModal(oldValue);
                        }
                    });

                    scope.$watch('itemDetails.manufacturer', function (newValue, oldValue) {
                        if (newValue === oldValue || oldValue === undefined || scope.loading) {
                            return;
                        }
                        if (newValue.manufacturerId === -2) {
                            createManufacturerModal(oldValue);
                        }
                    });

                    scope.$watch('itemDetails.serviceDate', function (newValue, oldValue) {
                        if (newValue === oldValue || scope.loading) {
                            return;
                        }
                        else {
                            scope.item.serviceDate = newValue;
                            scope.serviceDateByRegion = newValue ? moment(newValue).format(metDates.date(false)) : null;
                        }
                    });

                    scope.$watch('itemDetails.serviceAlertFrequency', function (newValue, oldValue) {
                        if (newValue === oldValue || scope.loading) {
                            return;
                        }
                        else {
                            scope.item.serviceAlertFrequency = newValue;
                        }
                    });

                    scope.saveDatePicker = function () {
                        var serviceDate = document.querySelector('#serviceDatePicker').value;
                        scope.itemDetails.serviceDate = serviceDate.length > 0 ? moment(serviceDate, metDates.date(false)).format(metDates.api) : undefined;
                        scope.saveForm();
                    };

                    scope.rightCardControl = function (id) {
                        var elements = document.getElementById("rightTabContent").getElementsByClassName("tab-pane");
                        _.forEach(elements, function (element) {
                            element.style.display = "none";
                        });

                        var selectedElement = document.getElementById(id);
                        selectedElement.style.display = "block";
                    };

                    scope.leftCardControl = function (id) {
                        var elements = document.getElementById("leftTabContent").getElementsByClassName("tab-pane");
                        _.forEach(elements, function (element) {
                            element.style.display = "none";
                        });

                        var selectedElement = document.getElementById(id);
                        selectedElement.style.display = "block";
                    };

                    scope.updateError = false;
                    scope.errorMessage = "";

                    scope.saveForm = function () {
                        scope.itemDetails.manufacturerId = scope.itemDetails.manufacturer.manufacturerId;
                        scope.item.manufacturer = scope.itemDetails.manufacturer.manufacturerName;

                        scope.itemDetails.categoryId = scope.itemDetails.category.categoryId;
                        scope.item.category = scope.itemDetails.category.categoryName;
                        
                        scope.item.locationId = scope.selectedPlace.placeId;
                        scope.itemDetails.location = scope.selectedPlace;
                        scope.item.location = scope.itemDetails.place.placeName;
                        scope.itemDetails.placeId = scope.selectedPlace.placeId;
                        scope.item.place = scope.selectedPlace.placeName;
                        
                        scope.itemDetails.divisionId = scope.selectedDivision.divisionId;
                        scope.itemDetails.division = scope.selectedDivision;
                        scope.item.division = scope.selectedDivision.divisionName;
                        scope.item.divisionId = scope.selectedDivision.divisionId;

                        scope.itemDetails.personId = scope.selectedPerson.personId;
                        scope.itemDetails.person = scope.selectedPerson;
                        scope.item.person = scope.selectedPerson.personName;

                        scope.item.toolNumber = scope.itemDetails.toolNumber;
                        scope.item.modelNumber = scope.itemDetails.modelNumber;
                        scope.item.model = scope.itemDetails.modelNumber;
                        scope.item.description = scope.itemDetails.itemDescription;
                        scope.item.category = scope.getCategoryName(scope.itemDetails.category);

                        scope.itemDetails.status = scope.selectedStatus.statusId;
                        scope.itemDetails.statusName = scope.selectedStatus.statusName;
                        scope.item.statusId = scope.itemDetails.status;
                        scope.item.status = scope.selectedStatus.statusName;

                        scope.item.purchaseLocation = scope.itemDetails.purchaseLocation;
                        scope.item.purchaseDate = scope.itemDetails.datePurchased;
                        scope.item.price = scope.itemDetails.price;

                        metInventory.update(
                            scope.itemDetails,
                            function (data) {
                                scope.updateError = false;
                                scope.detailEditView = false;
                                scope.itemDetails.serialNumberId = data.serialNumberId;
                                scope.item.serialNumber = scope.itemDetails.serialNumber;
                                scope.item.status = data.statusName;
                                scope.item.statusId = data.status;
                                scope.itemDetails.status = data.status;
                                scope.itemDetails.statusName = data.statusName;
                                scope.setSelectedStatus(getStatusById(scope.item.statusId), true);
                            },
                            function (error) {
                                scope.detailEditView = true;
                                scope.updateError = true;
                                scope.errorMessage = error.data.message;
                                $('#serialNumberEditContainer').addClass('md-input-focused md-input-invalid');
                            }
                        );
                    };

                    scope.getCategoryName = function (category) {
                        var categoryName = category.displayName;
                        if (category.displayName === undefined) {
                            categoryName = scope.item.category;
                        }
                        if (category.parentCategoryId !== null) {
                            var parentCategory = scope.categories.filter(function (obj) {
                                return obj.categoryId === category.parentCategoryId;
                            });
                            if (parentCategory.length > 0) {
                                categoryName = parentCategory[0].categoryName + ' - ' + categoryName;
                            }
                        }

                        return categoryName;
                    };

                    scope.onTabChanges = function (currentIndex) {
                        setTabSelectedIndex(currentIndex);
                    };

                    function setSelectedStatus (statusObj, doNotSave) {
                        scope.selectedStatus = statusObj;
                        if (!doNotSave && doNotSave !== undefined) {
                            scope.saveForm();
                        }
                    };

                    scope.setSelectedPlace = function (place) {
                        var selectedPlace = [];
                        angular.copy(scope.filter('filter')(scope.locations, { placeName: place }, true)[0], selectedPlace);
                        scope.selectedPlace = selectedPlace;
                    }

                    scope.setSelectedPerson = function (name) {
                        var selectedPerson = [];
                        angular.copy(scope.filter('filter')(scope.people, { personName: name }, true)[0], selectedPerson);
                        scope.selectedPerson = selectedPerson;
                    }

                    scope.setSelectedDivision = function (name) {
                        var selectedDivision = [];
                        angular.copy(scope.filter('filter')(scope.trades, { divisionName: name }, true)[0], selectedDivision);
                        scope.selectedDivision = selectedDivision;
                    }

                    function openModal() {
                        $modal.open(modalOptionsService.generalErrorModalOptions);
                    }

                    function getStatusById(id) {
                        return scope.filter('filter')(scope.statuses, {statusId: id}, true)[0];
                    }

                    function setTabSelectedIndex(value) {
                        scope.tabSelectedIndex.index = value;
                    }

                    function getUserItem(isCancel) {
                        metUserItems.get(scope.item.id, function (response) {
                            scope.itemDetails = response;
                            scope.selectedPlace = scope.itemDetails.place;
                            scope.selectedPerson = scope.itemDetails.person;
                            scope.selectedDivision = scope.itemDetails.division;
                            scope.showOverviewPanel = scope.itemDetails.cycleInformation !== null && scope.itemDetails.lastSeen === null;
                            var lastSeen = metDates.convertUtcToLocal(scope.item.lastSeen, metDates.longDateTimeFormat);
                            var lastScanned = metDates.convertUtcToLocal(scope.itemDetails.lastScanned, metDates.longDateTimeFormat);
                            if (scope.itemDetails.lastScanned === null || scope.itemDetails.lastSeen >= scope.itemDetails.lastScanned) {
                                scope.lastSeenText = scope.messages.lastSeen.value + ' ' + lastSeen;
                            }
                            if (scope.itemDetails.lastSeen === null || scope.itemDetails.lastSeen < scope.itemDetails.lastScanned) {
                                scope.lastSeenText = scope.messages.lastScanned.value + ' ' + lastScanned;
                                scope.isLatestScanned = true;
                            }
                            if (scope.itemDetails.serviceDate) {
                                var converted = metDates.momentUtcToLocal(scope.itemDetails.serviceDate);
                                scope.serviceDatePicker = converted;
                            }

                            var geocoder = new google.maps.Geocoder;
                            geocodeLatLng(geocoder);

                            if (scope.itemDetails.cycleInformation) {
                                scope.lastSyncDate = metDates.convertUtcToLocal(scope.itemDetails.cycleInformation.lastSync, metDates.longDateTimeFormat);
                            }

                            scope.loading = false;
                            if (isCancel) {
                                scope.detailEditView = false;
                            }
                            var searchTerm = scope.itemDetails.modelNumber;
                            if (searchTerm !== null) {
                                metItems.searchItems(
                                    searchTerm, 0, 10,
                                    function(searchResponse) {
                                        _.forEach(searchResponse.items,
                                            function (match) {
                                                scope.isValidModelNumber = match.modelNumber === scope.item.model;
                                            });
                                    });
                            }

                            scope.timeFromEntry = getTimeOwned();
                            if (scope.itemDetails.imageAlternates && scope.itemDetails.imageAlternates.smallUrl === null) {
                                scope.itemDetails.imageAlternates.smallUrl = '/Content/images/placeholder_other.png';
                            }
                            if (!scope.itemDetails.imageAlternates) {
                                scope.itemDetails.imageAlternates = scope.itemDetails.manufacturer.isPrimary
                                    ? { smallUrl: 'https://onekey-tool-images-na.s3.amazonaws.com/default-images/No%20Image%20Available.jpg' }
                                    : { smallUrl: '/Content/images/placeholder_other.png' }
                            }
                        });
                    }

                    function getTimeOwned() {
                        if (scope.itemDetails.dateAdded) {
                            var langKey = metDates.getLanguageCookies();
                            moment.locale(langKey);
                            var mDateAdded = moment(scope.itemDetails.dateAdded);
                            var adjustedDate = mDateAdded.add(mDateAdded.utcOffset() / 60, 'hours');
                            scope.timeFromEntry = adjustedDate.fromNow();
                        }
                        return scope.timeFromEntry;
                    }

                    var init = function (isCancel) {
                        scope.loadItems();
                        getUserItem(isCancel);
                        setTabSelectedIndex(0);
                        scope.setSelectedStatus(getStatusById(scope.item.statusId));
                        scope.serviceDateByRegion = scope.item.serviceDate ? moment(scope.item.serviceDate).format(metDates.date(false)) : null;
                        scope.updateError = false;
                    };

                    init();

                    function geocodeLatLng(geocoder) {
                        var latitude = scope.itemDetails.hasTickAttached ? scope.itemDetails.tick.latitude : scope.itemDetails.latitude;
                        var longitude = scope.itemDetails.hasTickAttached ? scope.itemDetails.tick.longitude : scope.itemDetails.longitude;

                        if (scope.itemDetails.lastSeen === null || scope.itemDetails.lastSeen < scope.itemDetails.lastScanned) {
                            latitude = scope.itemDetails.scanLatitude;
                            longitude = scope.itemDetails.scanLongitude;
                        }
                        var center = new google.maps.LatLng(latitude, longitude);
                        geocoder.geocode({'location': center}, function (results, status) {

                            if (status === 'OK') {
                                if (results[0]) {
                                    scope.address = results[0].formatted_address;
                                } else {
                                    scope.address = scope.messages.noAddressFound.value;
                                }
                            } else {
                                scope.address = scope.messages.noAddressFound.value;
                            }
                        });
                    }

                    function createPlaceModal(oldValue) {
                        var modalOptions = {
                            templateUrl: metUrls('addLocationModal'),
                            backdrop: true,
                            keyboard: true,
                            modalFade: true,
                            controller: function ($scope, $modalInstance, modalOptionsService) {
                                $scope.modalInit = modalInit;
                                $scope.save = save;
                                $scope.cancel = cancel;

                                function save() {
                                    var locationModel = { placeName: $scope.addLocationForm.location.$modelValue, typeId: 1 };
                                    $scope.saving = true;
                                    metLocations.create(locationModel, function (newLocation) {
                                        scope.itemDetails.place = newLocation;
                                        $modalInstance.close(newLocation);
                                    }, function () {
                                        $scope.saving = false;
                                        $scope.valid = false;
                                        if ($scope.location.placeName === "" || $scope.location.placeName === undefined) {
                                            $scope.duplicate = true;
                                            $scope.error = $scope.modalMessages.required.value;
                                        }
                                        else {
                                            $scope.duplicate = true;
                                            $scope.error = scope.modalMessages.error.value;
                                        }
                                    });
                                }

                                function cancel(reason) {
                                    $modalInstance.dismiss(reason);
                                }

                                function handleError(error) {
                                    $scope.saving = false;
                                    $scope.valid = false;
                                    $scope.duplicate = true;
                                    $scope.error = error.data.message === undefined ? error.data : error.data.message;
                                }

                                function modalInit() {
                                    $scope.modalMessages = modalOptionsService.locationModalOptions.messages;
                                }
                            },
                        };
                        var modalInstance = $modal.open(modalOptions);

                        modalInstance.result.then(function (response) {
                            scope.locations.push(response.toJSON());
                            scope.myModel = response.toJSON();
                            scope.setSelectedPlace(response.toJSON().placeName);
                        }, function () {
                            scope.itemDetails.place = oldValue;
                        });
                    }

                    function createPersonModal(oldValue) {
                        var modalOptions = modalOptionsService.personModalOptions;
                        modalOptions.controller = function ($scope, $modalInstance) {
                            $scope.save = save;
                            $scope.cancel = cancel;
                            $scope.personInit = personInit;
                            function save() {
                                metPeople.create($scope.person, function (newPerson) {
                                    scope.itemDetails.person = newPerson;
                                    $modalInstance.close(newPerson);
                                }, function () {
                                    $scope.saving = false;
                                    $scope.valid = false;
                                    if ($scope.person.personName === "" || $scope.person.personName === undefined) {
                                        $scope.duplicate = true;
                                        $scope.error = $scope.messages.required.value;
                                    }
                                    else {
                                        $scope.duplicate = true;
                                        $scope.error = $scope.messages.error.value;
                                    }
                                });
                            }

                            function cancel(reason) {
                                $modalInstance.dismiss(reason);
                            }

                            function personInit() {
                                $scope.messages = modalOptionsService.personModalOptions.messages;
                            }
                        };
                        var modalInstance = $modal.open(modalOptions);

                        modalInstance.result.then(function (success) {
                            scope.people.push(success.toJSON());
                            scope.setSelectedPerson(success.toJSON().personName);
                        }, function (error) {
                            scope.itemDetails.person = oldValue; 
                            scope.error = error;
                        });
                    }

                    function createDivisionModal(oldValue) {
                        var modalOptions = modalOptionsService.sharedDefaultOptions;
                        modalOptions.templateUrl = metUrls('addTradeModal');
                        var modalInstance = $modal.open(modalOptions);

                        modalInstance.result.then(function (success) {
                            scope.trades.push(success.toJSON());
                            scope.setSelectedDivision(success.toJSON().divisionName);
                        }, function () {
                            scope.itemDetails.division = oldValue;
                        });
                    }

                    function createCategoryModal(oldValue) {
                        var modalOptions = modalOptionsService.sharedDefaultOptions;
                        modalOptions.templateUrl = metUrls('addCategoryModal');
                        var modalInstance = $modal.open(modalOptions);

                        modalInstance.result.then(function (result) {
                            scope.itemDetails.category = result;
                            getCategories();
                            scope.categories.push(result);
                        }, function () {
                            scope.itemDetails.category = oldValue;
                        });
                    }

                    function createManufacturerModal(oldValue) {
                        var modalOptions = modalOptionsService.sharedDefaultOptions;
                        modalOptions.templateUrl = metUrls('addManufacturerModal');
                        var modalInstance = $modal.open(modalOptions);

                        modalInstance.result.then(function (success) {
                            scope.itemDetails.manufacturer = success;
                        }, function () {
                            scope.itemDetails.manufacturer = oldValue;
                        });
                    }

                    function getCategories() {
                        metCategories.getAll({
                            includeUncategorized: true
                        },
                            function (data) {
                                var categories = [];
                                scope.parentCategories = [];
                                _.forEach(data.items, function (category) {
                                    category.displayName = category.categoryName;
                                    categories.push(category);
                                    scope.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);
                                    });
                                });

                                scope.categories = categories;;
                                var newCategory = {
                                    categoryName: scope.messages.addCategoryOption.value,
                                    categoryId: -2,
                                    childCategories: null
                                };
                                scope.categories.unshift(newCategory);
                                _.forEach(scope.categories, function (item) {
                                    if (item.childCategories !== null && item.childCategories.length > 0) {
                                        _.forEach(item.childCategories, function (childCategory) {
                                            childCategory.childCategories = [];
                                            childCategory.categoryName = item.categoryName + ' ' + childCategory.categoryName;

                                            var index = scope.categories.map(function (category) { return category.categoryId; }).indexOf(childCategory.categoryId);
                                            scope.categories.splice(index, 1);
                                            scope.categories.push(childCategory);
                                        });
                                    }
                                });
                            });
                    }
                }
            };
        }
    ]);
}());

(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 oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metItemResources', [
        'urls', 'localize', 'dates',
        function (metUrls, metLocalize, metDates) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('itemResources'),
                scope: {
                    item: '='
                },
                link: function (scope, element, attrs) {
                    scope.messages = {
                        date: metLocalize('fieldNames', 'date'),
                        itemValue: metLocalize('fieldNames', 'ItemValue'),
                        serviceType: metLocalize('fieldNames', 'serviceType'),
                        location: metLocalize('fieldNames', 'place'),
                        purchaseInformation: metLocalize('fieldNames', 'purchaseInformation')
                    }
                    

                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metServiceRecord', [
        '$compile', 'urls', 'localize', 'dates', 'serviceRecords', 'itemStatuses', 'notify',
        function ($compile, metUrls, metLocalize, metDates, metServiceRecordService, itemStatuses, metNotify) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('serviceRecord'),
                scope: {
                    item: '='
                },
                link: function (scope, element) {
                    scope.messages = {
                        date: metLocalize('fieldNames', 'date'),
                        cost: metLocalize('fieldNames', 'cost'),
                        serviceType: metLocalize('fieldNames', 'serviceType'),
                        serviceRecord: metLocalize('fieldNames', 'serviceRecord'),
                        servicedBy: metLocalize('fieldNames', 'servicedBy'),
                        notes: metLocalize('fieldNames', 'notes'),
                        addRecord: metLocalize('fieldNames', 'addRecord'),
                        addServiceRecord: metLocalize('commands', 'addRecord_AllCaps'),
                        everythingInOneSpot: metLocalize('messages', 'everythingInOneSpot'),
                        emptyServiceRecordText: metLocalize('messages', 'emptyServiceRecordText'),
                        createRecord: metLocalize('commands', 'createRecord'),
                        delete: metLocalize('commands', 'delete'),
                        deleteConfirm: metLocalize('messages', 'deleteUploadConfirm'),
                        edit: metLocalize('commands', 'edit'),
                        view: metLocalize('commands', 'view'),
                        uploads: metLocalize('fieldNames', 'uploads')
                    };
                    if (!scope.serviceRecords) {
                        scope.serviceRecords = [];
                    }
                    scope.serviceTypes = '';
                    scope.emptyServiceRecords = false;
                    scope.statuses = [];
                    scope.dateFormat = metDates.date(true);
                    scope.hasUploads = false;

                    scope.createRecord = createRecord;
                    scope.getContainer = getContainer;
                    scope.hideAddDialog = hideAddDialog;
                    scope.showAddDialog = showAddDialog;
                    scope.deleteServiceRecord = deleteServiceRecord;
                    scope.refreshServiceRecords = refreshServiceRecords;
                    var statuses = itemStatuses.getAll();
                    statuses.$promise.then(function (data) {
                        _.forEach(data.items, function (status) {

                            scope.statuses.push(status);
                        });
                    });
                    scope.item.statuses = scope.statuses;
                    
                    scope.emptyServiceRecords = false;

                    metServiceRecordService.getAllByUserItemId(scope.item.id, function (data) {
                        scope.serviceRecords = data;
                        for (var i = 0; i < scope.serviceRecords.length; i++) {
                            scope.serviceRecords[i].localDate = metDates.convertUtcToLocal(scope.serviceRecords[i].date, scope.dateFormat);
                            scope.serviceRecords[i].cost =
                                scope.serviceRecords[i].cost === null ? 0 : scope.serviceRecords[i].cost;
                            for (var z = 0; z < scope.serviceRecords[i].serviceRecordUploads.length; z++) {
                                scope.serviceRecords[i].serviceRecordUploads[z].createdOnLocal = metDates.convertUtcToLocal(scope.serviceRecords[i].serviceRecordUploads[z].createdOn, scope.dateFormat);
                            }
                        }
                        scope.emptyServiceRecords = scope.serviceRecords.length <= 0;
                    }, function (error) { console.log(error) });

                    metServiceRecordService.getTypes(function (data) {
                        scope.serviceTypes = data;
                    }, function (error) { console.log(error) });

                    scope.getTypeForRecords = function (typeId) {
                        var desc = "";
                        angular.forEach(scope.serviceTypes, function (recordType) {
                            if (parseInt(recordType.id) == typeId)
                                desc = recordType.name;
                        });

                        return desc;
                    }
                    scope.serviceTypes =
                        scope.serviceRecords = [];

                    function createRecord(serviceRecord) {
                        var result = metServiceRecordService.create(serviceRecord);
                        result.$promise.then(function (response) {
                            console.log(response.data);
                        });
                    }
                    scope.editServiceRecord = function (selectedServiceRecord) {
                        console.log('in edit view');
                        scope.isEdit = true;
                        scope.selectedRecord = selectedServiceRecord;
                        scope.hasUploads = scope.selectedRecord.serviceRecordUploads.length > 0;
                        var container = getContainer();
                        var el = $compile('<met-add-edit data-item="item" data-service-record-items="serviceRecords" selected-record="selectedRecord" data-has-uploads="hasUploads" data-reload-records="refreshServiceRecords"></met-add-edit>')(scope);
                        container.append(el);
                        showEditDialog(container, selectedServiceRecord);
                    }
                    
                    scope.addServiceRecord = function () {
                        scope.isEdit = false;
                        var container = getContainer();
                        scope.selectedRecord = undefined;
                        scope.hasUploads = false;
                        var el = $compile('<met-add-edit data-item="item" data-service-record-items="serviceRecords" selected-record="selectedRecord" data-has-uploads="hasUploads" data-reload-records="refreshServiceRecords" data-empty-service-records="emptyServiceRecords"></met-add-edit>')(scope);
                        container.append(el);
                        showAddDialog(container);
                    }
                    
                    function getContainer() {
                        return element.parents('.item-container');
                    }

                    function showEditDialog(container, selectedServiceRecord) {

                        container.children().css('display', 'none');
                        $('#oneKeyAddEditContainer').css('display', 'table-cell');
                        scope.serviceRecord = selectedServiceRecord;
                    }

                    function showAddDialog(container) {
                        container.children().css('display', 'none');
                        $('#oneKeyAddEditContainer').css('display', 'table-cell');

                    }

                    function hideAddDialog(container) {
                        container.children().css('display', 'block');
                        $('#oneKeyAddEditContainer').remove();
                    }

                    function refreshServiceRecords() {
                        metServiceRecordService.getAllByUserItemId(scope.item.id,
                            function (response) {
                                scope.serviceRecords = response.data;
                                for (var i = 0; i < scope.serviceRecords.length; i++) {
                                    for (var z = 0; z < scope.serviceRecords[i].serviceRecordUploads.length; z++) {
                                        scope.serviceRecords[i].serviceRecordUploads[z].createdOnLocal = metDates.convertUtcToLocal(scope.serviceRecords[i].serviceRecordUploads[z].createdOn, scope.dateFormat);
                                    }
                                }
                                var container = scope.getContainer();
                                scope.hideAddDialog(container);
                            },
                            function (response) {
                                console.log(response.message);
                            });
                    }


                    scope.cancel = function () {
                        var container = scope.getContainer();
                        scope.hideAddDialog(container);
                    };

                    scope.update = function (serviceRecord) {
                        serviceRecords.update(serviceRecord,
                            function (serviceRecord) {
                                scope.original = null;
                                metNotify.success(serviceRecord.Id + 'updated successfully');
                            },
                            function (error) {
                                serviceRecord.error = error.data.message;
                            });
                    };

                    function deleteServiceRecord(serviceRecordId) {
                        metServiceRecordService.remove(serviceRecordId,
                            function (response) {
                                if (response.$resolved) {
                                    scope.serviceRecords = scope.serviceRecords.filter(function(deletedRecord) {
                                        return deletedRecord.id !== serviceRecordId;
                                    });
                                }
                                scope.emptyServiceRecords = scope.serviceRecords.length === 0;
                            },
                            function (response) {
                                metNotify.error(response.data.message);
                            });

                    }
                }
            };
        }
    ]);
}());

(function() {
    'use strict';

    var app = angular.module('oneKeyApp');

    app.directive('metFileUploader',
        [
            'Upload', '$log', 'notify', 'localize', 'urls', function($upload, $log, metNotify, metLocalize, metUrls) {
                return {
                    restrict: 'E',
                    scope: {
                        ngModel: '=',
                        ngModelList: '=',
                        metModelAlternates: '=',
                        metUploadUrl: '@',
                        metUploadAllowPdfs: '=',
                        metOnFileUploaded: '=',
                        metThumbDefault: '=',
                        metDefaultImage: '=',
                        metForceImage: '=',
                        metShowThumb: '@',
                        metImageDetailPosition: '@',
                        metDisableSave: '=?',
                        metDisabled: '=?',
                        metRemoveFile: '&?'
                    },
                    template:
                        '<div class="image-upload" data-ng-class="{\'image-upload-with-thumb\':showThumbnail}" data-ng-show="!metDisabled">' +
                            '<div data-ng-if="canUpload">' +
                            '<button data-ng-if="!metUploadAllowPdfs" class="btn btn-action-gray show-border" ngf-select="fileChanged($files)" accept="image/*" >{{buttonText.value}} ...</button> ' +
                            '<button data-ng-if="metUploadAllowPdfs && !fallback" class="btn btn-action-gray show-border" ngf-select="fileChanged($files)" accept="image/*, application/pdf" >{{buttonText.value}}</button> ' +
                            '<button data-ng-if="metUploadAllowPdfs && fallback" class="btn btn-action-gray show-border" ngf-select="fileChanged($files)">{{buttonText.value}}</button> ' +
                            '<met-image-thumb data-ng-if="showThumbnail" data-met-thumb-src="metModelAlternates.smallUrl" data-met-detail-src="metModelAlternates.mediumUrl" data-met-thumb-default="metThumbDefault" data-met-image-detail-position="{{metImageDetailPosition}}" ></met-image-thumb>' +
                            '<button data-ng-if="showRemoveButton()" data-ng-click="removeFile()" class="btn btn-action-gray show-border">{{ removeLink.value }}' +
                            '<div class="loading" data-ng-show="uploadingImage"><i class="fa fa-spinner fa-spin"></i></div>' +
                            '</div>' +
                            '<div data-ng-if="!canUpload">' +
                            '<a href="https://www.adobe.com/go/getflashplayer" target="_blank" border="0"><img src="/content/images/get_flash_player.jpg"/></a>' +
                            '<p class="small" ng-bind-html="installFlashToUpload.value"></p>' +
                            '</div>' +
                            '</div>',

                    replace: true,
                    link: function(scope, element, attrs) {
                        scope.buttonText = metLocalize('commands', 'UploadFile');
                        scope.removeLink = metLocalize('commands', 'Remove');
                        scope.unexpectedError = metLocalize('messages', 'unexpectedError');
                        scope.installFlashToUpload = metLocalize('messages', 'installFlashToUpload');


                        scope.fallback = angular.isDefined(FileAPI.hasFlash) && FileAPI.hasFlash;
                        scope.canUpload = !angular.isDefined(FileAPI.hasFlash) || FileAPI.hasFlash;

                        scope.initialImg = scope.metForceImage ? scope.ngModel : "";
                        scope.initialAlts = scope.metForceImage ? scope.metModelAlternates : "";
                        scope.fileUploaded = false;

                        scope.showThumbnail = angular.isDefined(attrs.metShowThumb);

                        var hasDisableSave = attrs.metDisableSave;

                        scope.showRemoveLink = function() {

                            var show = scope.ngModel;
                            if (scope.metForceImage) {
                                show = scope.fileUploaded;
                            }
                            if (scope.ngModel === scope.metDefaultImage) {
                                show = false;
                            }
                            return show;
                        }

                        scope.removeFile = function() {
                            scope.ngModel = "";
                            scope.metModelAlternates = "";

                            scope.fileUploaded = false;
                            if (scope.metOnFileUploaded) {
                                scope.$eval(scope.metOnFileUploaded);
                            }

                            if ('ngModelList' in attrs) {
                                for (var i = 0; i < scope.ngModelList.length; i++) {
                                    scope.ngModelList[i].imageUrl = "";
                                    scope.ngModelList[i].imageAlternates = "";
                                }
                            }
                        }

                        scope.showRemoveButton = function() {
                            if (!scope.ngModel ||
                                scope.ngModel == metUrls('milwaukeeDefault') ||
                                scope.ngModel == metUrls('otherDefault')) {
                                return false;
                            }
                            return true;
                        }

                        scope.fileChanged = function(files) {
                            if (files != null && files.length > 0) {
                                scope.uploadingImage = true;
                                if (hasDisableSave) {
                                    scope.metDisableSave = true;
                                }

                                $upload.upload({
                                    url: scope.metUploadUrl,
                                    method: 'POST',
                                    file: files[0]
                                }).success(function(result) {
                                        if (angular.isDefined(result.message) &&
                                            !angular.isDefined(result[scope.metUploadModelPropertyActual])) {
                                            //it is actually an error. fileapi.js doesn't recognize 400 Bad Request as an error.
                                            // so if we get a message property, and not the one they were looking for, treat it as an error.
                                            metNotify.error(result.message);
                                        }
                                        else {
                                            scope.ngModel = result['imageUrl'];
                                            scope.metModelAlternates = result['imageAlternates'];
                                            scope.fileUploaded = true;
                                            if (scope.metOnFileUploaded) {
                                                scope.$eval(scope.metOnFileUploaded);
                                            }

                                            // upload the given list of models if given a list (batch update child detail images)
                                            if ('ngModelList' in attrs) {
                                                for (var i = 0; i < scope.ngModelList.length; i++) {
                                                    scope.ngModelList[i].imageUrl = result['imageUrl'];
                                                    scope.ngModelList[i].imageAlternates = result['imageAlternates'];
                                                }
                                            }
                                        }
                                        scope.uploadingImage = false;
                                        if (hasDisableSave) {
                                            scope.metDisableSave = false;
                                        }
                                    }
                                ).error(function(e) {
                                    if (angular.isDefined(e) && angular.isDefined(e.message)) {
                                        metNotify.error(e.message);
                                    }
                                    else {
                                        metNotify.error(scope.unexpectedError.value);
                                    }
                                    scope.uploadingImage = false;
                                    if (hasDisableSave) {
                                        scope.metDisableSave = false;
                                    }
                                });
                            }
                        };
                        scope.uploadingImage = false;
                        scope.uploadFile = null;
                    }


                }
            }
        ]);
}());


(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metImageThumb', [
        '$compile', '$rootScope', 'urls',
        function ($compile, $rootScope, metUrls) {
            var popoverTemplate = '<div class="popover popover-image-detail" role="tooltip"><h3 class="popover-title"></h3><button type="button" class="close close-overhang"><i class="icon icon-cross-circle fa-lg"></i><span class="sr-only">Close</span></button><div class="popover-content"></div></div>';
            var imagePopoverContentTemplate = '<img data-ng-src="{{detailsSrc()}}" alt ="{{altText}}" class="receipt-detail"/>';
            var pdfPopoverContentTemplate = 'Pdf Attached';
         
            return {
                restrict: 'EA',
                replace: true,
                scope: {
                    metThumbSrc: '=',
                    metDetailSrc: '=',
                    metThumbDefault: '=',
                    altText: '@alt',
                    metImageDetailPosition: '@',
                    metThumbClass: '@'
                },
                template:
                    '<span>' +
                        '<img class="item-thumbnail {{metThumbClass}}" data-ng-if="!isPdf()" data-ng-class="{\'pointer\':showPointer()}" ' +
                        'data-ng-src="{{displaySrc()}}" alt ="{{altText}}" onerror="this.src=\'/Content/images/placeholder_other.png\'"/>' +
                    '<a href="{{metDetailSrc}}" target="_blank" data-ng-if="isPdf()"><img class="item-thumbnail item-thumbnail-pdf" ' +
                        'data-ng-src="{{pdfIcon}}" alt="{{altText}}"/></a></span>',
                link: function (scope, element, attrs) {
                    var position = scope.metImageDetailPosition || 'left';

                    scope.unspecifiedImageUrl = metUrls('otherDefault');

                    scope.pdfIcon = metUrls('pdfIcon');
                    scope.isPdf = function () {
                        return scope.metThumbSrc && scope.metThumbSrc.endsWith('.pdf');
                    };
                    //checks the path of the uploaded file and verifies if it is an image or not.
                    scope.IsImageUploaded = function () {
                        if (scope.detailsSrc() != scope.metThumbSrc)
                            return true;
                        else return false;
                    };
                    scope.displaySrc = function () {
                        return scope.metThumbSrc || scope.metThumbDefault || scope.unspecifiedImageUrl;
                    };
                    scope.detailsSrc = function() {
                        return scope.metDetailSrc || scope.metThumbDefault;
                    }
                    scope.showPointer = function () {
                        return !scope.isPdf(scope.metThumbSrc) &&
                            (scope.metThumbSrc || scope.hasDefault);
                    };
                    scope.hasDefault = scope.metThumbDefault &&
                        scope.metThumbDefault != scope.unspecifiedImageUrl;

                    var hasPopover = false;
                    scope.$watch('metThumbSrc', function (newValue, oldValue) {
                        if (newValue && !hasPopover) {
                            //an image was added to the item, but the item doesn't have a popover for it.
                            // this is a weird hack. sometimes the popover doesn't work the first time.
                            bindPopover();
                            destroyPopover();
                            bindPopover();
                        }
                        else if (!newValue && scope.hasDefault && !hasPopover) {
                            // this is a weird hack. sometimes the popover doesn't work the first time.
                            bindPopover();
                            destroyPopover();
                            bindPopover();
                        }
                        else if (!newValue && oldValue && !scope.hasDefault && hasPopover) {
                            //it used to have an image, but doesn't anymore...
                            // and it doesn't have a clickable "default" image (i.e. it is not a milwaukee tool)
                            // and it has a popover for displaying the detail image
                            destroyPopover();
                        }
                    });
                    scope.$on('metImageDetailOpened', function (e, name) {
                        if (name != scope.popoverId) {
                            jQuery214(element).popover('hide');
                        }
                    });
                    scope.$on('$destroy', function () {
                        if (angular.isDefined(scope.popoverId)) {
                            jQuery214('#' + scope.popoverId).remove();
                        }
                        destroyPopover();
                    });

                    var destroyPopover = function () {
                        jQuery214(element).popover('destroy');
                        hasPopover = false;
                    };
                    var bindPopover = function () {
                        var htmlTemplate = scope.isPdf() ? pdfPopoverContentTemplate : imagePopoverContentTemplate;
                        var innerContent = $compile(htmlTemplate)(scope);
                        var options = {
                            template: popoverTemplate,
                            content: innerContent,
                            placement: position,
                            html: true,
                            trigger: 'click',
                            container: '#onekey'
                        };
                            jQuery214(element).popover(options)
                                .on('shown.bs.popover', function (e) {
                                    scope.popoverId = jQuery214(element).attr('aria-describedby');
                                    $rootScope.$broadcast('metImageDetailOpened', scope.popoverId);
                                    jQuery214('#' + scope.popoverId + ' .close').bind('click', function () {
                                        jQuery214(element).popover('hide');
                                    });
                                    angular.element(document).click(function () {
                                        jQuery214('#' + scope.popoverId).remove();
                                    });
                                });
                            hasPopover = true;
                        
                    };
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metBasicInfo', [
        '$http', '$filter', '$window', 'urls', 'localize', 'dates', 'crimpers',
        function ($http, $filter, $window, metUrls, metLocalize, metDates, metCrimpers) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('crimperReportInfo'),
                link: function (scope, element, attrs) {
                    scope.infoMessages = {
                        basicInformation: metLocalize('messages', 'basicInformation'),
                        companyName: metLocalize('fieldNames', 'companyName'),
                        jobName: metLocalize('fieldNames', 'jobName'),
                        address: metLocalize('fieldNames', 'address'),
                        operator: metLocalize('fieldNames', 'operator'),
                        customer: metLocalize('fieldNames', 'customer'),
                        city: metLocalize('fieldNames', 'city'),
                        state: metLocalize('fieldNames', 'state'),
                        zip: metLocalize('fieldNames', 'zip'),
                        country: metLocalize('fieldNames', 'country'),
                        notes: metLocalize('fieldNames', 'notes'),
                        phoneNumber: metLocalize('fieldNames', 'phoneNumber'),
                        faxNumber: metLocalize('fieldNames', 'faxNumber'),
                        website: metLocalize('fieldNames', 'website'),
                        units: metLocalize('fieldNames', 'units'),
                        unitsBar: metLocalize('fieldNames', 'unit_Bar'),
                        unitsPsi: metLocalize('fieldNames', 'unit_Psi'),
                        logo: metLocalize('fieldNames', 'companyLogo'),
                        saveComanyInfo: metLocalize('fieldNames', 'saveCompanyInformationToProfile'),
                        lowPressureIncidents: metLocalize('fieldNames', 'lowPressureIncidents'),
                        maxPressure: metLocalize('fieldNames', 'maxPressure'),
                        cycleNumber: metLocalize('fieldNames', 'cycleNumber'),
                        previewReport: metLocalize('commands', 'previewReport'),
                        selectFromList: metLocalize('commands', 'selectFromList'),
                        requiredValidation: metLocalize('validation', 'requiredAttribute_ValidationError'),
                        loadingReport: metLocalize('messages', 'loadingReport')
                    }

                    scope.previewLoading = false;
                    scope.jobName = "";
                    scope.operator = "";
                    scope.customer = "";
                    scope.notes = "";
                    scope.isPsi = true;
                    scope.isBar = false;

                    scope.timeZone = new jstz.determine().name();

                    scope.saveCompanyInfo = true;
                    scope.showValidationMessages = false;
                    scope.imageUploadUrl = metUrls('imagesUserItemsApi');
                                       
                    scope.itemInstanceIds = [];
                    scope.getIncidents = function () {
                        _.forEach(scope.selectedCrimpers, function (value, index) {
                            scope.itemInstanceIds.push(value.itemInstanceId);
                        });

                        var beginDate = metDates.convertLocalToUtc(scope.startDate);
                        var endDate = metDates.convertLocalToUtc(scope.endDate);
                        metCrimpers.getCrimperIncidents(scope.itemInstanceIds, beginDate, endDate, 0,
                            function (data) {
                                createLowPressureIncidents(data.incidents);
                            }
                        );
                    };

                    scope.crimperIncidents = [];
                    function createLowPressureIncidents(incidents) {
                        _.forEach(scope.selectedCrimpers, function (crimper, index) {
                            var itemIncidents = $filter('filter')(incidents, { itemInstanceId: crimper.itemInstanceId });
                            if (itemIncidents.length > 0) {
                                scope.crimperIncidents.push({ crimper: crimper, incidents: itemIncidents });
                            }
                        });
                    }

                    scope.showErrorMessage = function (field, errorProperty) {
                        return field.$error[errorProperty] && (field.$dirty || scope.showValidationMessages);
                    };

                    scope.getRequiredValidation = function (fieldName) {
                        var message = scope.infoMessages.requiredValidation.value;
                        if (message) {
                            message = message.replace("{0}", fieldName);
                        }
                        return message;
                    };

                    scope.getLocalDate = function(utcDate) {
                        return metDates.convertUtcToLocal(utcDate, metDates.date(true));
                    };

                    var countryCode = "";
                    
                    function getCountryCode() {
                        countryCode = $filter('filter')(scope.countries, { code: scope.companyInfo.country })[0].code;
                        return countryCode;
                    }

                    function getStatesByCountry(code) {
                        $http({
                            url: metUrls('statesByCountry').concat('/'+code),
                            method: 'GET',
                            headers: { "Content-Type": "application/json;charset=utf-8" }
                        }).then(function (result) {
                            if (result.data.length != 0) {
                                scope.noStates = false;
                                $('#stateList').show();
                                scope.statesByCountry = result.data;
                                scope.companyInfo.state = "";
                            }
                            else {
                                $('#stateList').hide();
                                scope.noStates = true;
                                scope.companyInfo.state = "";
                            }   
                        }, function (error) {
                            $('#stateList').hide();
                            scope.noStates = true;
                            scope.companyInfo.state = "";
                        });
                    }

                    if (scope.companyInfo.country) {
                        getStatesByCountry(getCountryCode());
                    }

                    scope.updateStatesList = function () {
                        scope.statesByCountry = [];
                        if (scope.companyInfo.country) {
                            getStatesByCountry(getCountryCode());
                        }
                    };

                    scope.previewReport = function () {
                        document.cookie = "Authorization=Bearer " + localStorage.getItem('access_token') + ";path=/";
                        scope.previewLoading = true;
                        $window.scrollTo(0, 0);
                        var itemIncidents = [];
                        _.forEach(scope.crimperIncidents, function (crimperIncidents, index) {
                            _.forEach(crimperIncidents.incidents, function (incident, index) {
                                itemIncidents.push({ id: incident.id, notes: incident.notes });
                            });
                        });

                        var report = {
                            generalInfo: {
                                startDate: scope.startDate,
                                endDate: scope.endDate,
                                customerName: scope.customer,
                                jobName: scope.jobName,
                                operator: scope.operator,
                                notes: scope.notes,
                                companyName: scope.companyInfo.companyName,
                                address1: scope.companyInfo.address1,
                                city: scope.companyInfo.city,
                                state: scope.companyInfo.state,
                                zip: scope.companyInfo.zip,
                                country: scope.companyInfo.country,
                                phone: scope.companyInfo.phone,
                                fax: scope.companyInfo.fax,
                                website: scope.companyInfo.website,
                                companyLogo: scope.companyInfo.companyLogo,
                                units: scope.isPsi && scope.isBar ? 2 : scope.isBar ? 1 : 0
                            },
                            ItemIncidents: itemIncidents,
                            itemInstanceIds: scope.itemInstanceIds,
                            crimperType: 0,
                            offset: scope.offset,
                            timeZone: scope.timeZone
                        }


                        if (scope.crimperForm.$valid) {

                            if (scope.saveCompanyInfo) {
                                metCrimpers.saveCompanyInfo(scope.companyInfo);
                            }

                            metCrimpers.createReport(report,
                                function (data) {
                                    scope.showPreviewReport(data);
                                    scope.previewLoading = false;
                                },
                                function (error) {
                                    scope.previewLoading = false;
                                }
                            );
                        } else {
                            _.forEach(scope.crimperForm.$error, function (field) {
                                _.forEach(field, function (errorField) {
                                    errorField.$setDirty();
                                    scope.previewLoading = false;
                                })
                            });
                            scope.showValidationMessages = true;
                        }
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metCrimpersList', [
        'urls', 'localize', 'dates',
        function (metUrls, metLocalize, metDates) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('crimperReportList'),
                scope: {
                    results: '=',
                    sortColumn: '=',
                    isDescending: '='
                },
                link: function (scope, element, attrs) {
                    scope.messages = {
                        description: metLocalize('fieldNames', 'itemDescription'),
                        location: metLocalize('fieldNames', 'location'),
                        totalCycles: metLocalize('fieldNames', 'totalCycles'),
                        cyclesSinceService: metLocalize('fieldNames', 'cyclesSinceService'),
                        lastSync: metLocalize('fieldNames', 'lastSyncedOn'),
                        coinCell: metLocalize('fieldNames', 'coinCellLevel'),
                        serialNumber: metLocalize('fieldNames', 'serialNumber'),
                        place: metLocalize('fieldNames', 'placeId')
                    }

                    scope.sortTable = function (sortedColumn) {
                        if (scope.sortColumn == sortedColumn) {
                            scope.isDescending = !scope.isDescending;
                        } else {
                            scope.sortColumn = sortedColumn;
                            scope.isDescending = false;
                        }
                        scope.$emit("update-results");
                    }

                    scope.allSelected = false;
                    scope.allSelectedChange = function () {
                        _.forEach(scope.results, function (value, index) {
                            value.selected = scope.allSelected;
                        });
                    }

                    scope.selectionChange = function () {
                        scope.allSelected = false;
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metLocations', [
        '$filter', 'urls', 'localize', 'itemFieldFactory',
        function ($filter, metUrls, metLocalize, metItemFieldFactory) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('crimperReportsLocationFilters'),
                scope: {
                    updateResults: '&',
                    showHideLocations: '&',
                },
                link: function (scope, element, attrs) {
                    scope.itemFields = metItemFieldFactory;
                    scope.firstColumnEnd;
                    scope.secondColumnEnd;

                    scope.locationClick = function (location) {
                        var selected = !location.isSelected;
                        _.forEach(scope.itemFields.locations, function (value, index) {
                            value.isSelected = false;
                        });

                        location.isSelected = selected;
                        scope.showHideLocations();

                        var locationId = location.isSelected ? location.placeId : undefined;
                        scope.$emit("location-updated", { locationId: locationId });
                        setTimeout(function () { scope.updateResults(); }, 500);
                    }

                    scope.$watch('itemFields.locations', function (newValue) {
                        var length = parseInt(newValue.length / 3);
                        var mod = newValue.length % 3;

                        scope.firstColumnEnd = length - 1 + (mod >= 1 ? 1 : 0);
                        scope.secondColumnEnd = (length * 2) + (mod == 0 ? -1 : mod == 1 ? 0 : 1);
                    }, true)

                    scope.itemFields.init();
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metPreviewReport', [
        '$window', 'urls', 'localize', 'dates',
        function ($window, metUrls, metLocalize, metDates) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('crimperPreviewReport'),
                link: function (scope, element, attrs) {
                    scope.previewMessages = {
                       previewReport: metLocalize('commands', 'previewReport'),
                       downloadPdf: metLocalize('commands', 'downloadPDF')
                    }
                                        
                    scope.reportHtml = "";
                    scope.downloadUrl = "";

                    scope.downloadReport = function () {
                        $window.open(scope.downloadUrl, '_blank');
                    }
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metSelectCrimpers', [
        '$filter', 'urls', 'localize', 'dates', 'crimpers',
        function ($filter, metUrls, metLocalize, metDates, metCrimpers) {
            return {
                restrict: 'E',
                replace: true,
                templateUrl: metUrls('crimperReportSelect'),
                link: function (scope, element, attrs) {
                    scope.searchTerm = "";
                    scope.loading = true;
                    scope.noCrimpers = false;
                    scope.crimpers = [];
                    scope.locationsExpanded = false;
                    var date = new Date();
                    scope.offset = date.getTimezoneOffset();
                    date.setDate(date.getDate() - 365); // start date temporarily set back 1 year.
                    var startDate = date.toISOString();
                    scope.startDate = metDates.convertUtcToLocal(startDate);
                    scope.endDate = metDates.convertUtcToLocal(new Date().toISOString());
                    scope.locationId;
                    
                    scope.messages = {
                        inventorySearch: metLocalize('messages', 'inventorySearch'),
                        addInventory: metLocalize('titles', 'crimperReports_Form'),
                        crimpers: metLocalize('commands', 'crimpers'),
                        locationsDropDown: metLocalize('commands', 'locationsDropDown'),
                        startLabel: metLocalize('commands', 'startLabel'),
                        endLabel: metLocalize('commands', 'endLabel'),
                        loadingCrimpers: metLocalize('messages', 'loadingCrimpers'),
                        crimpersEmpty: metLocalize('messages', 'crimpersEmpty'),
                        crimperReports: metLocalize('titles', 'crimperReports'),
                        placesDropDown: metLocalize('commands', 'placesDropDown'),
                        hydraulics: metLocalize('messages', 'hydraulics'),
                        hydraulicReports: metLocalize('messages', 'hydraulicReports'),
                        loadingHydraulics: metLocalize('messages', 'loadingHydraulics'),
                        hydraulicsEmpty: metLocalize('messages', 'hydraulicsEmpty')
                    };
         
                    scope.$on('location-updated', function (event, data) {
                        scope.locationId = data.locationId;
                    });

                    scope.$on('update-results', function (event, data) {
                        scope.updateResults();
                    });

                    scope.showGenerateReport = function () {
                        return $filter('filter')(scope.crimpers, { selected: true }).length > 0;
                    }

                    scope.searchKeyUp = function ($event) {
                        if ($event.keyCode === 13) {
                            scope.updateResults();
                        }
                    }

                    scope.updateResults = function () {
                        scope.loading = true;
                        var filters = {
                            searchTerm: scope.searchTerm,
                            locationId: scope.locationId,
                            crimperType: undefined,
                            beginDate: scope.startDate,
                            endDate: scope.endDate,
                            itemInstanceIds: undefined
                        };

                        metCrimpers.getCrimpers(filters,
                            function (data) {
                                scope.crimpers = data.items;
                                scope.$broadcast("grid-updated", { totalResults: scope.crimpers.length, startNumber: 1, currentPage: 1, resultsPerPage: scope.crimpers.length });
                                scope.loading = false;
                                scope.noCrimpers = data.items.length == 0;
                            },
                            function (error) {

                            }
                        );
                    }

                    scope.endDateMax = new Date();
                    scope.startDateMax = new Date();
                    scope.endDateChange = function () {
                        var isValidDate = moment(scope.endDate, scope.datePickerOptions.format, true).isValid();
                        if (isValidDate) {
                            scope.startDateMax = scope.endDate;
                        }                       
                    }

                    scope.showHideLocations = function () {
                        scope.locationsExpanded = !scope.locationsExpanded;
                    }

                    scope.updateResults();                    
                }
            };
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.controller('crimpersController', [
        '$scope', '$sce', '$filter', 'localize', 'crimpers', 'dates', 'reportingService',
        function crimpersCtrl($scope, $sce, $filter, metLocalize, metCrimpers, metDates, reportingService) {
            $scope.datePickerOptions = metDates.getDatePickerOptions();
            $scope.selectedCrimpers = [];
            $scope.showCrimperList = true;
            $scope.showBasicInfo = false;
            $scope.previewReportVisible = false;
            $scope.countries = [];
            $scope.states = [];
            $scope.companyInfo = {};
            $scope.initialize = initialize;
            $scope.statesByCountry = [];
            $scope.noStates = false;

            $scope.enterInfo = function () {
                $scope.selectedCrimpers = $filter('filter')($scope.crimpers, { selected: true });
                $scope.showCrimperList = false;
                $scope.getIncidents();
                $scope.showBasicInfo = true;
            };

            $scope.showPreviewReport = function (reportData) {
                $scope.reportHtml = $sce.trustAsHtml(reportData.previewHtml);
                $scope.downloadUrl = reportData.pdfUrl;
                $scope.showBasicInfo = false;
                $scope.previewReportVisible = true;
            };

            function initialize(){
                getCountries();
                getCompanyInfo();
            }

            function getCompanyInfo(){
                reportingService.getUserProfile()
                    .then(function(data){
                        $scope.companyInfo = data;
                        $scope.companyInfo.imageAlternates = {
                            smallUrl: data.logoUrl,
                            mediumUrl: data.logoUrl,
                            largeUrl: data.logoUrl
                        };
                        getStatesByCountryCode($scope.companyInfo.country);
                    });
            }

            function getStatesByCountryCode(code) {
                if (!code) {
                    return;
                }
                reportingService.getStatesByCountryCode(code)
                    .then(function(data){
                        $scope.statesByCountry = $scope.states = data;
                        $scope.noStates = data && data.length > 0;
                    });
            }

            function getCountries(){
                reportingService.getCountries()
                    .then(function(data){
                        $scope.countries = data;
                    });
            }
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.controller('crimpersCreateController', [
        '$scope', '$rootScope', '$log', '$timeout', '$anchorScroll', '$location', '$document', '$filter',
        'jstz', 'localize',
        'notify', 'locations', 'crimpers', 'dates', 'reportingService',
        function crimpersCreateCtrl(
            $scope, $rootScope, $log, $timeout, $anchorScroll, $location, $document, $filter,
            metJstz, metLocalize,
            metNotify, metLocations, metCrimpers, metDates, reportingService) {
            var self = this; // private vars

            var format = $filter('stringFormat');

            $anchorScroll.yOffset = 75;

            // maximum number of incidents to display
            $scope.MAX_INCIDENT_THRESHOLD = 100;

            $scope.items = [];
            $scope.currentStep;
            $scope.incidents = null;
            $scope.incidentIndex = 0;
            $scope.itemEventIncidents = null;
            $scope.itemEventSuccesses = null;
            $scope.totalIncidents = 0;
            $scope.eventsLoading = false;
            $scope.pdfSaving = false;
            $scope.allIncidentsLoaded = false;
            $scope.reportForm = null;
            $scope.companyInfo = {};
            $scope.allUnits;

            $scope.crimperType = 1;
            $scope.settings = {
                highchart : {
                    psi: null,
                    bar: null
                }
            };

            $scope.emptyGeneralInfo = {
                dateRange: {
                    startDate: null,
                    endDate: null
                }
            };

            $scope.endDateMax = new Date();
            $scope.startDateMax = new Date();
            $scope.endDateChange = function () {
                $scope.startDateMax = $scope.endDate;
            }

            $scope.messages = {
                pageTitle: metLocalize('titles', 'CrimperReports_Form'),
                oneKey: metLocalize('titles', 'OneKey'),
                graphTitle: metLocalize('titles', 'CrimperReports_ChartTitle'),
                graphXaxis: metLocalize('titles', 'CrimperReports_ChartXAxis'),
                graphYaxis: metLocalize('titles', 'CrimperReports_ChartYAxis'),
                graphSeriesIncidents: metLocalize('titles', 'CrimperReports_ChartIncidents'),
                graphSeriesSuccess: metLocalize('titles', 'CrimperReports_ChartSuccessfulCrimp'),
                companyInformationHasBeenSaved: metLocalize('messages', 'CompanyInformationHasBeenSaved'),
                companyInformationCouldNotBeSaved: metLocalize('messages', 'CompanyInformationCouldNotBeSaved'),
            };

            //#region Visibility

            $scope.showThreshold = function () {
                return !$scope.eventsLoading && ($scope.totalIncidents >= $scope.MAX_INCIDENT_THRESHOLD);
            };

            $scope.showIncidents = function () {
                return !$scope.eventsLoading;
            };

            $scope.showPsi = function () {
                return angular.isDefined($scope.generalInfo.units)
                    && ($scope.generalInfo.units === $scope.allUnits.psi.id
                        || $scope.generalInfo.units === $scope.allUnits.psiBar.id);
            };

            $scope.showPsiAndBar = function () {
                return angular.isDefined($scope.generalInfo.units)
                    && $scope.generalInfo.units == $scope.allUnits.psiBar.id;
            };

            $scope.showBar = function () {
                return angular.isDefined($scope.generalInfo.units)
                    && ($scope.generalInfo.units == $scope.allUnits.bar.id
                        || $scope.generalInfo.units == $scope.allUnits.psiBar.id);
            };
            //#endregion

            //#region Form Events

            $scope.submitReport = function ($event) {
                $event.preventDefault();
                $scope.pdfSaving = true;

                //fix dates to utc for request
                $scope.generalInfo.startDate = formatUtcForRequest($scope.generalInfo.dateRange.startDate);
                $scope.generalInfo.endDate = formatUtcForRequest($scope.generalInfo.dateRange.endDate);

                //#region Save Report

                var report = {
                    generalInfo: $scope.generalInfo,
                    itemInstanceIds: _.pluck($scope.items, 'itemInstanceId'),
                    itemIncidents: getFormItemIncidents(),
                    timeZone: getTimezone(),
                    crimperType: $scope.crimperType
                };
                debugger;
                metCrimpers.createReport(report, function (result) {
                    $scope.pdfSaving = false;
                    if (result.isValid) {
                        window.open(result.pdfUrl, '_blank');
                        metNotify.success(result.message);
                        $scope.backToSearch(null, true);
                    } else {
                        metNotify.error(result.message);
                    }
                }, function (error) {
                    $scope.pdfSaving = false;
                    metNotify.error('Unable to save report.');
                });

                //#endregion
            };

            $scope.changeStep = function (nextStep, $event, form) {
                if (nextStep == 2 &&
                    form
                    && !form.$valid) {
                    return;
                }
                $event.preventDefault();

                if ($scope.currentStep == 1 && nextStep == 2) {
                    //ensure the startDate has correct value.  ng-model is not updated when calendar auto-corrects min
                    $scope.generalInfo.dateRange.startDate = $scope.getElement('#GeneralInformationStartDate').value;
                    $scope.generalInfo.dateRange.endDate = $scope.getElement('#GeneralInformationEndDate').value;
                }

                $scope.currentStep = nextStep;                

                // If this is the Incidents step, load incidents if we haven't.
                if ($scope.currentStep == 2 && (!$scope.itemEventSuccesses && !$scope.itemEventIncidents)) {                    
                    reloadItems();
                    $scope.loadEvents();
                }

                if ($scope.currentStep == 3) {
                    $scope.loadHighCharts();
                }
                
                if (!$scope.eventsLoading)
                {
                    $location.hash('step' + $scope.currentStep);
                    $anchorScroll();
                }
            }

            $scope.loadEvents = function () {
                var itemInstancesIds = _.pluck($scope.items, 'itemInstanceId');

                $scope.eventsLoading = true;
                metCrimpers.getCrimperIncidents(
                    itemInstancesIds,
                    formatUtcForRequest($scope.generalInfo.dateRange.startDate),
                    formatUtcForRequest($scope.generalInfo.dateRange.endDate),
                    $scope.crimperType,
                    function (result) {
                        $scope.incidents = result.incidents;
                        $scope.totalIncidents = result.incidents.length;

                        // clear out old settings.
                        $scope.settings.highchart = {
                            psi: null,
                            bar: null
                        };

                        // if highchart settings were sent, apply them.
                        if (result.settings && result.settings.highchart) {
                            $scope.settings.highchart = {
                                psi: result.settings.highchart.psi,
                                bar: result.settings.highchart.bar
                            };
                        }

                        // Always load $Threshold number of incidents
                        $scope.itemEventIncidents = {}; // initalize
                        $scope.loadMoreIncidents();

                        $scope.itemEventSuccesses = {}; // initalize
                        createEventCollection($scope.itemEventSuccesses, result.successful);

                        $scope.eventsLoading = false;

                        // give a short timeout for events to generate before setting the scroll
                        $timeout(function () {
                            $location.hash('step' + $scope.currentStep);
                            $anchorScroll();
                        }, 100);
                    });
            }

            $scope.loadHighCharts = function() {
                var unitSettings = getUnitSettings();

                var ppIncidents = [];
                for (var i = 0; i < $scope.incidents.length; i++) {                    
                    var date = new Date($scope.incidents[i].recordedOn + "Z"); // This is GMT
                    ppIncidents.push([date.getTime(),
                        $scope.incidents[i].peakPressure * unitSettings.conversionRate]);
                }

                var ppEvents = [];
                angular.forEach($scope.itemEventSuccesses, function (item, key) {
                    angular.forEach(item, function (itemEvent) {
                        var date = new Date(itemEvent.recordedOn + "Z"); // This is GMT
                        ppEvents.push([date.getTime(),
                            itemEvent.peakPressure * unitSettings.conversionRate]);
                    });
                });
                
                //#region ng-Highcharts Config
                var currentEndDate = new Date(formatUtcForRequest($scope.generalInfo.dateRange.endDate)).getTime() + 86400000;
                var endDate = new Date(currentEndDate);

                var xAxisMin = new Date(formatUtcForRequest($scope.generalInfo.dateRange.startDate)).getTime();
                var xAxisMax = endDate.getTime();
                $scope.chartConfig = {
                    options: {
                        chart: {
                            type: 'scatter',
                            backgroundColor: '#eee',
                            animation: false,
                        },
                        tooltip: {
                            formatter: function () {
                                var result = '<span style="color: ' + this.series.color + '">● </span><span>' + this.series.name + '</span>' + '<br/>' +
                                    Highcharts.dateFormat('%b %e, %Y', this.x) + '<br/>' +
                                    formatTooltip(this.y) + ' <br/>' + 
                                    '';
                                return result;
                            },
                            animation: false,
                        },
                        credits: {
                            enabled: false,
                        }
                    },
                    plotOptions: {
                        series: {
                            animation: false,
                        }
                    },
                    title: {
                        text: $scope.messages.graphTitle.value,
                    },
                    // Axis Setup
                    xAxis: {
                        type: 'datetime',
                        currentMin: xAxisMin,
                        currentMax: xAxisMax,
                        title: {
                            text: $scope.messages.graphXaxis.value,
                        },
                    },
                    yAxis: {
                        currentMin: unitSettings.min,
                        currentMax: unitSettings.max,
                        tickInterval: unitSettings.tickInterval,
                        title: {
                            text: format($scope.messages.graphYaxis.value, unitSettings.unit),
                        },
                        plotBands: [{
                            color: '#e1ece3',
                            from: unitSettings.bandFrom,
                            to: unitSettings.bandTo,
                        }],
                        labels: {
                            formatter: function () {
                                return Highcharts.numberFormat(this.value, 0);
                            }
                        }
                    },
                    // The data
                    series: [
                        {
                            name: $scope.messages.graphSeriesIncidents.value,
                            data: ppIncidents,
                            color: '#db011c',
                            marker: {
                                symbol: 'circle'
                            }
                        },
                        {
                            name: $scope.messages.graphSeriesSuccess.value,
                            data: ppEvents,
                            color: '#555',
                            marker: {
                                symbol: 'triangle'
                            },
                            enableMouseTracking: false,
                            
                        },
                    ],
                };

                //#endregion

                // Fix: highcharts resizing bug. Call window resize after short delay
                $timeout(function () {
                    $(window).resize();
                }, 10);
            }

            $scope.loadMoreIncidents = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }
                // Add another group of items to the collection
                $scope.incidentIndex = createEventCollection($scope.itemEventIncidents, $scope.incidents, $scope.incidentIndex, $scope.MAX_INCIDENT_THRESHOLD);

                if ($scope.incidentIndex == $scope.totalIncidents) {
                    $scope.allIncidentsLoaded = true;
                }
            };

            $scope.showErrorFor = function (field) {
                return $scope.reportForm.$submitted
                    && field.$invalid;
            }

            $scope.cancelReset = function ($event) {
                $event.preventDefault();
            }

            var formatTooltip = function(val) {
                if ($scope.generalInfo.units == $scope.allUnits.bar.id) {
                    return format('{0} {1}',
                        Highcharts.numberFormat(val, 0, '.', ','),
                        $scope.allUnits.bar.description);
                }

                if ($scope.generalInfo.units == $scope.allUnits.psiBar.id) {
                    return format('{0} {1} / {2} {3}',
                        Highcharts.numberFormat(val, 0, '.', ','),
                        $scope.allUnits.psi.description,
                        Highcharts.numberFormat(val * $scope.allUnits.conversionRate, 0, '.', ','),
                        $scope.allUnits.bar.description);
                }

                return format('{0} {1}',
                    Highcharts.numberFormat(val, 0, '.', ','),
                    $scope.allUnits.psi.description);
            }

            var getUnitSettings = function() {
                var psiSettings = {
                    min: 0,
                    max: 10000,
                    tickInterval: 2500,
                    bandFrom: 7151,
                    bandTo: 7982,
                    conversionRate: 1,
                    unit: $scope.allUnits.psi.description
                };

                var psi = $scope.settings.highchart.psi;
                if(psi) {
                    psiSettings.min = psi.min;
                    psiSettings.max = psi.max;
                    psiSettings.tickInterval = psi.tickInterval;
                    psiSettings.bandFrom = psi.from;
                    psiSettings.bandTo = psi.to;
                }

                var barSettings = {
                    min: 0,
                    max: 700,
                    tickInterval: 175,
                    bandFrom: 493,
                    bandTo: 550,
                    conversionRate: $scope.allUnits.conversionRate,
                    unit: $scope.allUnits.bar.description
                };

                var bar = $scope.settings.highchart.bar;
                if(bar) {
                    barSettings.min = bar.min;
                    barSettings.max = bar.max;
                    barSettings.tickInterval = bar.tickInterval;
                    barSettings.bandFrom = bar.from;
                    barSettings.bandTo = bar.to;
                }

                var psiAndBarSettings = {
                    min: psiSettings.min,
                    max: psiSettings.max,
                    tickInterval: psiSettings.tickInterval,
                    bandFrom: psiSettings.from,
                    bandTo: psiSettings.to,
                    conversionRate: 1,
                    unit: $scope.allUnits.psi.description
                };

                if ($scope.generalInfo.units == $scope.allUnits.bar.id) {
                    return barSettings;
                }

                if ($scope.generalInfo.units == $scope.allUnits.psiBar.id) {
                    return psiAndBarSettings;
                }

                return psiSettings;
            };

            function getFormItemIncidents() {
                //IN: 
                //{
                //    1234:[
                //        { id: 1, notes: 'asdf' }
                //    ],
                //    2345:[
                //        { id: 3, notes: 'wer' }
                //    ]
                //};
                //OUT: 
                //[
                //    { id: 1, notes: 'asdf' },
                //    { id: 3, notes: 'wer' }
                //];
                var results = [];
                for (var outer in $scope.itemEventIncidents) {
                    var incidents = $scope.itemEventIncidents[outer];

                    for (var incident in incidents) {
                        results.push(incidents[incident]);
                    }
                }

                return _.filter(results, function (incident) {
                    return incident.notes && _.trim(incident.notes).length > 0;
                });

            }

            function reloadItems() {
                var itemInstanceIds = _.pluck($scope.items, 'itemInstanceId');

                var filters = {
                    beginDate: moment($scope.generalInfo.dateRange.startDate,
                            $scope.datePickerOptions.format)
                        .utc().format('YYYY-MM-DDTHH:mm'),
                    endDate: moment($scope.generalInfo.dateRange.endDate,
                            $scope.datePickerOptions.format)
                        .utc().format('YYYY-MM-DDTHH:mm'),
                    itemInstanceIds: itemInstanceIds,
                    crimperType: $scope.crimperType
                };

                metCrimpers.getCrimpers(filters, function (result) {
                    $scope.items = result.items;
                });
            }

            function createEventCollection(container, events, index, limit) {
                index = index || 0;
                limit = limit || events.length;
                var limitIndex = index + limit;

                while (index < limitIndex && index < events.length) {
                    var event = events[index];
                    if (!container[event['itemInstanceId']]) {
                        container[event['itemInstanceId']] = new Array();
                    }
                    container[event['itemInstanceId']].push(event);

                    index++;
                }

                return index;
            }

            function getTimezone() {
                return metJstz.determine().name();
            }

            //#endregion
            
            //#region Broadcast

            $scope.generateReportInit = function(event, data) {
                // clear
                $scope.resetForm();

                // page properties
                $document.prop('title', $scope.messages.pageTitle.value + ' - ' + $scope.messages.oneKey.value);

                // init data
                $scope.items = data.items;
                $scope.generalInfo.dateRange.startDate = data.startDate;
                $scope.generalInfo.dateRange.endDate = data.endDate;
                $scope.crimperType = data.crimperType;
            };

            $scope.backToSearch = function ($event, clear) {
                if ($event) {
                    $event.preventDefault();
                }
                $scope.resetForm();

                // notify crimper controller
                var data = {
                    clear: clear,
                };

                $location.hash('dashboard');

                $scope.$emit('cancelGenerateReport', data);
            };

            $scope.resetForm = function() {
                $scope.currentStep = 1;
                $scope.reportForm.$setPristine();

                // Set Save buttons back to default
                $scope.pdfSaving = false;

                // We canceled the report and new report parameters could be searched, clear dependant data
                $scope.itemEventSuccesses = null;
                $scope.itemEventIncidents = null;
                $scope.incidents = null;
                $scope.totalIncidents = 0;
                $scope.incidentIndex = 0;
                $scope.allIncidentsLoaded = false;
                $scope.saveCompanyInformationChecked = false;
                resetGeneralInfo();
            }


            // Listener needs to come after callback if it's scoped
            $scope.$on('generateCrimperReport', $scope.generateReportInit);

            function resetGeneralInfo() {
                $scope.generalInfo = angular.copy($scope.emptyGeneralInfo);
                if ($scope.defaultUnit) {
                    $scope.generalInfo.units = $scope.defaultUnit.id;
                }

                // map the original init values to the default values of the form
                mapCompanyInfoToGeneralInfo();
            };

            function mapCompanyInfoToGeneralInfo() {
                $scope.generalInfo.companyName = $scope.companyInfo.companyName;
                $scope.generalInfo.address1 = $scope.companyInfo.address1;
                $scope.generalInfo.address2 = $scope.companyInfo.address2;
                $scope.generalInfo.city = $scope.companyInfo.city;
                $scope.generalInfo.state = $scope.companyInfo.state;
                $scope.generalInfo.zip = $scope.companyInfo.zip;
                $scope.generalInfo.country = $scope.companyInfo.country;
                $scope.generalInfo.phone = $scope.companyInfo.phone;
                $scope.generalInfo.fax = $scope.companyInfo.fax;
                $scope.generalInfo.companyLogo = $scope.companyInfo.logoUrl;
                $scope.generalInfo.imageAlternates = {
                    smallUrl: $scope.companyInfo.logoUrl,
                    mediumUrl: $scope.companyInfo.logoUrl,
                };
            };
            //#endregion

            //#region Lookup

            $scope.getItemInstance = function (id)
            {
                for (var i = 0; i < $scope.items.length; i++)
                {
                    if (id == $scope.items[i].itemInstanceId) {
                        return $scope.items[i];
                    }
                }
                return undefined;
            }

            $scope.getLocalDateTime = function (datetime) {
                return moment(datetime).format($scope.datePickerOptions.format);
            }

            var formatUtcForRequest = function(datetime) {
                return moment(datetime, $scope.datePickerOptions.format).utc().format('YYYY-MM-DDTHH:mm');
            }

            //#endregion

            //#region DateTimePicker
            //$scope.minimumDate = '01/01/2014 12:00 AM';
            $scope.minimumDate = '01/01/1111 12:00 AM'; //min date disabled temporarily

            $scope.datePickerOptions = metDates.getDatePickerOptions();
            $scope.datePickerOptions.minDate = $scope.minimumDate;

            $scope.$watchGroup(['generalInfo.dateRange.startDate', 'generalInfo.dateRange.endDate'],
                function () {
                    resetDateDependentData();
            });

            function resetDateDependentData() {
                $scope.incidents = null;
                $scope.incidentIndex = 0;
                $scope.itemEventIncidents = null;
                $scope.itemEventSuccesses = null;
                $scope.totalIncidents = 0;
                $scope.allIncidentsLoaded = false;

            }

            //#endregion

            //#region Save Company Information

            $scope.canSaveCompanyInformation = function () {
                return !_.isEmpty($scope.generalInfo.companyName)
                    && !_.isEmpty($scope.generalInfo.address1)
                    && !_.isEmpty($scope.generalInfo.city)
                    && !_.isEmpty($scope.generalInfo.state)
                    && !_.isEmpty($scope.generalInfo.zip)
                    && !_.isEmpty($scope.generalInfo.country);
            };

            $scope.saveCompanyInformation = function(event, form) {
                if (!$scope.canSaveCompanyInformation() || !form.$valid) {
                    return;
                }

                if (event != null) {
                    event.preventDefault();
                }

                $scope.savingCompanyInformation = true;

                metCrimpers
                    .saveCompanyInfo($scope.generalInfo)
                    .$promise
                    .then(function(result) {
                        $scope.savingCompanyInformation = false;
                        if (result.isValid) {
                            onSaveCompanyInformationSuccess(event, form);
                        } else {
                            metNotify.error(result.message);
                        }
                    })
                    .catch(function(reason) {
                        $scope.savingCompanyInformation = false;
                        metNotify.error($scope.messages.companyInformationCouldNotBeSaved.value);
                    });
            };
            var mapGeneralInfoToCompanyInfo = function () {
                _.assign($scope.companyInfo, $scope.generalInfo);
                $scope.companyInfo.logoUrl = $scope.generalInfo.companyLogo;
            }
            var onSaveCompanyInformationSuccess = function (event, form) {
                $scope.saveCompanyInformationChecked = false;

                metNotify.success($scope.messages.companyInformationHasBeenSaved.value);

                $scope.changeStep(2, event, form);

                mapGeneralInfoToCompanyInfo();
            };

            $scope.getMinimumDate = function () {
                return ($scope.generalInfo.dateRange.startDate == null || $scope.generalInfo.dateRange.startDate == '') ? $scope.minimumDate: $scope.generalInfo.dateRange.startDate;
            };
            
            //#endregion

            $scope.initialize = function (reportForm) {
                $scope.currentStep = 1;
                $scope.reportForm = reportForm;

                //$scope.allUnits = init.units;
                //$scope.defaultUnit = init.units.psi;
                $scope.allUnits = {
                    psi: { id: '0', description: 'psi' },
                    bar: { id: '1', description: 'bar' },
                    psiBar: { id: '2', description: 'psiBar' }
                };
                $scope.defaultUnit = angular.copy($scope.allUnits.psi);
                getCountries();
                getStates();
                getCompanyInfo();

                resetGeneralInfo();
            };

            //only used because couldnt get jasmine tests to use document - need to clean up 
            $scope.getElement = function(name) {
                return document.querySelector(name);
            };

            function getCompanyInfo(){
                reportingService.getUserProfile()
                    .then(function(data){
                        $scope.companyInfo = data;
                        $scope.companyInfo.imageAlternates = {
                            smallUrl: data.logoUrl,
                            mediumUrl: data.logoUrl,
                            largeUrl: data.logoUrl
                        };
                    });
            }

            function getStates(){
                reportingService.getStates()
                    .then(function(data){
                        $scope.states = data;
                    });
            }

            function getCountries(){
                reportingService.getCountries()
                    .then(function(data){
                        $scope.countries = data;
                    });
            }
        }
    ]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.controller('inventoryReportsController', [
        '$scope', '$window', '$log', '$document', '$timeout', 'localize', 'dates', 'locations', 'people', 'trades', 'categories', 'urls',
        function inventoryReportsCtrl(
            $scope, $window, $log, $document, $timeout, metLocalize, metDates, metLocations, metPeople, metTrades, metCategories, metUrls) {
            $scope.locations = [];
            $scope.persons = [];
            $scope.trades = [];
            $scope.categories = [];

            $scope.selectedLocations = [];
            $scope.selectedPersons = [];
            $scope.selectedTrades = [];
            $scope.selectedCategories = [];

            $scope.isLoading = false;
            $scope.hasError = false;
            $scope.content = {};
            $scope.datePickerOptions = metDates.getDatePickerOptions();
            $scope.timeZone = new jstz.determine().name();
            $scope.request = {
                reportType: undefined,
                start: undefined,
                end: undefined,
                limit: undefined,
                userLocations: [],
                userPersons: [],
                userTrades: [],
                userCategories: [],
                timeZone: $scope.timeZone
            };

            function loadLocations() {
                $scope.locations = [];
                metLocations.getAll({
                    includeUnspecified: false
                },
                    function (data) {
                        $scope.locations = data.items;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    });
            }

            function loadPersons() {
                $scope.persons = [];
                metPeople.getAll({
                    includeUnspecified: false
                },
                    function (data) {
                        $scope.persons = data.items;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    });
            }

            function loadTrades() {
                $scope.trades = [];

                var params = {
                    includeUnspecified: false
                };
                metTrades.getAll(params,
                    function (data) {
                        $scope.trades = data.items;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    });
            }

            function loadCategories() {
                $scope.categories = [];

                var params = {
                    includeUncategorized: false
                };
                metCategories.getAll(params,
                    function (data) {
                        _.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);
                            });
                        });

                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    });
            }

            $scope.totalItemCount = 0;
            $scope.reportsError = false;
            $scope.locationError = false;
            $scope.personError = false;
            $scope.tradeError = false;
            $scope.categoryError = false;

            $scope.locationToggle = "location";
            $scope.personToggle = "person";
            $scope.locationPersonFilter = $scope.locationToggle;
            $scope.showLocationFilter = function () {
                var show = $scope.request.reportType == 1 || ($scope.request.reportType == 2 && $scope.locationPersonFilter == $scope.locationToggle);
                return show;
            }

            $scope.showPersonFilter = function () {
                var show = $scope.request.reportType == 1 || ($scope.request.reportType == 2 && $scope.locationPersonFilter == $scope.personToggle);
                return show;
            }

            $scope.showTradeFilter = function () {
                var show = $scope.request.reportType == 1;
                return show;
            }

            $scope.showCategoryFilter = function () {
                var show = $scope.request.reportType == 1;
                return show;
            }

            $scope.showLocationPersonToggle = function () {
                var show = $scope.request.reportType == 2;
                return show;
            }

            $scope.locationPersonToggleChanged = function (selectedFilter) {
                $scope.locationPersonFilter = selectedFilter;
                $scope.selectedLocations = [];
                $scope.selectedPersons = [];
            }

            var isValid = function () {
                $scope.reportsError = !$scope.request.reportType || !$scope.request.reportType.length;
                return !$scope.reportsError
            };

            $scope.$watch('request.reportType', function () {
                $scope.content.setHtml('');
                $scope.reportsError = null;
                $scope.locationError = null;
                $scope.personError = null;
                $scope.tradeError = null;
                $scope.categoryError = null;
                $scope.request.start = null;
                $scope.selectedLocations = [];
                $scope.selectedPersons = [];
                $scope.selectedTrades = [];
                $scope.selectedCategories = [];
                $scope.request.end = null;
            });

            $scope.generate = function (baseUrl) {
                if (!isValid()) {
                    return;
                }

                var url = baseUrl + "?reportType=" + $scope.request.reportType;

                url += createGenerateArrayParam($scope.selectedLocations, "UserLocations", "placeId");
                url += createGenerateArrayParam($scope.selectedPersons, "UserPersons", "personId");
                url += createGenerateArrayParam($scope.selectedTrades, "UserTrades", "divisionId");
                url += createGenerateArrayParam($scope.selectedCategories, "UserCategories", "categoryId");

                if ($scope.request.start) {
                    url += '&start=' + $scope.request.start;
                } else {
                    url += '&start=';
                }

                if ($scope.request.end) {
                    url += '&end=' + $scope.request.end;
                } else {
                    url += '&end=';
                }

                if ($scope.request.timeZone) {
                    url += '&timeZone=' + $scope.request.timeZone;
                }
                document.cookie = "Authorization=Bearer " + localStorage.getItem('access_token') + ";path=/";
                $window.location.href = url;
            };

            function createGenerateArrayParam(array, paramName, idAttributeName) {
                var queryString = "";
                if (array.length > 0) {
                    var params = "";
                    _.forEach(array, function (selected) {
                        params += "&" + paramName + "=" + selected[idAttributeName];
                    });

                    queryString += params;
                }
                return queryString;
            }

            $scope.$watchGroup([
                'selectedCategories',
                'selectedLocations',
                'selectedPersons',
                'selectedTrades',
                'request.start',
                'request.end'
            ], function () {
                $scope.count();
            });

            var shouldGetCount = function () {
                return !_.isNull($scope.request.reportType) && !_.isUndefined($scope.request.reportType)
                    && ($scope.selectedLocations.length
                        || $scope.selectedCategories.length
                        || $scope.selectedTrades.length
                        || $scope.selectedPersons.length
                        || ($scope.request.start && $scope.request.end));
            };

            var buildReportRequest = function () {
                return {
                    reportType: $scope.request.reportType,
                    start: moment($scope.request.start, $scope.datePickerOptions.format),
                    end: moment($scope.request.end, $scope.datePickerOptions.format),
                    userLocations: _.map($scope.selectedLocations, 'placeId'),
                    userPersons: _.map($scope.selectedPersons, 'personId'),
                    userTrades: _.map($scope.selectedTrades, 'divisionId'),
                    userCategories: _.map($scope.selectedCategories, 'categoryId')
                };
            };

            $scope.count = function () {
                if (shouldGetCount()) {
                    $.ajax({
                        beforeSend: function (request) {
                            request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
                        },
                        url: metUrls('baseApiUrl').concat('/reports/count'),
                        type: 'POST',
                        data: JSON.stringify(buildReportRequest()),
                        contentType: 'application/json'
                    }).done(function (response) {
                        $scope.totalItemCount = response.itemCount;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    }).error(function (error) {
                        if (error.status == 401) {
                            return;
                        }
                    }).fail(function () {
                        console.log('Failed to load item count');
                    });
                } else {
                    $scope.totalItemCount = 0;
                }
            };

            $scope.preview = function () {
                if (!isValid()) {
                    return;
                }

                $scope.isLoading = true;
                $scope.hasError = false;

                $scope.request.userLocations = [];
                $scope.request.userPersons = [];
                $scope.request.userTrades = [];
                $scope.request.userCategories = [];
                _.forEach($scope.selectedLocations, function (selectedLoc) {
                    $scope.request.userLocations.push(selectedLoc.placeId.toString());
                });
                _.forEach($scope.selectedPersons, function (selectedPerson) {
                    $scope.request.userPersons.push(selectedPerson.personId.toString());
                });
                _.forEach($scope.selectedTrades, function (selectedTrade) {
                    $scope.request.userTrades.push(selectedTrade.divisionId.toString());
                });
                _.forEach($scope.selectedCategories, function (selectedCategory) {
                    $scope.request.userCategories.push(selectedCategory.categoryId.toString());
                });
                document.cookie = "Authorization=Bearer " + localStorage.getItem('access_token') + ";path=/";

                $.ajax({
                    beforeSend: function (request) {
                        request.setRequestHeader('Authorization', 'Bearer ' + localStorage.getItem('access_token'));
                    },
                    type: 'GET',
                    url: metUrls('inventoryReportsPreview'),
                    contentType: "application/json",
                    data: $scope.request,
                    traditional: true,
                    success: function (result) {
                        $scope.content.setHtml(result);
                        $scope.isLoading = false;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);
                    },
                    error: function (error) {
                        $scope.content.setHtml('');
                        $scope.isLoading = false;
                        $scope.hasError = true;
                        setTimeout(function () {
                            $scope.$apply();
                        }, 0);

                        if (error.status === 401) {
                            return;
                        }
                    }
                });
            };

            $scope.initialize = function () {
                loadLocations();
                loadPersons();
                loadTrades();
                loadCategories();
                $('#ajax-loading').remove();
                $scope.transferFrom = localStorage.getItem('transferFrom');
            };
        }
    ]);
}());
(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.directive('metCrimperSummary', [
        '$compile', '$parse', 'localize',
        function ($compile, $parse, metLocalize) {
            return {
                restrict: 'E',
                replace: true,
                require: 'ngModel',
                templateUrl: '/OneKeyScripts/app/reports/metCrimperSummary.directive.html',
                scope: { },
                link: function (scope, element, attrs, ngModel) {
                    scope.messages = {
                        totalCycles: metLocalize('fieldNames', 'totalCycles'),
                        fullPressureCycles: metLocalize('fieldNames', 'fullPressureCycles'),
                        fullPressureRate: metLocalize('fieldNames', 'fullPressureRate')
                    };
                    scope.totalEvents = 0;
                    scope.successfulEvents = 0;

                    ngModel.$render = function() {
                        var items = ngModel.$viewValue;

                        scope.totalEvents = _.sum(items, 'totalEventCount');
                        scope.successfulEvents = _.sum(items, 'successfulEventCount');

                        scope.successRate = formatSuccessRate();
                    }

                    var formatSuccessRate = function() {
                        if (scope.totalEvents == 0) {
                            return "--";
                        }
                        var rounded = (scope.successfulEvents * 100.0 / scope.totalEvents)
                            .toFixed(2);
                        if (rounded == '100.00') {
                            return '100%';
                        }
                        return rounded + '%';
                    }
                }
            };
        }
    ]);
}());

