(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('locations', ['$resource', 'urls', function ($resource, metUrls) {

        var api = $resource(metUrls('placeApi').concat('/:placeId'),
            {
                placeId: '@placeId'
            },
            {
                'update': { method: 'PUT' },
                'query': { method: 'GET', isArray: false },
                'search': {
                    method: 'GET',
                    url: metUrls('placeApi').concat('/search')
                },
                'migrate': {
                    method: 'POST',
                    isArray: true,
                    url: metUrls('placeApi').concat('/migrate')
                },
                'counts': {
                    method: 'GET',
                    url: metUrls('placeApi').concat('/counts')
                }
            }
        );

        return {
            getAll: function (options, success, error) {
                return api.query(options, success, error);
            },
            getLocation: function (placeId, success, error) {
                return api.get({ placeId: placeId }, success, error);
            },
            update: function (location, success, error) {
                return api.update(location, success, error);
            },
            create: function (location, success, error) {
                return api.save(location, success, error);
            },
            remove: function (location, success, error) {
                return api.remove({ placeId: location.placeId }, success, error);
            },
            search: function (placeFilters, successCallback, errorCallback) {
                return api.search(
                    placeFilters,
                    successCallback,
                    errorCallback
                );
            },
            migrate: function (migrateRequest, successCallback, errorCallback) {
                return api.migrate(
                    migrateRequest,
                    successCallback,
                    errorCallback
                );
            },
            counts: function(successCallback, errorCallback) {
                return api.counts(successCallback, errorCallback);
            }
        };
    }]);
}());

(function () {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('trades', ['$resource', 'urls', function ($resource, metUrls) {

        var resource = $resource(metUrls('tradeApi').concat('/:divisionId'),
            {
                divisionId: '@divisionId'
            },
            {
                'update': { method: 'PUT' },
                'query': { method: 'GET', isArray: false }
            }
        );

        return {
            getAll: function (options, success, error) {
                return resource.query(options, success, error);
            },
            getTrade: function (tradeId, success, error) {
                return resource.get({ tradeId: tradeId }, success, error);
            },
            update: function (trade, success, error) {
                return resource.update(trade, success, error);
            },
            create: function (trade, success, error) {
                return resource.save(trade, success, error);
            },
            remove: function (trade, success, error) {
                return resource.remove({ divisionId: trade.divisionId }, success, error);
            }
        };
    }]);
}());

(function() {
    'use strict';

    var oneKeyApp = angular.module('oneKeyApp');

    oneKeyApp.service('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('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.directive('metReportContent', function () {
        return {
            restrict: 'A',
            replace: true,
            scope: {
                content: '='
            },
            link: function (scope, element, attrs) {
                scope.content.setHtml = function (html) {
                    element.html(html);
                }

                var offsetTop = element.offset().top;
                $(window).scroll(function () {
                    var window_top = $(window).scrollTop();
                    var header = element.find('.report-location-header');
                    var width = header.context.offsetWidth;
                    if (window_top > offsetTop) {
                        header.addClass('stick-to-top');
                        header.css('width', width);
                    } else {
                        header.removeClass('stick-to-top');
                    }
                });
            }
        };
    });
}());

(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.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');
            };
        }
    ]);
}());
