(function () {

'use strict';

    angular
        .module('web.shared.api')
        .service('apiErrorHandler', ApiErrorHandler);

    function ApiErrorHandler() {
        var displayError = angular.noop;
        var promptLogin = angular.noop;

        this.onErrorMessage = function (callback) {
            displayError = callback;
            return this;
        }

        this.onLoginRequired = function (callback) {
            promptLogin = callback;
            return this;
        }

        this.handle = function (response, status, headers) {
            if (status == 401 || status == 403) {
                promptLogin(status);
            }

            var message;
            var contentType = headers('Content-Type');
            if (contentType && contentType.indexOf('html') > -1) {
                var title = response.match('<title>([^<]+)</title>');
                if (title) {
                    message = title[1];
                }
            } else {
                while (response.innerException) {
                    response = response.innerException;
                }

                message = response.exceptionMessage || response.message || response;
            }

            message = message || "An unknown error has occurred.";

            console.error(message);
            displayError(message);

            return message;
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.api')
        .provider('apiFactory', ApiFactory);

    function ApiFactory() {

        this.defaultRootUrl = '';
        this.customHeaders = undefined;

        $$get.$inject = ['$http', '$q', '$rootScope', 'apiPathBuilder', 'apiErrorHandler'];
        function $$get ($http, $q, $rootScope, apiPathBuilder, apiErrorHandler) {
            var defaultRootUrl = this.defaultRootUrl;
            var customHeaders = this.customHeaders;

            $rootScope.pendingCalls = 0;

            function callUsingPromise(config) {
                $rootScope.pendingCalls++;

                if (customHeaders) {
                    config.headers = customHeaders;
                }

                var task = $q.defer();
                $http(config).
                    success(function (data, status, headers, request) {
                        task.resolve(data);
                        $rootScope.pendingCalls--;
                    }).
                    error(function (data, status, headers, request) {
                        apiErrorHandler.handle(data, status, headers, request);
                        task.reject(data);
                        $rootScope.pendingCalls--;
                    });

                return task.promise;
            };

            return {
                Instance: function(rootUrl) {
                    rootUrl = rootUrl || defaultRootUrl;

                    var methods = ['JSONP', 'DELETE', 'GET', 'HEAD'],
                        dataMethods = ['PUT', 'POST'];

                    var api = {};

                    for (var m = methods.length; m--;) {
                        (function(method) {
                            api[method.toLowerCase()] = function(path, params) {
                                var config = {
                                    method: method,
                                    url: apiPathBuilder.applyParams(rootUrl + (path || ''), params)
                                };
                                return callUsingPromise(config);
                            };
                        })(methods[m]);
                    }

                    for (m = dataMethods.length; m--;) {
                        (function(method) {
                            api[method.toLowerCase()] = function(path, params, data) {
                                var config = {
                                    method: method,
                                    url: apiPathBuilder.applyParams(rootUrl + (path || ''), params),
                                    data: data
                                };
                                return callUsingPromise(config);
                            };
                        })(dataMethods[m]);
                    }

                    return api;
                }
            };
        }

        this.$get = $$get;
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.api')
        .service('apiPathBuilder', ApiPathBuilder);

    function ApiPathBuilder() {
        this.applyParams = function (url, params) {
            var i, pathArgs = [], segment, segments = url.split(/\W/);
            for (i = segments.length; i--;) {
                segment = segments[i];

                if (!segment) continue;
                if (new RegExp("^\\d+$").test(segment)) continue;
                if (!new RegExp("(^|[^\\\\]):" + segment + "(\\W|$)").test(url)) continue;

                pathArgs.push(segment);
            }

            url = url.replace(/\\:/g, ':');

            var arg, val, encodedVal;
            for (i = pathArgs.length; i--;) {
                arg = pathArgs[i];
                val = params[arg];

                if (val != undefined) {
                    encodedVal = encodeURIComponent(val)
                        .replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',')
                        .replace(/%20/g, '%20').replace(/%26/gi, '&').replace(/%3D/gi, '=').replace(/%2B/gi, '+');
                }

                url = url.replace(new RegExp(":" + arg + "(\\W|$)", "g"), (encodedVal || '') + "$1");
            }

            url = url.replace(/\/+$/, '').replace(/\/\.(?=\w+($|\?))/, '.').replace(/\/\\\./, '/.');

            var key, value, seperator, qString = "";
            for (key in params) {
                value = params[key];
                if (value != undefined && pathArgs.indexOf(key) == -1) {
                    seperator = qString ? '&' : '?';
                    qString += seperator + key + '=' + encodeURIComponent(value);
                }
            }

            url += qString;

            return url;
        };
    };

})();
(function() {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('bool', Constructor);

    function Constructor() {
        return function (value, onTrue, onFalse, onUndefined) {
            if (value == true) {
                if (onTrue != undefined) {
                    return onTrue;
                } else {
                    return "Yes";
                }
            } else if (value == false) {
                if (onFalse != undefined) {
                    return onFalse;
                } else {
                    return "No";
                }
            } else {
                if (onUndefined != undefined) {
                    return onUndefined;
                } else {
                    return "N/A";
                }
            }
        };
    };

})();
(function () {

    'use strict';

    angular
        .module('web.shared.filters')
        .filter('clipLeft', Constructor);

    function Constructor() {
        return function (value, clipValue) {
            if (!value || value.substring(0, clipValue.length) !== clipValue) {
                return value;
            }

            return value.substring(clipValue.length);
        };
    };

})();
(function () {

    'use strict';

    angular
        .module('web.shared.filters')
        .filter('clipRight', Constructor);

    function Constructor() {
        return function (value, clipValue) {
            if (!value || value.substring(value.length - clipValue.length) !== clipValue) {
                return value;
            }

            return value.substring(0, value.length - clipValue.length);
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('distinct', Constructor);

    function Constructor() {
        return function (list) {
            return _.uniq(list);
        }
    };

})();
(function() {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('fromNow', Constructor);

    function Constructor() {
        return function (value) {
            if (value == undefined) {
                return value;
            }

            return moment(value).fromNow();
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('mailMerge', Constructor);

    function Constructor() {
        return function (text, fields) {
            if (!text || !fields) return undefined;

            var merged = text;
            var field, oldValue, newValue;
            for (var i = 0; i < fields.length; i++) {
                field = fields[i];
                oldValue = '[[' + field.key + ']]';
                newValue = field.formatString && field
                    ? field.formatString.format(field.value)
                    : field.value;

                merged = merged.replaceAll(oldValue, newValue);
            }

            return merged;
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('money', Constructor);

    function Constructor() {
        return function (input, decimalPlaces, symbol) {
            if (isNaN(input)) return input;
            symbol = symbol != undefined ? symbol : '$';
            var factor = "1" + Array(+(decimalPlaces > 0 && decimalPlaces + 1)).join("0");
            var number = (Math.round(input * factor) / factor).toString();
            return symbol + number.replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('percentage', Constructor);

    function Constructor() {
        return function (input, decimalPlaces, suffix) {
            if (isNaN(input)) return input;
            decimalPlaces = angular.isNumber(decimalPlaces) ? decimalPlaces : 2;
            suffix = suffix != undefined ? suffix : '%';
            return Math.round(input * Math.pow(10, decimalPlaces + 2)) / Math.pow(10, decimalPlaces) + suffix;
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('phone', Constructor);

    function Constructor() {
        return function (tel) {
            if (!tel) { return ''; }

            var value = tel.toString().replace(/[\-\(\) ]/g, '');

            if (value.match(/[^0-9]/)) {
                return tel;
            }

            var countryCode, areaCode, number;

            switch (value.length) {
                case 10: // +1PPP####### -> C (PPP) ###-####
                    countryCode = 1;
                    areaCode = value.slice(0, 3);
                    number = value.slice(3);
                    break;

                case 11: // +CPPP####### -> CCC (PP) ###-####
                    countryCode = value[0];
                    areaCode = value.slice(1, 4);
                    number = value.slice(4);
                    break;

                case 12: // +CCCPP####### -> CCC (PP) ###-####
                    countryCode = value.slice(0, 3);
                    areaCode = value.slice(3, 5);
                    number = value.slice(5);
                    break;

                default:
                    return tel;
            }

            if (countryCode == 1) {
                countryCode = "";
            }

            number = number.slice(0, 3) + '-' + number.slice(3);

            return (countryCode + " (" + areaCode + ") " + number).trim();
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('property', Constructor);

    function Constructor() {
        function tunnel(rootObject, propertyArray) {
            var value = rootObject;

            angular.forEach(propertyArray, function (property) {
                value = value[property];
            });

            return value;
        }

        return function (array, propertyName, propertyValue) {
            if (array == undefined || array.length == 0 ||
                propertyName == undefined || propertyValue == undefined) {
                return array;
            }

            if (propertyName.match(/\./)) {
                var propertyLayers = propertyName.split('.');
                return _.filter(array, function (item) {
                    return angular.equals(tunnel(item, propertyLayers), propertyValue);
                });
            } else {
                return _.filter(array, function (item) {
                    return angular.equals(item[propertyName], propertyValue);
                });
            }
        }
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('range', Constructor);

    function Constructor() {
        return function (input, total) {
            total = parseInt(total);
            for (var i = 0; i < total; i++)
                input.push(i);
            return input;
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('sort', Constructor);

    function Constructor() {
        return function (list) {
            return _.sortBy(list, function (item) { return item; });
        }
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('subset', Constructor);

    function Constructor() {
        return function (array, skip, take) {
            skip = skip || 0;
            take = take || 0;

            return _(array)
			.chain()
			.rest(skip)
			.first(take || array.length - skip)
			.value();
        }
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('truncate', Constructor);

    function Constructor() {
        return function (text, length, end) {
            if (text == undefined) {
                return '';
            }

            end = end || "...";
            length = length || 10;

            return text.length <= length || text.length - end.length <= length ? text : String(text).substring(0, length - end.length) + end;
        };
    };

})();
(function () {

'use strict';

    angular
        .module('web.shared.filters')
        .filter('zeroless', Constructor);

    function Constructor() {
        return function (value, replacement) {
            if (value > 0) {
                return value;
            } else {
                if (replacement != undefined) {
                    return replacement;
                } else {
                    return "-";
                }
            }
        };
    };

})();
(function() {
    'use strict';

    angular
        .module('web.shared')
        .controller('legacyForm', LegacyForm);

    LegacyForm.$inject = ['$scope', 'LEGACY_URL', '$uibModal'];

    function LegacyForm($scope, LEGACY_URL, $uibModal) {
        $scope.launch = function () {
            //window.dialog(LEGACY_URL + $scope.legacyPath, $scope.formTitle, 700, 700);

            $uibModal.open({
                windowTemplateUrl: 'app/shared/legacyForm/legacyFormModal.html',
                title: $scope.formTitle,
                template: '<iframe width="700" height="600" style="border: 0; overflow-x: scroll;" ng-src="' + LEGACY_URL + $scope.legacyPath + '"></iframe>',
                size: '700'
            });

        }
    };

})();
(function() {
    'use strict';

    angular
        .module('web.shared')
        .directive('legacyForm', LegacyForm);

    LegacyForm.$inject = [];

    function LegacyForm() {
        return {
            restrict: 'E',
            replace: true,
            controller: 'legacyForm',
            templateUrl: 'app/shared/legacyForm/legacyForm.html',
            scope: {
                formTitle: '@',
                legacyPath: '@',
                buttonText: '@'
            }
        };
    };

})();
(function() {
    'use strict';

    angular
        .module('web.shared')
        .controller('modalWindow', ModalWindow);

    ModalWindow.$inject = ['$scope', 'modalOptions'];

    function ModalWindow($scope, modalOptions) {
        $scope.options = modalOptions;
    };

})();
(function() {
    'use strict';

    angular
        .module('web.shared')
        .service('modalWindow', ModalWindow);

    ModalWindow.$inject = ['$uibModal'];

    function ModalWindow($uibModal) {
        this.open = function(options) {
            $uibModal.open({
                animation: true,
                windowTemplate: '',
                controller: 'modalWindow',
                template: options.body,
                size: options.size,
                resolve: {
                    modalOptions: function() {
                        return options;
                    }
                }
            });
        }
    };

})();
