/* Minification failed. Returning unminified contents.
(3287,93-94): run-time error JS1195: Expected expression: >
(3287,136-137): run-time error JS1004: Expected ';': )
(3288,26-27): run-time error JS1195: Expected expression: )
(3294,59-60): run-time error JS1195: Expected expression: >
(3294,114-115): run-time error JS1004: Expected ';': )
(3297,59-60): run-time error JS1195: Expected expression: >
(3297,133-134): run-time error JS1004: Expected ';': )
(3300,65-66): run-time error JS1004: Expected ';': {
(3302,18-19): run-time error JS1195: Expected expression: )
(3306,30-31): run-time error JS1004: Expected ';': {
(3308,10-11): run-time error JS1195: Expected expression: )
(3314,12-13): run-time error JS1195: Expected expression: )
(3314,14-15): run-time error JS1004: Expected ';': {
(3440,99-100): run-time error JS1195: Expected expression: >
(3440,136-137): run-time error JS1004: Expected ';': )
(3443,15-19): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(3450,13-14): run-time error JS1002: Syntax error: }
(3453,39-40): run-time error JS1004: Expected ';': {
(3570,6-7): run-time error JS1002: Syntax error: }
(3574,12-13): run-time error JS1195: Expected expression: )
(3574,14-15): run-time error JS1004: Expected ';': {
(3615,2-3): run-time error JS1195: Expected expression: )
(3615,6-7): run-time error JS1197: Too many errors. The file might not be a JavaScript file: ;
(3454,50-56): run-time error JS1018: 'return' statement outside of function: return
 */
var app = angular.module("app-hd", [

    //"ngAnimate", // animations"ngSanitize",
    "ngSanitize", // sanitizes html bindings (ex: sidebar.js)
    "ngCookies",
    //"ngLocale",
    "ngMessages",
    // 3rd Party Modules
    "LocalStorageModule", // module required for authentication
    "common", // common functions, logger, spinner
    "ui.router", // angulars state router
    "angular-cache",
    "ngFileUpload",
    'ui.bootstrap',
    "ui.utils.masks",
    "uiGmapgoogle-maps",
    "angularFileUpload",
    "ngclipboard"
]);

function getBaseURL() {
    var fullsite = window.location.pathname;
    var prts = fullsite.split("/");
    if (prts.length > 0) fullsite = prts[1];
    var proto = fullsite.indexOf("https") >= 0 ? 'https://' : 'http://';
    return proto + window.location.host + "/";
}

function getBaseWithController() {
    var fullsite = window.location.pathname;
    var prts = fullsite.split("/");
    if (prts.length > 0) fullsite = prts[1];
    var proto = fullsite.indexOf("https") >= 0 ? 'https://' : 'http://';
    return proto + window.location.host + "/" + fullsite + "/";
}

app.constant("ngAuthSettings", {
    apiServiceBaseUri: getBaseWithController(),
    baseUri: getBaseURL(),
    clientId: "ngAuthApp",
    cdnBaseUrl: "https://oberweis.b-cdn.net"
});

angular.isValue = function (val) {
    return !(val === null || !angular.isDefined(val) || (angular.isNumber(val) && !isFinite(val)));
};

app.config([
    "$httpProvider", function ($httpProvider) {

        if (!$httpProvider.defaults.headers.get) {
            $httpProvider.defaults.headers.get = {};
        }
        //disable IE ajax request caching
        $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT';
        // extra
        $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache';
        $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
        
        $httpProvider.interceptors.push("smcCustomerRedirectInterceptor");

        $httpProvider.interceptors.push("authInterceptorService");
    }]);

app.run([

    "$rootScope", "$cookies", '$state', function ($rootScope, $cookies, $state, authService) {
        //
        //	when app is in mobile mode this closes the
        //	bootstrap menu once a selection is made
        //

        // for simulatiing when a browser hits page for first time uncomment the following line
        // localStorage.clear();

        //for debugging routing problems un comment the two functions below and watch for
        //either to be activated
        //$rootScope.$on('$stateChangeError',
        //    function (event, toState, toParams, fromState, fromParams, error) {
        //        var xs = 2;
        //    });

        //$rootScope.$on('$stateNotFound', function (event, unfoundState, fromState, fromParams) {
        //    console.log(unfoundState.to); // "lazy.state"
        //    console.log(unfoundState.toParams); // {a:1, b:2}
        //    console.log(unfoundState.options); // {inherit:false} + default options
        //});
    }]);

app.run([
    "$rootScope", "$location", "$cookies", "authService", function ($rootScope, $location, $cookies, authService) {
        $rootScope.idenity = [{ email: "" }];
        $rootScope.imageBasePath = "";
        authService.fillAuthData();

        $rootScope.salesPerson = {
            id: null,
            name: null,
            message: null,
            invalid: null,
            tempId: null
        };

        $rootScope.$watch(function () {
            return $location;
        }, function (value) {
            var url = new URL(value.absUrl());
            var sid = url.searchParams.get("sid");
            if (!sid) {
                sid = url.searchParams.get("salesId");
            }
            //var c = $cookies.get("salesId");
            if (sid != null) {
                var expireDate = new Date();
                expireDate.setDate(expireDate.getDate() + 14);
                $cookies.put("salesId", sid, { 'expires': expireDate });
                $location.search("sid", null);
                $location.search("salesId", null);
            }
        });
    }
]);;
(function () {
    var app = angular.module('app-hd');

    // Configure Toastr
    //toastr.options.timeOut = 4000;
    //toastr.options.positionClass = 'toast-bottom-right';

    var keyCodes = {
        backspace: 8,
        tab: 9,
        enter: 13,
        esc: 27,
        space: 32,
        pageup: 33,
        pagedown: 34,
        end: 35,
        home: 36,
        left: 37,
        up: 38,
        right: 39,
        down: 40,
        insert: 45,
        del: 46
    };

    function getSiteName() {
        var fullsite = window.location.pathname;

        var prts = fullsite.split('/');
        if (prts.length > 0) {
            fullsite = prts[1];
        }

        return fullsite + '/';
    }

    var imageCategory = {
        basePath: 'https://oberweis.b-cdn.net/assets/images/categories/',
        noImageFile: 'noimg.png'
    };

    var events = {
        controllerActivateSuccess: 'controller.activateSuccess',
        spinnerToggle: 'spinner.toggle'
    };

    var config = {
        appErrorPrefix: '[Ober Error] ', //Configure the exceptionHandler decorator
        docTitle: 'Oberweis: ',
        events: events,
        baseUrl: getSiteName(),
        localStorageCacheOff: false,
        defaultCategory: 'featured',
        keyCodes: keyCodes,
        imageCategory: imageCategory,
        version: '0.0.1',
        paymentServiceErrorMessage: 'We were unable to make a connection. Please refresh the page and try again.'
    };

    app.value('config', config);

    app.config([
        '$logProvider', function ($logProvider) {
            // turn debugging off/on (no info or warn)
            $logProvider.debugEnabled(false);
        }
    ]);

    //#region Configure the common services via commonConfig
    app.config([

        'commonConfigProvider', function (cfg) {
            cfg.config.controllerActivateSuccessEvent = config.events.controllerActivateSuccess;
            cfg.config.spinnerToggleEvent = config.events.spinnerToggle;
        }

    ]);

    app.config([
         '$compileProvider', function ($compileProvider) {
             //configure routeProvider as usual
             $compileProvider.debugInfoEnabled(false);
         }
    ]);

    app.config([
         'uiGmapGoogleMapApiProvider', function (uiGmapGoogleMapApiProvider) {
             uiGmapGoogleMapApiProvider.configure({
                 //    key: 'your api key',
                 //v: '3.20', //defaults to latest 3.X anyhow
                 client: 'gme-oberweisdairyinc',
                 libraries: 'places,drawing,'
             });
         }]);
})();;
(function () {
    "use strict";

    var app = angular.module("app-hd");

    app.run(['$rootScope', '$state', '$window', '$location', 'authService', 'common', 'config', function ($rootScope, $state, $window, $location, authService, common, config) {
        //
        //	this adds a check before a page routing occurs to see if you should be
        //	logged in to visit that page.  If user should be logged on and is not
        //	they are redirected to login page.  This was moved from app
        //
        $rootScope.$on('$locationChangeSuccess', function () {
            //this logic will hadle the old links containing '#'
            if ($window.location.hash.indexOf('#/') > -1) {
                $window.location.href = decodeURIComponent($window.location.href.replace('#/', '/'));
            }
            if ($window.location.hash.indexOf('#%2F') > -1) {
                $window.location.href = decodeURIComponent($window.location.href.replace('#%2F', '/'));
            }


            $rootScope.actualLocation = $location.path();
        });
        $rootScope.$watch(function () { return $location.path() }, function (newLocation, oldLocation) {
            if ($rootScope.actualLocation === newLocation && newLocation != '/shopping/cart') {
                common.$broadcast("browserBack", { show: false });
            }
        });

        $rootScope.$on("$stateChangeStart", function (event, toState, toParams) {
            //  This section redirects based on user not being authenticated
            if ($rootScope.processing == true) return;
            else $rootScope.processing = true;
            var requireLogin = toState.data.requireLogin;
            var isAuth = authService.authentication.isAuth;
            common.cntlCount = 0;
            if (requireLogin && !isAuth) {
                event.preventDefault();
                var paramStr = angular.toJson(toParams);
                $rootScope.processing = false;
                $state.go("sign-in", {
                    rqst: toState.name,
                    rqstParams: paramStr
                });
                return;
            }

            if (toState.data.salesPersonAdding) {
                $rootScope.salesPersonAdding = true;
            }

            $rootScope.processing = false;

            var fromState = $state.current.name.toLowerCase();

            var fullsite = "" + window.location;

            if (fullsite.indexOf('/category') > 0) {

                if (toState.name != fromState) {
                    common.scrollToPosition = $(document).scrollTop();
                }
                else {
                    common.scrollToPosition = 0;
                }
            }
        });

        $rootScope.$on("$viewContentLoaded", function (event, toState, toParams, fromState, fromParams) {
            window.scrollTo(0, 0);
            common.$broadcast(config.events.spinnerToggle, { show: false });
        });

    }]);

    app.config([
        '$injector', '$stateProvider', '$urlMatcherFactoryProvider', '$urlRouterProvider', '$locationProvider',
        function ($injector, $stateProvider, $urlMatcherFactoryProvider, $urlRouterProvider, $locationProvider) {

            // split the url on the hash to get the route
            //var route = window.location.hash.split('#')[1]
            //if (route != null) {
            //    $urlRouterProvider.otherwise(function ($injector, $location) {
            //        // split the url on the hash to get the route
            //        var badRoute = [];
            //        var url = '';
            //        badRoute = window.location.hash.split('/');
            //        if (badRoute.length > 0) {
            //            url = location.origin + '/error/' + badRoute[badRoute.length - 1];
            //        }
            //        else {
            //            url = location.origin + '/error/unknown';
            //        }
            //        // Navigates the user to the error page and captures the bad route data
            //        location.href = url;
            //        return;
            //    });
            //}
            $locationProvider.html5Mode(true);

            $urlMatcherFactoryProvider.caseInsensitive(true);
            $urlMatcherFactoryProvider.strictMode(true);
            $urlMatcherFactoryProvider.strictMode(false);
            $stateProvider
                .state("retail", {
                    url: "/grocery-stores/products",
                    data: {
                        requireLogin: false
                    },
                    templateUrl: "app/hd/views/retail-browsing.html" + appVersion,
                    controller: "productCatalogRetailController as vm"
                })
                .state("retail.browsing", {
                    url: "/:category",
                    views: {
                        "" : {
                            templateUrl: "app/hd/views/retail-category.html" + appVersion
                        }
                    }
                })
                .state("retail.product", {
                    url: "/product/:id",
                    views: {
                        "": {
                            templateUrl: "app/hd/views/retail-product-page.html" + appVersion,
                            controller: "productDetailRetailController as vm"
                        }
                    }
                })
                .state("dairy-stores", {
                    url: "/dairy-stores/products",
                    data: {
                        requireLogin: false
                    },
                    templateUrl: "app/hd/views/dairy-store-browsing.html" + appVersion,
                    controller: "productCatalogDairyStoreController as vm"
                })
                .state("dairy-stores.browsing", {
                    url: "/:category",
                    views: {
                        "": {
                            templateUrl: "app/hd/views/dairy-store-category.html" + appVersion
                        }
                    }
                })
                .state("dairy-stores.product", {
                    url: "/product/:id",
                    views: {
                        "": {
                            templateUrl: "app/hd/views/dairy-store-product-page.html" + appVersion,
                            controller: "productDetailDairyStoreController as vm"
                        }
                    }
                })
                .state("curator", {
                    url: "/home-delivery/curator-agreement",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/curator/curator-agreement.html" + appVersion,
                        }
                    }
                })
                .state("curator-confirmation", {
                    url: "/home-delivery/curator-confirmation",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/curator/curator-agreement-confirmation.html" + appVersion,
                        }
                    }
                })
                .state("sign-in", {
                    url: "",
                    templateUrl: "app/hd/views/home-delivery-sign-in.html" + appVersion,
                    controller: "authenticationController as vm",
                    params: {
                        rqst: null,
                        rqstParams: null
                    },

                    data: {
                        requireLogin: false
                    }
                })
                .state("sign-in2", {
                    url: "/home-delivery/log-in?action",
                    templateUrl: "app/hd/views/home-delivery-sign-in.html" + appVersion,
                    controller: "authenticationController as vm",

                    data: {
                        requireLogin: false
                    }
                })
                .state("sign-in3", {
                    url: "/home-delivery/log-in/",
                    templateUrl: "app/hd/views/home-delivery-sign-in.html" + appVersion,
                    controller: "authenticationController as vm",

                    data: {
                        requireLogin: false
                    }
                })
                .state("sign-in-error", {
                    url: "/home-delivery/log-in?error",
                    templateUrl: "app/hd/views/home-delivery-sign-in.html" + appVersion,
                    controller: "authenticationController as vm",

                    data: {
                        requireLogin: false
                    }
                })
                // browse i.e. shopping without being logged in
                .state("browsing", {
                    url: "/home-delivery/browsing",
                    abstract: false,
                    data: {
                        requireLogin: false
                    },

                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-browsing.html" + appVersion
                        },
                    }
                })
                .state("browsing.recipes", {
                    url: "/recipe",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/recipe/recipe-catalog.html" + appVersion,
                            controller: "recipeCatalogController as recipeCatalogCtrl"
                        }
                    }
                })
                .state("browsing.recipes.recipe", {
                    url: "/:id",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/recipe/recipe-detail.html" + appVersion,
                            controller: "recipeDetailController as recipeDetailCtrl"
                        }
                    }
                })
                .state("browsing.categorycollections", {
                    url: "/category/:productViewId",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        }
                    }
                })
                .state("browsing.collection", {
                    url: "/collection/:id",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/collections/collection-detail.html" + appVersion,
                            controller: "collectionDetailController as vm"
                        }
                    }
                })
                .state("shopping.categorycollections", {
                    url: "/category/:productViewId",
                    data: {
                        requireLogin: true
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                            controller: "productCatalogController as vm"
                        }
                    }
                })
                .state("shopping.collection", {
                    url: "/collection/:id",
                    data: {
                        requireLogin: true
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/collections/collection-detail.html" + appVersion,
                            controller: "collectionDetailController as vm"
                        }
                    }
                })
                .state("browsing.product", {
                    url: "/product/:id",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-product-page.html" + appVersion,
                            controller: "productDetailController as vm"
                        }
                    }
                })
                .state("browsing.category", {
                    url: "/category/:productViewId/:subViewId",

                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@browsing.category': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                            //templateUrl: "app/hd/views/shopping-category-products-grid2.html",
                        },
                    }
                })
                .state("browsing.categorynoparm", {
                    url: "/category",
                    data: {
                        requireLogin: false
                    },

                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@browsing.category': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                        },
                    }
                })
                .state("sales2", {
                    url: "/sales/:salesId",
                    data: {
                        requireLogin: false,
                        salesPersonAdding: true,
                    },
                    views: {
                        '': {
                            template: "<div ui-view></div>",
                            controller: "signupBaseController as vm",
                        },
                    }
                })
                .state("sales", {
                    url: "/home-delivery/sales?salesId",
                    data: {
                        requireLogin: false,
                        salesPersonAdding: true,
                    },
                    views: {
                        '': {
                            template: "<div ui-view></div>",
                            controller: "signupBaseController as vm",
                        },
                    }
                })
                .state("sales.1", {
                    //url: "",
                    url: '?promo&salesAdding',
                    views: {
                        '': {
                            templateUrl: "app/hd/views/home-delivery-sign-up.html" + appVersion,

                            controller: "availabilityController as vm"
                        }
                    }
                })
                .state("sign-up", {
                    url: "/home-delivery/sign-up",
                    abstract: true,
                    data: {
                        requireLogin: false,
                    },
                    views: {
                        '': {
                            template: "<div ui-view></div>",
                            controller: "signupBaseController as vm",
                        },
                    }
                })
                .state("sign-upwithPromo", {
                    url: "/sign-up-promo?promo",
                    data: {
                        requireLogin: false,
                    },
                    views: {
                        '': {
                            template: "<div ui-view></div>",
                            controller: "signupBaseController as vm",
                        },
                    }
                })
                .state("sign-up22", {
                    url: 'sign-up?promo&salesAdding&acct',
                    views: {
                        '': {
                            templateUrl: "app/hd/views/home-delivery-sign-up.html" + appVersion,
                            controller: "availabilityController as vm"
                        }
                    }
                })
                .state("sign-up.1", {
                    //url: "",
                    url: '?promo&salesAdding&address1&address2&zip&emailAddress&acct&sid&curator',
                    views: {
                        '': {
                            templateUrl: "app/hd/views/home-delivery-sign-up.html" + appVersion,
                            controller: "availabilityController as vm"
                        }
                    }
                })
                //.state("sign-up.salesId", {
                //    url: "/:salesId",
                //    views: {
                //        '': {
                //            templateUrl: "app/hd/views/home-delivery-sign-up.html",
                //            controller: "availabilityController as vm"
                //        },
                //    }
                //})
                .state("sign-up.2", {
                    abstract: true,
                    url: "/shopping",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping.html" + appVersion,
                            controller: "productCatalogController as vm",
                        },
                    }
                })
                .state("sign-up.2.account-help", {
                    url: "/account-help",
                    templateUrl: 'app/hd/views/shopping-account-help.html' + appVersion,
                    data: {
                        requireLogin: false
                    }
                })

                //TODO: review whether we can do this a different way and not have to repeat all of the shopping states twice (one for new customer and one for sales rep new customer)
                .state("sign-up.2.product", {
                    url: "/product/:id",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-product-page.html" + appVersion,
                            controller: "productDetailController as vm"
                        }
                    }
                })

                .state("sign-up.2.category", {
                    url: "/category/:productViewId/:subViewId",
                    abstract: false,
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@sign-up.2.category': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                            //templateUrl: "app/hd/views/shopping-category-products-loadGridDirective.html",
                        },
                    }
                })
                .state("sign-up.2.categoryNoparm", {
                    url: "/category",
                    abstract: false,
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@sign-up.2': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                            //templateUrl: "app/hd/views/shopping-category-products-loadGridDirective.html",
                        },
                    }
                })
                .state("sign-up.2.cart", {
                    url: "/cart",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-cart.html" + appVersion,
                        },
                    }
                })
                .state("sign-up.3", {
                    url: "/shopping-checkout-delivery-date",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-delivery-date.html" + appVersion,
                            controller: "deliveryDateController as vm"
                        }
                    }
                })
                .state("sign-up.5", {
                    url: "/shopping-checkout",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout.html" + appVersion,
                            controller: "contactInfoController as vm"
                        }
                    }
                })
                .state("sign-up.99", {
                    url: "/shopping-checkout",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout.html" + appVersion,
                            controller: "contactInfoController as vm"
                        }
                    }
                })
                .state("sign-up.4", {
                    url: "/shopping-checkout-porch-box",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-porch-box.html" + appVersion,
                            controller: "porchBoxController as vm"
                        }
                    }
                })
                .state("sign-up.6", {
                    url: "/shopping-checkout-payment-info?order_id&response_code&secondary_response_code&response_code_text",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-payment-info.html" + appVersion,
                            controller: "paymentController_signup as vm"
                        }
                    }
                })
                .state("sign-up.7", {
                    url: "/shopping-checkout-place-order",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-place-order.html" + appVersion,
                            controller: "placeOrderController as vm"
                        }
                    }
                })
                .state("sign-up.8", {
                    url: "/shopping-checkout-confirmation",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-confirmation.html" + appVersion,
                        }
                    }
                })
                .state("sign-up.101", {
                    url: "/shopping-checkout-curator-agreement",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/curator/curator-agreement.html" + appVersion,
                        }
                    }
                })
                .state("sign-up.error", {
                    url: "/shopping-checkout-error",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-checkout-error.html" + appVersion,
                        }
                    }
                })
                .state("sign-up.9", {
                    url: "/shopping-checkout-user-lookup/:cid",
                    data: {
                        requireLogin: false
                    },
                    templateUrl: "app/hd/views/user-lookup/shopping-checkout-user-lookup.html" + appVersion,
                    controller: "lookUpAccountController as vm"
                })
                .state("sign-up.10", {
                    url: "/shopping-checkout-user",
                    data: {
                        requireLogin: false
                    },
                    templateUrl: "app/hd/views/user-lookup/shopping-checkout-user.html" + appVersion,
                    controller: "lookUpAccountController as vm"
                })
                .state("shopping", {
                    url: "/home-delivery/shopping",
                    abstract: false,
                    data: {
                        requireLogin: true
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping.html" + appVersion,
                            controller: "productCatalogController as vm",
                        },
                    }
                })
                .state("shopping.referral", {
                    url: "/referral",
                    templateUrl: "app/hd/views/shopping-referral.html" + appVersion,
                    controller: "referralController",
                    data: {
                        requireLogin: true
                    }
                })
                .state("shopping.referral.tab", {
                    url: "/:tabName",
                    templateUrl: "app/hd/views/shopping-referral-tab.html" + appVersion,
                    data: {
                        requireLogin: true
                    },
                    controller: function($scope, $stateParams) {
                        $scope.tabName = $stateParams.tabName;
                    }
                })
                .state("shopping.recipes", {
                    url: "/recipe",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/recipe/recipe-catalog.html" + appVersion,
                            controller: "recipeCatalogController as recipeCatalogCtrl"
                        }
                    }
                })
                .state("shopping.recipes.recipe", {
                    url: "/:id",
                    params: {
                        id: null
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/recipe/recipe-detail.html" + appVersion,
                            controller: "recipeDetailController as recipeDetailCtrl"
                        }
                    }
                })
                .state("shopping.product", {
                    url: "/product/:id",
                    params: {
                        id: null
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-product-page.html" + appVersion,
                            controller: "productDetailController as vm"
                        }
                    }
                })
                .state("shopping.category", {
                    url: "/category/:productViewId/:subViewId",
                    params: {
                        productViewId: null,
                        subViewId:null
                    },
                    data: {
                        requireLogin: true
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@shopping.category': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                            // templateUrl: "shopping-category-products-loadGridDirective.html"
                        },
                    }
                })
                .state("shopping.categorynoparm", {
                    url: "/category",
                    data: {
                        requireLogin: false
                    },
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-category.html" + appVersion,
                        },
                        'bottomRow@shopping.category': {
                            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion,
                            //templateUrl: "app/hd/views/shopping-category-products-loadGridDirective.html",
                        },
                    }
                })
                .state("shopping.cart", {
                    url: "/cart",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-cart.html" + appVersion,
                        },
                    }
                })
                .state("shopping.order-change", {
                    url: "/order-change",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-order-change.html" + appVersion,
                        },
                    }
                })
                .state("shopping.account", {
                    url: "/account/:tab?order_id&response_code&secondary_response_code&response_code_text",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/shopping-account.html" + appVersion,
                            controller: "accountController as vm"
                        }
                    }
                })
                .state("shopping.account-help", {
                    url: "/account-help",
                    templateUrl: 'app/hd/views/shopping-account-help.html' + appVersion,
                    data: {
                        requireLogin: false
                    }
                })
                .state("shopping.tips", {
                    url: "/tips",
                    templateUrl: 'app/hd/views/shopping-tips.html' + appVersion,
                    data: {
                        requireLogin: false
                    }
                })
                .state("shopping.subscription", {
                    url: "/subscription/:id",
                    templateUrl: "app/hd/views/subscription/subscription-offers.html" + appVersion,
                    data: {
                        requireLogin: true
                    }
                })
                .state("shopping.mySubscriptions", {
                    url: "/mySubscriptions",
                    templateUrl: "app/views/account-tabs/subscriptions.html" + appVersion,
                    data: {
                        requireLogin: true
                    }
                })
                .state("shopping.claimEGiftCard", {
                    url: "/egift/:claimCode",
                    templateUrl: "app/hd/views/eGiftCard/customer-gift-card-add-to-account.html" + appVersion,
                    data: {
                        requireLogin: true
                    }
                })
                .state("shopping.product-help", {
                    url: "/product-help",
                    templateUrl: 'app/hd/views/shopping-product-help.html' + appVersion,
                    data: {
                        requireLogin: false
                    }
                })
                .state("shopping.payments", {
                    url: "/payments",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/payments.html" + appVersion
                        }
                    }
                })
                .state("shopping.myHistory", {
                    url: "/myHistory",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/myHistory.html" + appVersion
                        }
                    }
                })
                .state("shopping.myHistoryOrder", {
                    url: "/myHistoryOrder/:id",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/MyHistoryOrderDetail.html" + appVersion
                        }
                    }
                })
                .state("shopping.Suspend", {
                    url: "/Suspend",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/Suspend.html" + appVersion
                        }
                    }
                })
                .state("shopping.myAccount", {
                    url: "/myAccount",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/MyAccount.html" + appVersion
                        }
                    }
                })
                .state("shopping.detail", {
                    url: "/detail/:id",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/productsdetail.html" + appVersion
                        }
                    }
                })
                .state("shopping.all", {
                    url: "/all/:search",
                    views: {
                        'columnTwo@shopping': {
                            templateUrl: "app/views/ProductCatalog/productThumbslist.html" + appVersion
                        },
                    },
                })
                .state("find-a-store", {
                    url: "/search/find-a-store",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/find-a-store.html" + appVersion,
                            controller: "findStoreController as vm"
                        }
                    },
                    data: {
                        requireLogin: false
                    }
                })
                .state("find-a-grocery-store", {
                    url: "/grocery-stores/find-a-store",
                    views: {
                        '': {
                            templateUrl: "app/hd/views/find-a-store.html" + appVersion,
                            controller: "findStoreController as vm"
                        }
                    },
                    data: {
                        requireLogin: false,
                        retail: true
                    }
                })
                .state("shopping.tutorial", {
                    url: "/tutorial",
                    templateUrl: "app/hd/views/tutorial.html" + appVersion, //,
                    data: {
                        requireLogin: false
                    }
                })
                .state("shopping.deliveryFeedback", {
                    url: "/delivery-feedback",
                    templateUrl: "app/hd/views/deliveryFeedback.html" + appVersion, //,
                    data: {
                        requireLogin: true
                    }
                })
                .state("home", {
                    url: "/",
                    data: {
                        requireLogin: false
                    },
                    onEnter: function () {
                        // Navigate the user back to the homepage
                        var urlOrigination = location.origin;
                        window.location = urlOrigination;
                        return;
                    }
                });
        }]);
})();
;
(function () {
    "use strict";

    // Define the common module
    // Contains services:
    //  - common
    //  - logger
    //  - spinner
    var commonModule = angular.module("common", []);

    // Must configure the common service and set its
    // events via the commonConfigProvider
    commonModule.provider("commonConfig", function () {
        this.config = {
            // These are the properties we need to set
            //controllerActivateSuccessEvent: '',
            //spinnerToggleEvent: ''
        };

        this.$get = function () {
            return {
                config: this.config
            };
        };
    });

    commonModule.factory("common",
        ["datacontext", "$q", "$http", "$rootScope", "$timeout", "$filter", "$cookies", "commonConfig", "logger", common]);

    function common(datacontext, $q, $http, $rootScope, $timeout, $filter, $cookies, commonConfig, logger) {
        var throttles = {};
        var service = {
            dc: datacontext,
            // common angular dependencies
            $broadcast: $broadcast,
            $q: $q,
            $http: $http,
            $timeout: $timeout,

            // generic
            activateController: activateController,
            createSearchThrottle: createSearchThrottle,
            debouncedThrottle: debouncedThrottle,
            getDollars: getDollars,
            getCents: getCents,
            isNumber: isNumber,
            logger: logger, // for accessibility
            possibleDates: possibleDates,
            isHoliday: isHoliday,
            availableDay: availableDay,
            textContains: textContains,
            cntlCount: 0,
            validateForm: validateForm,
            validator: validator,
            validateCustomerNumber: validateCustomerNumber,
            handleError: handleError,
            preventBrowserBack: preventBrowserBack,
            setCustomerSettingsCookie: setCustomerSettingsCookie,
            getCustomerSettingsCookie: getCustomerSettingsCookie,
            getSeoMetadata: getSeoMetadata,
            getCDNBaseImageUrl: getCDNBaseImageUrl,
            getServerDateTime: getServerDateTime,
            disableBrowserBack: disableBrowserBack,
            includePaymentScripts: includePaymentScripts,
            getImageVersion: getImageVersion,
            insertLinkTrack: insertLinkTrack,
        }

        return service;

        //function activateController(promises, controllerId) {
        //    return $q.all(promises).then(function (eventArgs) {
        //        var data = { controllerId: controllerId };
        //        $broadcast(commonConfig.config.controllerActivateSuccessEvent, data);
        //    });
        //}

        function includePaymentScripts() {
            const node = document.createElement('script');
            node.src = '/scripts/site/chaseJS.js'
            node.type = 'text/javascript';
            document.getElementsByTagName('head')[0].appendChild(node);
        }


        function disableBrowserBack() {
            function disableBack() { window.history.forward() }
            window.onload = disableBack();
            window.onpageshow = function (evt) { if (evt.persisted) disableBack() };
        }
        function insertLinkTrack(insertType) {

            var brandingLinkTracker = {
                Id : 0,
                LinkType : insertType,
                LinkSource : null,
                LogDate : null
            };

            var self = this;
            var defer = $q.defer();

            var url = 'api/baseApi/UpdateBrandingTracking';
            self.$http.post(url, brandingLinkTracker).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            }
            
        }

        function getSeoMetadata(id, typeId) {
            var self = this;
            var defer = $q.defer();

            var url = 'api/baseApi/GetSeoMetaData/' + id + '/' + typeId;

            self.$http.get(url).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            }
        }
        var imageBaseUrl = null;

        function getCDNBaseImageUrl() {
            var self = this;
            var defer = $q.defer();
            if (self.imageBaseUrl) {
                return self.$q.when(self.imageBaseUrl);
            }
            var url = 'api/baseApi/GetCDNImageBaseURL';
            self.$http.get(url).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                imageBaseUrl = data;
                defer.resolve(data);
            }
        }
        function getImageVersion() {
            var self = this;
            var defer = $q.defer();
            var url = 'api/baseApi/GetImageVersion';
            self.$http.get(url).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            }
        }
        function setCustomerSettingsCookie(setting, value, expireDays) {
            var currentObj = getCustomerSettingsCookie();

            currentObj[setting] = value;

            var now = new Date();

            var exp = new Date(now.getFullYear(), now.getMonth(), now.getDate() + expireDays);

            $cookies.putObject('customerSettings', currentObj, {
                expires: exp
            });
        }

        function getCustomerSettingsCookie() {
            var obj = $cookies.get('customerSettings');

            if (obj == null || obj == undefined) {
                obj = "{}";
            }
            return JSON.parse(obj);
        }

        function activateController(promises, controllerId) {
            service.cntlCount++;
            if (promises.length == 0) {
                var data = { controllerId: controllerId };
                $broadcast(commonConfig.config.controllerActivateSuccessEvent, data);
            }

            return $q.all(promises).then(function (eventArgs) {
                var data = { controllerId: controllerId };
                if (data.controllerId != "homeDeliveryController")
                    $broadcast(commonConfig.config.controllerActivateSuccessEvent, data);
            });
        }

        function preventBrowserBack() {
            history.pushState(null, null, document.URL);
            window.addEventListener('popstate', function () {
                history.pushState(null, null, document.URL);
            });
        }

        function handleError(error) {
            var msg = '';

            if (error.length > 0) {
                msg = error[0];
            } else {
                msg = 'There was a problem with the request.';
            }

            return msg;
        }

        function $broadcast() {
            //return undefined;

            $rootScope.$broadcast.apply($rootScope, arguments);
        }

        function createSearchThrottle(viewmodel, list, filteredList, filter, delay) {
            // After a delay, search a viewmodel's list using
            // a filter function, and return a filteredList.

            // custom delay or use default
            delay = +delay || 300;
            // if only vm and list parameters were passed, set others by naming convention
            if (!filteredList) {
                // assuming list is named sessions, filteredList is filteredSessions
                filteredList = "filtered" + list[0].toUpperCase() + list.substr(1).toLowerCase(); // string
                // filter function is named sessionFilter
                filter = list + "Filter"; // function in string form
            }

            // create the filtering function we will call from here
            var filterFn = function () {
                // translates to ...
                // vm.filteredSessions
                //      = vm.sessions.filter(function(item( { returns vm.sessionFilter (item) } );
                viewmodel[filteredList] = viewmodel[list].filter(function (item) {
                    return viewmodel[filter](item);
                });
            };

            return (function () {
                // Wrapped in outer IFFE so we can use closure
                // over filterInputTimeout which references the timeout
                var filterInputTimeout;

                // return what becomes the 'applyFilter' function in the controller
                return function (searchNow) {
                    if (filterInputTimeout) {
                        $timeout.cancel(filterInputTimeout);
                        filterInputTimeout = null;
                    }
                    if (searchNow || !delay) {
                        filterFn();
                    } else {
                        filterInputTimeout = $timeout(filterFn, delay);
                    }
                };
            })();
        }

        function debouncedThrottle(key, callback, delay, immediate) {
            // Perform some action (callback) after a delay.
            // Track the callback by key, so if the same callback
            // is issued again, restart the delay.

            var defaultDelay = 1000;
            delay = delay || defaultDelay;
            if (throttles[key]) {
                $timeout.cancel(throttles[key], false);
                throttles[key] = undefined;
            }
            if (immediate) {
                callback();
            } else {
                throttles[key] = $timeout(callback, delay, false);
            }
        }

        function isNumber(val) {
            // negative or positive
            return /^[-]?\d+$/.test(val);
        }

        function textContains(text, searchText) {
            return text && -1 !== text.toLowerCase().indexOf(searchText.toLowerCase());
        }
        function getDollars(n) {
            if (!n) {
                n = 0;
            }
            if (!isFinite(n)) {
                n = 0;
            }

            return Math.floor(n);
        }

        function getCents(n) {

            if (!n) {
                n = 0;
            }
            if (!isFinite(n)) {
                n = 0;
            }
            var c = Math.round((n - getDollars(n)) * 100);
            if (c < 10)
                c = "0" + c;

            return c;
        }

        /*
         * Add days functionality
         */
        function addDays(days) {
            var someDate = new Date();
            var numberOfDaysToAdd = days;
            someDate.setDate(someDate.getDate() + numberOfDaysToAdd);
            return someDate;
        }

        /*
         * Calculates the next available delivery date using the normal delivery day for your region
         */
        function calculateNextDeliveryDate(deliveryDay) {
            var weekday = new Array(7);
            weekday[0] = "sun";
            weekday[1] = "mon";
            weekday[2] = "tue";
            weekday[3] = "wed";
            weekday[4] = "thu";
            weekday[5] = "fri";
            weekday[6] = "sat";

            var currentDate = new Date(getServerDateTime());
            var cutoffDate = new Date(datacontext.cust.mycust.branchCutoff);

            var shortDateName = deliveryDay.toLowerCase();

            var idx = 1;
            if (cutoffDate < currentDate) {
                //skip toworrow if cutoffDate has past to ensure it's not currently just past the cutoff by minutes/hours
                idx = 2;
            }

            for (idx; idx < 9; idx++) {
                var currentDateAddedDays = new Date(currentDate);
                currentDateAddedDays.setDate(currentDate.getDate() + idx);

                var firstAvailDelDay = currentDateAddedDays.getDay();
                if (shortDateName == weekday[firstAvailDelDay]) {
                    return currentDateAddedDays;
                }
            }
        }
        function getServerDateTime() {
            var serverDate;

            $.ajax({
                type: 'GET',
                cache: false,
                async: false,
                url: 'api/Customers/GetServerDateTime',
                success: function (result) {
                    serverDate = new Date(result);
                }
            });

            return serverDate;
        }

        function possibleDates(n, nextDeliveryDate, deliveryDay, eow) {

            //first determine next possible delivery date
            var date = moment(calculateNextDeliveryDate(deliveryDay));
            //var date = moment(nextDeliveryDate);
            var dates = [];
            var i = 0;
            eow = eow ? eow : 0;

            if ((!datacontext.cust.mycust.serviceStartDate && datacontext.cust.mycust.serviceStartDate > datacontext.cust.mycust.branchCutoff)) {
                datacontext.cust.mycust.branchCutoff = datacontext.cust.mycust.serviceStartDate;
            }

            while (i < n) {
                if (availableDay(date, eow)) {
                    var d = moment(date).toDate();

                    if (new Date(d) > new Date(datacontext.cust.mycust.branchCutoff)) {
                        dates.push({ value: d, text: $filter('date')(d, 'M/d/yyyy') });
                        i++;
                    }
                }
                date = date.add(7, 'days');
            }

            return dates;
        }

        function availableDay(dt, eow) {
            if (isHoliday(dt)) {
                return false;
            }

            if (eow != 0) {
                var even = dt.week() % 2 == 0;
                return (eow == 1 && even) || (eow == 2 && !even);
            }
            return true;
        }

        //	//Determine if date is a Holiday
        function isHoliday(dt) {
            // Christmas is 12/25 every year
            if (dt.month() == 11 && dt.date() == 25) {
                return true;
            }

            // Thanksgiving is the 4th Thursday of November every year
            if (dt.month() == 10) {
                var nTh = 4; // Fourth
                var nTargetDay = 4; // Thursday
                var nTargetMonth = 10; // November
                var nTargetYear = dt.year();

                var nEarliestDate = (1 + (7 * (nTh - 1)));

                var dtEarliestDate = moment(new Date(nTargetYear, nTargetMonth, nEarliestDate));
                var nWeekday = dtEarliestDate.day();

                var nOffset = 0;

                if (nTargetDay == nWeekday) {
                    nOffset = 0;
                } else {
                    if (nTargetDay < nWeekday) {
                        nOffset = nTargetDay + (7 - nWeekday);
                    } else {
                        nOffset = (nTargetDay + (7 - nWeekday)) - 7;
                    }
                }

                var dtHolidayDate = moment(new Date(nTargetYear, nTargetMonth, nEarliestDate + nOffset));
                if (dt.startOf('day').isSame(dtHolidayDate)) {
                    return true;
                }
            }

            // Not a holiday
            return false;
        };

        function validateForm(formId) {
            var $form = $(formId);

            $form.validate({
                errorClass: 'customErrorClass',
            });
            return $form.valid();
        }

        function validator(formId) {
            var $form = $(formId);

            var validator = $form.validate();

            return validator;
        }

        function validateCustomerNumber(customerNumber) {
            if (customerNumber === 0) {
                window.location.href = "/";
            }
        }
    }
})();;
(function () {
    angular.module('common').factory('logger', ['$log', logger]);

    function logger($log) {
        var service = {
            getLogFn: getLogFn,
            log: log,
            logError: logError,
            logSuccess: logSuccess,
            logWarning: logWarning
        };

        return service;

        function getLogFn(moduleId, fnName) {
            fnName = fnName || 'log';
            switch (fnName.toLowerCase()) { // convert aliases
                case 'success':
                    fnName = 'logSuccess'; break;
                case 'error':
                    fnName = 'logError'; break;
                case 'warn':
                    fnName = 'logWarning'; break;
                case 'warning':
                    fnName = 'logWarning'; break;
            }

            var logFn = service[fnName] || service.log;
            return function (msg, data, showToast) {
                logFn(msg, data, moduleId, (showToast === undefined) ? true : showToast);
            };
        }

        function log(Message, data, source, showToast) {
            logIt(Message, data, source, showToast, 'info');
        }

        function logWarning(Message, data, source, showToast) {
            logIt(Message, data, source, showToast, 'warning');
        }

        function logSuccess(Message, data, source, showToast) {
            logIt(Message, data, source, showToast, 'success');
        }

        function logError(Message, data, source, showToast) {
            logIt(Message, data, source, showToast, 'error');
        }

        function logIt(Message, data, source, showToast, toastType) {
            var write = (toastType === 'error') ? $log.error : $log.log;
            source = source ? '[' + source + '] ' : '';
            write(source, Message, data);
            //if (showToast) {
            //    if (toastType === 'error') {
            //        toastr.error(Message);
            //    } else if (toastType === 'warning') {
            //        toastr.warning(Message);
            //    } else if (toastType === 'success') {
            //        toastr.success(Message);
            //    } else {
            //        toastr.info(Message);
            //    }
            //}
        }
    }
})();;
(function () {
    "use strict";

    var controllerId = "accountController";
    angular.module("app-hd").controller(controllerId,
        ["$scope", "$http", "$location", "$state", "$cookies", "config", "common", "datacontext", 'authService', accountController]);

    function accountController($scope, $http, $location, $state, $cookies, config, common, datacontext, authService) {
        //alert('test')
        var vm = this;
        vm.baseUrl = config.baseUrl;
        vm.updatePhone = false;
        vm.phoneError = false;
        vm.updateEmail = false;
        vm.canSubmit = true;
        vm.checkedValue = false;
        vm.updateUser = false;
        vm.userError = false;

        $scope.$watch(function () { return datacontext.cust.mycust }, function () {
            vm.customer = datacontext.cust.mycust;
        });
        vm.customerDC = datacontext.cust;
        // vm.custOriginalPhone = '';
        // vm.custOriginalEmail = '';

        vm.paymentsummaryPagingData =
            {
                itemsPerPage: 5,
                currentPage: 0,
                items: []
            };
        vm.historyPagingData =
            {
                itemsPerPage: 5,
                currentPage: 0,
                items: []
            };
        vm.subscriptionPagingData =
        {
            itemsPerPage: 10,
            currentPage: 0,
            items: []
            };

        vm.registration =
            {
                aspID: "", //stuser",
                passwordResetToken: "", //"testuser",
                userName: authService.authentication.userName,
                phoneNumber: "",
                email: "",
                //questionGuess: "",
                newPassword: "",
                //userQuestion: "",
                result: "",
                message: ""
            };

        vm.products = datacontext.products.entityData;
        vm.ChangeSecurityQandAMessage = "";
        vm.ChangeSecurityQandAError = "";
        vm.GetStandingDeliveryTotals = _getStandingDeliveryTotals;
        vm.passwordChangeErrorMessage = "";
        vm.passwordChangeSuccessMessage = "";
        vm.Error = "";
        vm.changeState = $scope.$parent.vm.changeState;

        $scope.form = {};

        vm.validate = function () {
            vm.passwordChangeErrorMessage = "";
            if ($scope.form.passform.newPassword.$touched && $scope.form.passform.newPasswordConfirmed.$touched) {
                if (vm.registration.newPassword != vm.registration.newPasswordConfirmed) {
                    vm.passwordChangeSuccessMessage = "";
                    vm.passwordChangeErrorMessage = "New password and confirmation password do not match.";
                }
            }

            if (vm.passwordChangeErrorMessage) {
                return false;
            }
            return true;
        };

        //vm.ChangePasswordCancel = function () {
        //    vm.registration.password =
        //        vm.registration.newPassword =
        //        vm.registration.newPasswordConfirmed = "";
        //};

        vm.ChangePassword = function () {
            if (common.validateForm("#passform") && vm.validate()) {

                authService.changePassword(vm.registration).then(
                    function (response) {
                        vm.passwordChangeErrorMessage = "";
                        vm.passwordChangeSuccessMessage = "The password was changed successfully.";
                        vm.registration.newPassword = '';
                        vm.registration.newPasswordConfirmed = '';
                        vm.registration.password = '';

                        $cookies.remove("loginData");
                    }, function (error) {
                        vm.passwordChangeErrorMessage = common.handleError(error);
                    });
            }
        };

        vm.ChangeCustomerEmail = function () {
            vm.custOriginalEmail = vm.customer.eMail;
            $http.post("api/customers/UpdateCustomerEmail", '"' + datacontext.cust.mycust.eMail + '"')
                .success(function (response) {
                    vm.updateEmail = false;
                    datacontext.cust.mycust.eMail = response;
                    console.log("Email address has been updated");
                })
                .error(function (data, status, headers, config) {
                    console.log("error changing email");
                    vm.updateEmail = false;
                });
            return;
        };
        vm.clearReminderCheckboxes = function () {
            vm.customer.emailPreferences.smsDeliveryReminders = false;
            vm.customer.emailPreferences.deliveryReminders = false;
        }
        vm.clearDeliveryNotifCheckboxes = function () {
            vm.customer.emailPreferences.smsDeliveryNotifications = false;
            vm.customer.emailPreferences.postDeliveryNotifications = false;
        }
        vm.clearReminderNoneButton = function () {
            vm.customer.emailPreferences.reminderNone = false;
        }
        vm.clearNotifNoneButton = function () {
            vm.customer.emailPreferences.deliveryNone = false;
        }
        vm.UpdateInfo = function () {
            vm.userPassword = "";
            vm.updatePhone = true;
            vm.updateEmail = true;
        }

        vm.SaveChanges = function () {
            if (common.validateForm("#phoneNumber") && common.validateForm("#emailAddress")) {
                vm.ChangeCustomerPhone();
                vm.ChangeCustomerEmail();
            }
        }
        vm.CancelChanges = function () {
            vm.CancelCustomerPhoneChange();
            vm.CancelCustomerEmailChange();
        }

        vm.ChangeCustomerPhone = function () {
            var newPhoneNumber = angular.element('#newphone').val();
            $http.post("api/customers/UpdateCustomerPhone", '"' + newPhoneNumber + '"')
                .success(function (response) {
                    vm.custOriginalPhoneView = angular.element('#newphone').val();;
                    datacontext.cust.mycust.phone = response;
                    vm.updatePhone = false;
                    vm.phoneError = false;
                })
                .error(function (error) {
                    vm.updatePhone = true;
                    vm.phoneError = true;
                    vm.customer.phone = vm.custOriginalPhoneView;
                });
            return;
        };

        vm.CancelCustomerPhoneChange = function () {
            vm.custOriginalPhoneView = (typeof vm.customer.phone === "string") ? vm.customer.phone : vm.customer.phoneNumber;
            vm.updatePhone = false;
            vm.phoneError = false;
            return;
        };
        vm.CancelCustomerEmailChange = function () {
            vm.customer.eMail = vm.custOriginalEmail;
            vm.updateEmail = false;
            return;
        };

        vm.SaveChangeUser = function () {
            vm.userChangeErrorMessage = "";
            vm.userChangeSuccessMessage = "";
            if (common.validateForm("#user-form")) {
                var user = {
                    userId: vm.customer.aspNetUserId,
                    newUsername: vm.userOriginalName,
                    username: vm.customer.userName,
                    password: vm.userPassword,
                    custId: vm.customer.id
                }
                $http.post("api/account/UpdateUserName", user)
                    .success(function (response) {
                        vm.customer.userName = datacontext.cust.mycust.userName = vm.userOriginalName;
                        vm.userPassword = "";
                        vm.userOriginalName = "";
                        vm.updateUser = false;
                        vm.userError = false;
                        vm.userChangeSuccessMessage = "Your Username has been updated.";
                        $cookies.remove("loginData");
                    })
                    .error(function (error) {
                        vm.updateUser = true;
                        vm.userError = true;
                        vm.customer.phone = vm.custOriginalPhoneView;
                        vm.userChangeErrorMessage = common.handleError(error);
                    });
                return;
            }
        };

        vm.CancelChangeUser = function () {
            vm.userPassword = "";
            vm.userOriginalName = "";
            vm.userChangeErrorMessage = "";
            vm.userChangeSuccessMessage = "";
            //vm.userOriginalName = vm.customer.userName;
            vm.updateUser = false;
            vm.userError = false;
            return;
        };

        vm.UpdateUserInfo = function () {
            vm.userPassword = "";
            vm.userOriginalName = "";
            vm.userChangeErrorMessage = "";
            vm.userChangeSuccessMessage = "";
            vm.updateUser = true;
            vm.userError = true;
        }


        vm.UpdatePrefs = function () {
            $http.post("api/customers/UpdateEmailPrefs", datacontext.cust.mycust)

                .success(function (response) {
                    alert("Preferences have been updated");
                })
                .error(function (data, status, headers, config) {
                    alert("Preferences failed to updated. Please try again or contact customer service.");
                });

            return;
        };



        //vm.ChangeSecurityQandA = function () {
        //    vm.updatePhone = false; //

        //    $http.post("api/account/SetMyQuestion", vm.registration)

        //        .success(function (response) {
        //            datacontext.cust.mycust = response;
        //            vm.ChangeSecurityQandAMessage = "Security question & answer has been updated.";
        //        })
        //        .error(function (data, status, headers, config) {
        //            vm.ChangeSecurityQandAError = "Security question has not been updated";
        //        });

        //    return;
        //};

        $scope.Message = "";

        vm.showDetailsModal = false;
        vm.showDetail = function (h) {
            //console.log(h);
            vm.selectedDetail = h;
            vm.showDetailsModal = true;
        }

        //function LoadQuestionData() {
        //    return $http.get("api/Account/GetPasswordResetToken")
        //        .success(function (data) {
        //            vm.registration.userQuestion = data.securityQuestion;
        //        })
        //        .error(function (data, status, headers, config) {
        //            vm.Message = data;
        //        });
        //};

        vm.range = function (itemPagingData) {
            var rangeSize = 5;
            var ret = [];
            var start;
            if ((itemPagingData.items.length / itemPagingData.itemsPerPage) < rangeSize) rangeSize = Math.ceil(itemPagingData.items.length / itemPagingData.itemsPerPage);

            start = itemPagingData.currentPage;
            if (start > vm.pageCount(itemPagingData) - rangeSize) {
                start = vm.pageCount(itemPagingData) - rangeSize + 1;
            }

            for (var i = start; i < start + rangeSize; i++) {
                ret.push(i);
            }
            return ret;
        };

        vm.currentItems = function (itemPagingData) {
            return vm.offset(
                itemPagingData.items,
                itemPagingData.currentPage
                * itemPagingData.itemsPerPage);
        }

        vm.offset = function (input, start) {
            start = parseInt(start, 10);
            return input.slice(start);
        };

        vm.gotoFirst = function (itemPagingData) {
            vm.setPage(0, itemPagingData);

        };

        vm.prevPageDisabled = function (itemPagingData) {
            return itemPagingData.currentPage === 0 ? "disabled" : "";
        };

        vm.pageCount = function (itemPagingData) {
            return Math.ceil(itemPagingData.items.length / itemPagingData.itemsPerPage) - 1;
        };

        vm.gotoLast = function (itemPagingData) {
            vm.setPage(vm.pageCount(itemPagingData), itemPagingData);

        };

        vm.nextPageDisabled = function (itemPagingData) {
            return itemPagingData.currentPage === vm.pageCount(itemPagingData) || (itemPagingData.items.length == 0) ? "disabled" : "";
        };

        vm.setPage = function (n, itemPagingData) {
            itemPagingData.currentPage = n;
        };

        // Standing delivery items
        vm.standingDelivery = function (item) {
            return item && item.standingQuantity && item.standingQuantity > 0;
        };

        // The user has elected to change their standing order
        vm.changeStandingOrder = function () {
            // Assumes the user is authenticated and isn't an incomplete startup
            location.href = '/home-delivery/shopping/cart';
        };

        function _getStandingDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.standingTotals) ? datacontext.order.orderTotals.standingTotals : 0;
        }

        $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
            var target = $(e.target).attr("aria-controls") // activated tab
            vm.activeTab = target;
            $state.go('shopping.account', { tab: target }, { notify: false });
        });

        vm.activeTab = "contact-info";

        $scope.getPaymentHistory = function () {
            vm.paymentsummaryPagingData.items = [];
            datacontext.cust.paymentsummary.forEach(function (item) {
                vm.paymentsummaryPagingData.items.push(item);
            });
        }

        vm.toggleAutoRenew = function (id) {
            $http.post("api/subscription/ToggleSubscriptionAutoRenew/" + id )
                .success(function (response) {
                    console.log("Auto Renew was updated");
                })
                .error(function (data, status, headers, config) {
                });
        };

        activate();
        function activate() {
            //
            //	this code will run only once throughout the sign up of a new customer
            //
            if ($state.params.tab) {
                vm.activeTab = $state.params.tab;
            }

            common.activateController([
                datacontext.order.getOrderHistory(),
                datacontext.cust.getPaymentSummary(),
                vm.customerDC.getAccountBalanceSummary(),
                datacontext.subscription.getSubscriptionHistory()
                //,LoadQuestionData()
            ], controllerId)
                .then(function () {
                    datacontext.primeCustomer().then(function () {
                        vm.customer = datacontext.cust.mycust;
                        if (vm.customer != null) {
                            vm.updatePhone = false;
                            var rawPhone = vm.custOriginalPhoneView = vm.custOriginalPhone = (typeof vm.customer.phone === "string") ? vm.customer.phone : vm.customer.phoneNumber;
                            vm.custOriginalPhoneView = rawPhone.substr(0, 5) + ' ' + rawPhone.substr(5);
                            vm.custOriginalEmail = vm.customer.eMail;
                            vm.historyPagingData.items = datacontext.order.orderHistoryData;
                            vm.subscriptionPagingData.items = datacontext.subscription.subscriptionHistoryData;
                            //vm.products = datacontext.products.entityItems;
                            vm.products = datacontext.products.entityData;
                            vm.payData = datacontext.cust.paymentsummary;

                            $scope.getPaymentHistory();
                        }
                    });
                });

        }
    }
})();;
(function () {
    var controllerId = 'announcementController';
    angular.module("app-hd").controller(controllerId,
        ["$scope" , "common", "$http", announcementController]);

    function announcementController($scope, common, $http) {
        var vm = this;
        vm.announcements = [];
        

        $http.get("/api/announcement/getAnnouncements").then(function (response) {
            var announcements = response.data;
            for(var i = 0; i < announcements.length; i++) {
                var announcement = announcements[i];
                vm.announcements.push({ header: announcement.header, body: announcement.body });
            }
        });
    }
})();;
(function () {
    var controllerId = 'applicationController';
    angular.module('app-hd').controller(controllerId,
        ['$rootScope', '$state', '$scope', 'common', 'authService', 'ngAuthSettings', applicationController]);

    function applicationController($rootScope, $state, $scope, common, authService, ngAuthSettings) {
        
        var debugState = false;
        
        if (debugState) {
            $rootScope.$on('$stateChangeStart',function(event, toState, toParams, fromState, fromParams){
                console.log('$stateChangeStart to '+ toState.to +'- fired when the transition begins. toState,toParams : \n',toState, toParams);
            });

            $rootScope.$on('$stateChangeError',function(event, toState, toParams, fromState, fromParams){
                console.log('$stateChangeError - fired when an error occurs during transition.');
                console.log(arguments);
            });

            $rootScope.$on('$stateChangeSuccess',function(event, toState, toParams, fromState, fromParams){
                console.log('$stateChangeSuccess to '+ toState.name+ '- fired once the state transition is complete.');
            });

            $rootScope.$on('$viewContentLoaded',function(event){
                console.log('$viewContentLoaded - fired after dom rendered',event);
            });

            $rootScope.$on('$stateNotFound',function(event, unfoundState, fromState, fromParams){
                console.log('$stateNotFound '+ unfoundState.to +'  - fired when a state cannot be found by its name.');
                console.log(unfoundState, fromState, fromParams);
            });
        }
        
        var vm = this;
        vm.appVersion = appVersion;
        $scope.imageVersion;
        $scope.CDNImageBaseURL;

        if (!$scope.CDNImageBaseURL || $scope.CDNImageBaseURL.length === 0) {
            common.getCDNBaseImageUrl().then(function (data) {
                if (data) {
                    $scope.CDNImageBaseURL = data;
                }
            });
        }
        if (!$scope.imageVersion || $scope.imageVersion <= 0) {
            common.getImageVersion().then(function (data) {
                if (data) {
                    $scope.imageVersion = data;
                }
            });
        }

        vm.seo = {
            title: "",
            description: "",
            canonical: "",
            h1Header:"",
            keywords: "",
            headerImageTag:"",
            robots: ""
        }

        $scope.setStoreName = function (name) {
            vm.storeName = name;
        }
        $scope.injectSeo = function (title, description, keyword, noIndex, noFollow, canonical, h1Header, headerImageTag) {

            if (title) {
                vm.seo.title = title;
            }

            if (description)
                vm.seo.description = description;
            if (keyword)
                vm.seo.keywords = keyword;
            if (canonical)
                vm.seo.canonical = canonical;
            if (h1Header)
                vm.seo.h1Header = h1Header;
            if (headerImageTag) {
                vm.seo.headerImageTag = headerImageTag;
            }
            if (noFollow == "ng-init" && noIndex == "ng-init") {
                vm.seo.robots += "noindex,nofollow";
            }
            else if (noIndex == "ng-init") {
                vm.seo.robots = "noindex";
            }
            else if (noFollow == "ng-init") {
                vm.seo.robots = "nofollow";
            }
            else {
                vm.seo.robots = '';
            }
        }

        $scope.getSeoMetadata = function (id, typeId) {
            common.getSeoMetadata(id, typeId).then(function (data) {
                var seo = {};
                if (data) {
                    seo = data;
                    if (typeId === 11) {
                        //this scope param is only populated on the city job page to inject citySearchPageContent
                        $scope.citySearchPageContent = seo.seoMetaDescription;
                    }
                    if (data.seoNoIndex) {
                        seo.seoNoIndex = "ng-init";
                    }
                    if (data.seoNoFollow) {
                        seo.seoNoFollow = "ng-init";
                    }
                }
                $scope.injectSeo(seo.seoTitleTag, seo.seoMetaDescription, seo.seoKeywords, seo.seoNoIndex, seo.seoNoFollow, seo.seoCanonicalURL, seo.seoH1Header,seo.seoOptimizedImageURL);
            });
        }
        
        $scope.getCookie = function getCookie(cname) {
            var name = cname + "=";
            var decodedCookie = decodeURIComponent(document.cookie);
            var ca = decodedCookie.split(';');
            for(var i = 0; i <ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) == ' ') {
                    c = c.substring(1);
                }
                if (c.indexOf(name) == 0) {
                    return c.substring(name.length, c.length);
                }
            }
            return "";
        }
        
        $scope.setCookie = function setCookie(cname, cvalue, exdate) {
            var expires;
            if (exdate) {
                expires = "expires="+ exdate.toUTCString();
            } else {
                expires = "expires=0";
            }
            
            document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
        }

        var metaDefaults = {
            url: ngAuthSettings.apiServiceBaseUri
            + 'browsing/category/featured/',

            type: 'website',
            title: vm.seo.title,
            description: vm.seo.description,
            canoncial: vm.seo.canonical,
            image: ngAuthSettings.BaseUri + 'images/' + 'logo-banner.jpg' + vm.appVersion
        }
        $scope.showAboutHDModal = false;

        vm.isAuthenticated = function () {
            return authService.authentication.isAuth;
        }

        vm.insideHomeDelivery = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/home-delivery') > 0 && fullsite.indexOf("/home-delivery/menu") < 1) return true;
            else return false;
        };

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }

        vm.showSearchBtn = function () {
            var fullsite = "" + window.location;
            return (fullsite.indexOf('/category') > 0);
        }

        $scope.isAuth = function () {
            return authService.authentication.isAuth;
        }

        $scope.ogMetaData = {};

        vm.goRecipes = function () {
            $state.go('browsing.recipes', {}, {
                reload: true,
                inherit: false,
                notify: true
            });
        }
        vm.goOurMenu = function () {
            $state.go('browsing.category', {}, {
                reload: true,
                inherit: false,
                notify: true
            });
        }
        activate();

        function activate() {
            common.activateController([], controllerId);
            angular.copy(metaDefaults, $scope.ogMetaData);
            var st = $state.current;
            function isHomeDeliveryURL() {
                var fullsite = "" + window.location;
                if (fullsite.indexOf('/home-delivery') > 0) return true;
                else return false;
            }
        }

        $rootScope.$on('setMetaData',
            function (event, data) {
                _.extend($scope.ogMetaData, data);
            });

        $rootScope.$on('setMetaDefault',
            function (event, data) {
                angular.copy(metaDefaults, $scope.ogMetaData);
            });
    }
})();;
(function () {
    var app = angular.module("app-hd");

    app.controller('authenticationController', [
        '$state', '$scope', '$http', '$location', '$stateParams', '$cookies', 'config', 'common', 'authService', 'ngAuthSettings', '$window', 'datacontext',
        function ($state, $scope, $http, $location, $stateParams, $cookies, config, common, authService, ngAuthSettings, $window, datacontext) {
            $scope.loginData = {
                useRefreshTokens: true,
                rememberMe: false
            };

            $scope.isAuth = function () { return authService.authentication.isAuth; }
            $scope.message = "";
            $scope.rememberMe = true;
            $scope.PassWordReset =
            {
                aspID: "",
                passwordResetToken: "",
                userName: "",
                phoneNumber: "",
                email: "",
                questionGuess: "",
                newpassword: "",
                userQuestion: "",
                result: "",
                message: ""
            };
            $scope.anyPWResetFlagsOn = !($scope.showPWlookup || $scope.showPWLookupForm || $scope.showPWReset);
            //|| $scope.showPWLookupQuestion
            $scope.showPWlookup = false;
            $scope.showPWLookupForm = false;
            //$scope.showPWLookupQuestion = false;
            $scope.showPWReset = false;
            $scope.showResetPWLinkSent = false;
            $scope.showPWResetSuccess = false;
            /* Is this user a mobile user */
            $scope.isMobile = ($window.innerWidth < 768);

            $scope.gotoSignIn = function () {
                var hash = $window.location.href;
                if ((hash.indexOf('home-delivery') > 0) || hash.indexOf('about-home-delivery') == 0) {
                    $state.go('sign-in');
                } else {
                    $window.location = 'home-delivery/log-in';
                }
            }
            $scope.isNewCustomer = function () {
                return datacontext.isNewCustomer;
            }

            $scope.isNewCustomer = function () {
                return datacontext.isNewCustomer;
            }

            $scope.goToMyCart = function () {
                //$state.go('shopping.account');

                $window.location = '/home-delivery/shopping/cart';
            }

            $scope.needToRegister = function () {
                var hash = $window.location.href;
                if (hash.indexOf('home-delivery') >= 0) {
                    $state.go('sign-up.1');
                } else {
                    $window.location = 'home-delivery/sign-up';
                }
            }

            $scope.CancelReset = function () {
                $state.go('sign-in', '', {
                    reload: true,
                    inherit: false,
                    notify: true
                });
            }

            $scope.loginFromDropdown = function () {
                if (common.validateForm("#drop-signin")) {
                    $scope.login();
                }
            }

            $scope.loginFromSignIn = function (showCuratorAgreement) {
                if (common.validateForm("#form-signin")) {
                    $scope.login(showCuratorAgreement);
                }
            }

            $scope.showTopGreyBar = function () {
                var showBar = !($scope.isAuth() || $scope.isNewCustomer());

                if (showBar) {
                    $('#bodyContainer').addClass('top-grey-bar');
                }
                else {
                    $('#bodyContainer').removeClass('top-grey-bar');
                }
                return showBar;
            }

            $scope.login = function (showCuratorAgreement) {

                common.$broadcast(config.events.spinnerToggle, { show: true });
                datacontext.resetAllData();
                $scope.showPWlookup = false;

                datacontext.cust.setStaySignedIn($scope.rememberMe);

                if ($scope.loginData.orgPassword !== $scope.loginData.maskPassword) {
                    $scope.loginData.password = $scope.loginData.maskPassword;
                }

                $scope.loginData.password = encodeURIComponent($scope.loginData.password);

                authService.login($scope.loginData).then(function (response) {
                    $scope.setLoginData();
                    //
                    // this needs to check response for converted customer

                    common.dc.cust.as400Refresh = true;

                    // why is this being done here?
                    // this is why we dont rounte to prelogin
                    // route
                    common.$q.all([datacontext.primeCustomer()])
                        .then(function () {
                            datacontext.primeProducts(true);
                            //don't wait for response.
                            //common.$q.all([datacontext.primeProducts(true)]);
                            //var default_target = '/home-delivery/shopping/category/' + config.defaultCategory + "/";

                            if (showCuratorAgreement) {
                                default_target = '/home-delivery/curator-agreement';
                                $window.location = default_target;
                            }
                            //if they are coming to log in from a specific portion of the site take them back to that spot on the site                            
                            if ($stateParams && $stateParams.rqst) {
                                $state.go($stateParams.rqst, angular.fromJson($stateParams.rqstParams));
                            }
                            //if not, send them to the featured category page
                            else {
                                $state.go('shopping.category', { productViewId: config.defaultCategory });
                            }

                        }, function (err) {
                            $scope.message = err.errorMessage;
                            $scope.logOut();
                            common.$broadcast(config.events.spinnerToggle, { show: false });
                        });
                }, function (failed) {
                    $scope.message = (failed.errorMessage) ? failed.errorMessage : "The username and password do not match our records.";
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });
            };

            $scope.setLoginData = function () {
                if ($scope.loginData.rememberMe) {

                    $http.get("api/Account/GetPasswordHash?userName=" + $scope.loginData.userName).then(function (result) {
                        $scope.loginData.passwordHash = result.data;
                        delete $scope.loginData.password;
                        $scope.loginData.maskPassword = Array($scope.loginData.maskPassword.length + 1).join("*");
                        var now = new $window.Date(),
                            // this will set the expiration to 6 months
                            exp = new $window.Date(now.getFullYear(), now.getMonth() + 6, now.getDate());

                        $cookies.putObject('loginData', $scope.loginData, {
                            expires: exp
                        });
                    });

                }
                else {
                    $cookies.remove('loginData');
                }
            }

            $scope.getLoginData = function (data) {

                if ($location.search().hash && $location.search().user) {
                    $scope.loginData.passwordHash = $location.search().hash;
                    $scope.loginData.maskPassword = "******";
                    $scope.loginData.userName = $location.search().user;
                    $scope.loginData.rememberMe = false;
                    $cookies.putObject('loginData', $scope.loginData);
                    $location.search('').replace();

                }
                else {
                    var loginData = $cookies.getObject('loginData');

                    if (loginData) {
                        $scope.loginData = loginData;
                        $scope.loginData.password = decodeURIComponent(loginData.passwordHash);
                        $scope.loginData.orgPassword = $scope.loginData.maskPassword;
                    }
                }


            }

            $scope.logOut = function () {
                datacontext.resetAllData();
                authService.logOut();
                $scope.showPWlookup = false;
                $state.go('sign-in');
            }

            $scope.PassWordReset.NewPasswordConfirmed = $scope.PassWordReset.NewPassword = "";
            $scope.PassWordReset.passwordChangeMessage = "";

            $scope.validatePassword = function () {
                //
                //  this is used by the password section to control the color of the result Message
                //
                var error = '';
                if ($scope.PassWordReset.NewPassword !== '' && $scope.PassWordReset.NewPasswordConfirmed !== '')
                    error = "New password and confirmation password do not match.";
                if ($scope.PassWordReset.NewPassword != $scope.PassWordReset.NewPasswordConfirmed) {
                    $scope.PassWordReset.passwordChangeMessage = error;
                } else {
                    if ($scope.PassWordReset.passwordChangeMessage == error) {
                        $scope.PassWordReset.passwordChangeMessage = "";
                    }
                }

                if ($scope.PassWordReset.passwordChangeMessage) {
                    return false;
                }
                return true;
            };

            //$scope.saveSQLRecovery = function () {
            //    return $http.post("api/Account/SetMyQuestionSQL", $scope.PassWordReset)

            //    .success(function (data) {
            //        $scope.PassWordReset = data;
            //        $scope.showPWlookup = false;
            //        $scope.showPWLookupForm = false;
            //        $scope.showPWLookupQuestion = false;
            //        $scope.showPWReset = false;
            //    })
            //    .error(function (data, status, headers, config) {
            //        $scope.message = data;
            //    });
            //};
            //$scope.saveRecovery = function () {
            //    return $http.get("api/Account/SetMyQuestion", $scope.PassWordReset)

            //    .success(function (data) {
            //        $scope.PassWordReset = data;
            //        $scope.showPWReset = false;
            //        $scope.showPWLookupForm = false;
            //    })
            //    .error(function (data, status, headers, config) {
            //        $scope.message = data;
            //    });
            //};
            $scope.startPWRecovery = function () {
                var hash = $window.location.hash;
                if (hash.indexOf('home-delivery') >= 0) {
                    $state.go('sign-in', { action: 'recovery' });
                    $scope.showPWlookup = true;
                    return;
                }
                else {
                    $window.location = 'home-delivery/log-in?action=recovery';
                    return;
                }

                $scope.showPWlookup = true;
            };
            $scope.LookUp = function () {

                $scope.message = "";

                $scope.loginData.userName = "";
                $scope.loginData.password = "";

                if (common.validateForm("#form-signin")) {

                    common.$broadcast(config.events.spinnerToggle, { show: true });

                    return $http.post("api/Account/GetPasswordResetToken", $scope.PassWordReset)

                        .success(function (data) {
                            common.$broadcast(config.events.spinnerToggle, { show: false });
                            $scope.PassWordReset = data;
                            if (data.message === "") {
                                //$scope.showPWlookup = false;
                                $scope.showPWLookupForm = false;
                                //$scope.showPWLookupQuestion = false;
                                $scope.showResetPWLinkSent = true;
                            }
                        })
                        .error(function (data, status, headers) {
                            common.$broadcast(config.events.spinnerToggle, { show: false });
                            $scope.message = data.message;
                        });
                }
            };

            //$scope.checkAnswer = function () {
            //    $scope.message = "";

            //    return $http.post("api/Account/checkAnswer", $scope.PassWordReset)
            //    .success(function (data) {
            //        $scope.PassWordReset = data;

            //        if (data.message === "") {

            //            $scope.showPWLookupQuestion = false;
            //            $scope.showPWLookupReset = true;
            //            $scope.showPWReset = true;

            //        }
            //    })
            //    .error(function (data, status, headers, config) {
            //        $scope.message = data;
            //    });
            //};
            $scope.SetNewPassword = function () {

                if (common.validateForm("#form-signin")) {

                    var cidParam = $location.search().cid;

                    datacontext.cust.lookupCustomerById(cidParam).then(function () {

                        $scope.PassWordReset.passwordChangeMessage = "";

                        $scope.PassWordReset.userId = datacontext.cust.mycust.aspNetUserId;

                        $scope.PassWordReset.passwordResetToken = $location.search().token;

                        return authService.setPassword($scope.PassWordReset)
                            .then(function (response) {
                                $scope.showPWlookup = false;
                                $scope.showPWLookupForm = false;
                                $scope.showPWReset = false;
                                $scope.showPWReset = true;
                                $scope.showPWResetSuccess = true;
                                $cookies.remove('loginData');
                            }, function (error) {
                                $scope.PassWordReset.passwordChangeMessage = common.handleError(error);
                            });
                    }, function () {
                        $scope.message = "This password reset link is no longer valid. Please submit a new password reset request.";
                    });
                }
            };

            $scope.clearValidationMessages = function () {
                $scope.PassWordReset.passwordChangeMessage = "";
            }

            //$scope.SetNewSQLPassword = function () {
            //    return $http.post("api/Account/SetMyQuestionSQL", $scope.PassWordReset)

            //    .success(function (data) {
            //        $scope.PassWordReset = data;
            //        if ((data.message) || (data.message === "")) {
            //            $scope.showPWlookup = false;
            //            $scope.showPWLookupForm = false;
            //            $scope.showPWReset = false;
            //        }
            //    })
            //    .error(function (data, status, headers, config) {
            //        $scope.message = data;
            //    });
            //};

            function onDestroy() {
                //
                //  this should fire when we leave the new customer process
                //
                //$scope.$on('$destroy', function () {
                $scope.$on('$destroy', function () {
                    //$scope.$onDestroy = function () {
                    debugger;
                    var staySignedIn = datacontext.cust.getStaySignedIn();
                    if (!staySignedIn) {
                        authService.logOut();
                    }
                });
            }

            activate();
            function activate() {
                var url = $window.location.href;
                if (url.indexOf('?browsing') >= 0) {
                    window.location = url.replace('?', '#');
                    return;
                };

                if ($location.search().hash && $location.search().user) {
                    authService.logOut();
                }

                //onDestroy();
                if (authService.authentication.isAuth) {
                    // $state.go('shopping.categorynoparm');
                    // return;
                } else {
                    localStorage.clear();
                }

                common.activateController([], 'authenticationController');
                var parms = $stateParams;

                if ($location.search().action == 'reset') {
                    var token = $location.search().token;
                    $scope.showPWReset = true;
                }

                else if (parms.error) {
                    $scope.message = parms.error;
                }

                if (($state.current.name == '') && ($location.search().action == 'recovery')) {
                    $scope.showPWlookup = true;
                } else {
                    if ((parms.action) && (parms.action == 'recovery')) $scope.showPWlookup = true;
                }
                common.$broadcast(config.events.spinnerToggle, { show: false });

                $scope.getLoginData();
            }
            $scope.setLoginSeo = function () {
                $scope.getSeoMetadata("login", 7)
            };

            $scope.saveUpdate = function () {
                common.dc.cust.saveData_In_myCache("pw", $scope.PassWordReset);
            };
            $scope.authExternalProvider = function (provider) {
                var redirectUri = location.protocol + '//' + location.host + '/authcomplete.html';
                var externalProviderUrl = ngAuthSettings.apiServiceBaseUri + "api/Account/ExternalLogin?provider=" + provider
                    + "&response_type=token&client_id=" + ngAuthSettings.clientId
                    + "&redirect_uri=" + redirectUri;
                window.$windowScope = $scope;
                var oauthWindow = window.open(externalProviderUrl, "Authenticate Account", "location=0,status=0,width=600,height=750");
            };

            $scope.authCompletedCB = function (fragment) {
                $scope.$apply(function () {
                    if (fragment.haslocalaccount === 'False') {
                        authService.logOut();
                        authService.externalAuthData = {
                            provider: fragment.provider,
                            userName: fragment.external_user_name,
                            externalAccessToken: fragment.external_access_token
                        };

                        $location.path('/associate');
                    } else {
                        //Obtain access token and redirect to Orders
                        var externalData = { provider: fragment.provider, externalAccessToken: fragment.external_access_token };
                        authService.obtainAccessToken(externalData).then(function (response) {
                            if ((!$state.current) || ($state.current.name == '')) {
                                $window.location = 'home-delivery/shopping/category/' + config.defaultCategory;
                                return;
                            }

                            $state.go(config.defaultCategory)
                        },
                            function (err) {
                                $scope.message = err.error_description;
                            });
                    }
                });
            };
        }]);
})();;
(function () {
    var controllerId = 'cartButtonController';

    angular.module('app-hd').controller(controllerId,
        ["$cookies"
            , "$rootScope"
            , "$stateParams"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "config"
            , "common"
            , "datacontext"
            , "authService", cartButtonController]);

    function cartButtonController($cookies
        , $rootScope
        , $stateParams
        , $scope
        , $state
        , $timeout
        , $window
        , config
        , common
        , datacontext
        , authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        vm.mycust = datacontext.cust.mycust;
        vm.authentication = authService.authentication;

        vm.isAuth = function () {
            return authService.authentication.isAuth;
        }

        vm.cartShowMenu = function () {
            if (vm.cartMenuShowing)
                vm.cartMenuShowing = false;
            else
                vm.cartMenuShowing = true;
        };
        vm.cat = $stateParams.cat;
        vm.orderContext = datacontext.order;
        vm.mycust = datacontext.cust.mycust;
        vm.customerDC = datacontext.cust;
        vm.productsDC = datacontext.products;
        vm.products = vm.productsDC.entityItems;
        vm.orderDC = datacontext.order;
        vm.noindexProducts = [];

        vm.GetNextDeliveryTotals = _getNextDeliveryTotals;
        vm.GetStandingDeliveryTotals = _getStandingDeliveryTotals;

        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;

        vm.showCart = false;
        vm.showStickycart = false;
        vm.allowOrderEdits =
            function (prd) {
                if (!datacontext.products.partialsMappedLoaded) return false;
                return datacontext.products.allowOrderEdits(prd);
            }
        vm.showOrderEdits = vm.isAuth() || datacontext.isNewCustomer;

        vm.GetNextOrderItemsCount = _getNextOrderItemsCount;

        function _getNextOrderItemsCount() {
            return datacontext.order.GetNextOrderItemsCount();
        }

        vm.goToMyCart = function () {
            if (vm.isAuth()) {
                vm.showStickycart = false;
                $window.location = '/home-delivery/shopping/cart';
                return;
            }
            else {
                vm.checkoutButtonClicked();
                return;
            }
        }
        vm.logOut = function () {
            datacontext.resetAllData();
            authService.logOut();
            $scope.showPWlookup = false;
            $state.go('sign-in');
        }
        vm.isNewCustomer = function () {
            return datacontext.isNewCustomer;
        }

        vm.isIncompleteStartup = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.incompleteCustomerSignup;
        }

        vm.showCartButton = function () {
            return (authService.authentication.isAuth || datacontext.isNewCustomer);
            //&& ($state.current.url.indexOf('/') >= 0);
        }

        vm.checkoutButtonClicked = function () {
            if (vm.isAuth() && !vm.isIncompleteStartup()) {
                if ($state.current.name === "sign-in" || $state.current.name === "") {
                    $window.location = '/home-delivery/shopping/cart';
                }
                else {
                    $state.go('shopping.cart');
                }
            }
            else if (vm.isIncompleteStartup() && $state.current.name === "") {
                $window.location = '/home-delivery/sign-up/shopping/cart';
            }
            else {
                if ($state.current.name === "sign-in") {
                    $window.location = '/home-delivery/sign-up/shopping/cart';
                }
                else {
                    $state.go('sign-up.2.cart');
                }
            }
        }

        vm.getCategory = function (product) {
            if (product.brand == 'Oberweis') return product.categoryName;
        }

        vm.goProduct = function (productId) {
            var destParam = { id: productId };
            if (($state.current.name.indexOf('sign') >= 0) && ($state.current.name.indexOf('category') >= 0)) {
                $state.go('^.product', destParam);
                return;
            }
            $state.go('^.product', destParam);
            return;
        }


        vm.showCheckoutReminder = function () {
            if (vm.GetNextOrderItemsCount() > 0 && datacontext.cust.mycust.orderChanged && !datacontext.cust.mycust.hideReminder && vm.isideProductPages()) {
                return true;
            }
            return false;
        }
        vm.isInsideShoppingCart = function () {
            return ($state.current.name.indexOf('cart') >= 0)
        }
        vm.isideProductPages = function () {
            return ($state.current.name.indexOf('product') >= 0 || $state.current.name.indexOf('category') >= 0);
        }

        vm.hideCheckoutReminder = function () {
            datacontext.cust.mycust.hideReminder = true;
        }

        function _getNextOrderItemsCount() {
            return datacontext.order.GetNextOrderItemsCount();
        }

        function _getNextDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.nextTotals) ? datacontext.order.orderTotals.nextTotals : 0;
        }

        function _getStandingDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.standingTotals) ? datacontext.order.orderTotals.standingTotals : 0;
        }

        vm.nextDelivery = function (item) {
            return item && item.nextQuantity && item.nextQuantity > 0;
        }
        vm.standingDelivery = function (item) {
            return item && item.standingQuantity && item.standingQuantity > 0;
        }

        vm.products = vm.productsDC.entityItems;
        vm.storeChange = function () {
            datacontext.order.saveitems(vm.orderItems);
        };
        vm.showCartMessage = function showCartMessage() {
            var show = false;

            if (!vm.isAuth() && vm.showOrderEdits) {
                vm.cartMessage = 'Continue your sign-up process here.  You can return to shopping anytime. ';
                show = true;
            }
            else if (vm.isAuth()) {
                vm.cartMessage = 'To see items in your cart click here';
                show = true;
            }

            return show;
        }
        activate();

        function activate() {
            if (vm.isAuth()) {
                common.activateController([
                    datacontext.primeProducts()
                ], controllerId)
                    .then(function () {
                        vm.mycust = datacontext.cust.mycust;
                        vm.hasData = true;
                        vm.noindexProducts = datacontext.products.entityData;
                        vm.products = datacontext.products.entityItems;
                    });

                return;
            }
        };
    }
})();
;
(function () {
    var controllerId = 'cartController';

    angular.module('app-hd').controller(controllerId,
    ['$window', '$stateParams', '$state', 'config', 'common', 'datacontext', "authService", mainCart]);

    function mainCart($window, $stateParams, $state, config, common, datacontext, authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;

        vm.authentication = authService.authentication;
        vm.baseUrl = config.baseUrl;

        vm.allowCollapse = true;
        vm.cartMenuShowing = $window.innerWidth > 768;
        vm.cartShowMenu = function () {
            if (vm.cartMenuShowing)
                vm.cartMenuShowing = false;
            else
                vm.cartMenuShowing = true;
        };
        vm.cat = $stateParams.cat;
        vm.orderContext = datacontext.order;
        vm.mycust = datacontext.cust.mycust;
        vm.customerDC = datacontext.cust;
        vm.productsDC = datacontext.products;
        vm.catDC = datacontext.category;
        vm.products = vm.productsDC.entityItems;
        //vm.nextDelivery = function (item) {
        //    return item && item.nextQuantity && item.nextQuantity > 0;
        //}
        //vm.standingDelivery = function (item) {
        //    return item && item.standingQuantity && item.standingQuantity > 0;
        //}

        vm.nextDeliveryCount = datacontext.order.getNextOrderItemsCount();

        vm.title = 'Cart';
        vm.collection = [];
        vm.prods = {};
        vm.orderItems = [];

        vm.showNextCart = function () {
            if (!datacontext.cust.creatingNewCustomer) {
                return true;
            }
            return false;
        }

        vm.saveChange = function () {
            datacontext.order.isDirty = true;
            datacontext.order.PostOrderDetailUpdate();
        };

        vm.selectCat = function () {
        };
        vm.getProduct = function (id) {
            if (angular.isDefined(id)) {
                return datacontext.products.entityItems[id];
            }

            return null;
        };
        vm.hasData = false;

        vm.gotoCategory = function (prod) {
            ///
            //	are categories currently displayed
            //

            //
            //	if showing categories then just change
            //	the selected element that backs the
            //

            if ($state.current.name.indexOf('catalog') < 0) {
                return $state.go('^.catalog', { id: prod.categoryId });
            } else {
                angular.forEach(datacontext.category.entityItems, function (branch) {
                    angular.forEach(branch.children, function (child) {
                        if (child.name == prod.categoryId) {
                            datacontext.category.selectedCategory = child;
                            branch.expanded = true;
                            if (branch.isParent) {
                                datacontext.category.selectedCategory = branch;
                                datacontext.products.currentParent = branch.name;
                            } else {
                                var selectedary = { "children": [branch] };

                                datacontext.category.selectedCategory = selectedary;
                                datacontext.products.currentParent = branch.parentName;
                            }
                        }
                    });
                });
                datacontext.products.entityItems[prod.productId].select = true;
            }
        };

        vm.storeChange = function () {
            datacontext.order.saveitems(vm.orderItems);
        };

        activate();
        function activate() {
            common.activateController([
                datacontext.primeProducts()
            ], controllerId)
                .then(function () {
                    vm.mycust = datacontext.cust.mycust;
                    vm.hasData = true;
                }
                );
        };
        vm.getCategory = function (product) {
            if (product.brand == 'Oberweis') return product.categoryName;
        }
        vm.commitOrder = function () {
            datacontext.order.PushOrderToAS400().then(function (result) {
                console.log(result);
            });
            datacontext.order.isDirty = false;
        };

        vm.hidemember = function (member) {
            if ((member.parentName == vm.currentParent) || (member.isParent)) return true;
            return false;
        };
    }
})();;
(function () {
    "use strict";
    var controllerId = "catalogPopupController";

    angular.module("app-hd").controller(controllerId, ["$stateParams" , "$scope" , catalogPopupController]); 
    
    function catalogPopupController($stateParams, $scope) {
        var vm = this;
        var date = new Date();
        
        vm.overlayImageFileName = date.getFullYear().toString() + (("0" + (date.getMonth() + 1)).slice(-2)) + ".jpg";

        vm.showModal = false;
        
        var COOKIE_NAME = 'displayed_catalog';
        
        if (navigator.cookieEnabled && !$scope.getCookie(COOKIE_NAME)) {
            vm.showModal = true;
            var lastDayOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 1);
            $scope.setCookie(COOKIE_NAME, true, lastDayOfMonth);
        }
        
        vm.closeCatalogModal = function () {
            vm.showModal = false;
        }

        $("#lookbook-mobile").one("error",
            function() {
                $(this).attr("src", "assets/images/lookbook/mobile/fallback.jpg");
            });

        $("#lookbook-desktop").one("error",
            function() {
                $(this).attr("src", "assets/images/lookbook/desktop/fallback.jpg");
            });
    }
})();
;
(function () {
    var controllerId = 'claimEGiftCardCodeController';

    angular.module('app-hd').controller(controllerId, ['$scope', '$http', '$stateParams', 'eGiftCardService', claimEGiftCardCodeController]);
    
    function claimEGiftCardCodeController($scope, $http, $stateParams, eGiftCardService) {
        var vm = this;
        let claimCode = null;
        vm.loadedDetails = false;
        vm.cardDetails = null;
        
        vm.claimState = {
            error: null,
            completed: false,
            loading: false
        };
        
        (function activate() {
            claimCode = $stateParams.claimCode

           eGiftCardService
               .getUnclaimedEGiftCardDetails(claimCode)    
                .then(function success(response) {
                    if (response.data) {
                        vm.cardDetails = response.data;
                    }
                })
                .catch(function () {
                })
                .finally(function () {
                    vm.loadedDetails = true;
                });
        })();
        
        vm.applyToAccount = function() {
            vm.claimState.loading = true;
            eGiftCardService
                .applyEgiftCardToAccount(claimCode)
                .then(function() {
                    vm.claimState.error = null;
                    vm.claimState.completed = true;
                })
                .catch(function(error) {
                    vm.claimState.error = error;
                })
                .finally(function () {
                    vm.claimState.loading = false;
                })
        }
    }
})()

;
(function () {
    var controllerId = 'collectionCatalogController';

    angular.module('app-hd').controller(controllerId, ['$scope', '$http', '$state', 'common', 'config', 'authService', 'unauthenticatedBranch', 'datacontext', collectionCatalogController]);


    function collectionCatalogController($scope, $http, $state, common, config, authService, unauthenticatedBranch, datacontext) {
        var vm = this;

        vm.$state = $state;
        vm.productCollections = [];
        vm.currentBranch = 1;
        vm.previousBranch = 0;
        vm.showOneTimeUseDisclaimer = false;
        vm.showCartEditDisclaimer = false;
        vm.priceCode = null;
        vm.isAuth = null;


        vm.isAuthenticated = function () {
            if (vm.isAuth == null) {
                vm.isAuth = authService.authentication.isAuth;
                //console.log(vm.isAuth);
            }
            return vm.isAuth;
        };

        vm.getBranch = function () {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
            vm.currentBranch = curBranch;
        };

        vm.getPriceCode = function () {
            if (datacontext.cust && datacontext.cust.mycust)
                vm.priceCode = datacontext.cust.mycust.price_schedule;
            else
                vm.priceCode = null;
            //console.log("Customer PriceCode:" + vm.priceCode);
        };

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (newVal, oldVal) {
            if (oldVal && newVal && oldVal.branchNumber !== newVal.branchNumber) {
                vm.getActiveCollectionsForBranch();
            }
        });

        vm.getActiveCollectionsForBranch = function () {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
            var url = "api/ProductCollection/GetActiveProductCollections/?branchNumber=" + curBranch + "&newStartsOnly=false";
            vm.getPriceCode();

            $http.get(url)
                .success(function (data) {
                    vm.productCollections = data;
                    //Product collection discounts apply only if the price code of the user matches
                    if (vm.priceCode != null) {
                        angular.forEach(vm.productCollections, function (pc) {
                            pc.validForPriceCode = pc.productCollectionPriceCode.some(pcpc => pcpc.priceCode.toString() == vm.priceCode);
                        });
                    }

                    //Show prices and disclaimers if user is not logged in, but if logged in only show if collection discount valid for user price code
                    vm.showOneTimeUseDisclaimer =
                        !vm.isAuthenticated()
                        || vm.productCollections.some(pc => pc.validForPriceCode == true && pc.oneTimeUse == true);
                    vm.showCartEditDisclaimer =
                        !vm.isAuthenticated()
                        || vm.productCollections.some(pc => pc.validForPriceCode == true && pc.discountValue && pc.discountValue > 0);

                })
                .error(function (data, status, headers, config) {
                    vm.message = data;
                });

        };

        (function activate() {
            vm.getActiveCollectionsForBranch();
        })();


    }
})();
;
(function () {
    var controllerId = 'collectionDetailController';

    angular.module('app-hd').controller(controllerId,
        ["$scope",
            "$state",
            "$http",
            "$stateParams",
            "config",
            "common",
            "datacontext",
            "authService",
            "$window",
            "unauthenticatedBranch",
            collectionDetailController]);


    function collectionDetailController($scope, $state, $http, $stateParams, config, common, datacontext, authService, $window, unauthenticatedBranch) {
        var vm = this;
        vm.appVersion = appVersion;
        vm.products = datacontext.products.entityItems;
        vm.collectionSelectionsValid = false;
        vm.collectionId = $stateParams.id;
        vm.selectedProductCollection = $scope.SelectedCollection;
        vm.totalsRefreshing = false;
        vm.isAuth = false;
        vm.saveSuccess = false;
        vm.showCollectionSaveResultPopup = false;
        vm.satisfyQuantityImpossible = false;


        vm.isAuthenticated = function () {
            vm.isAuth = authService.authentication.isAuth;
            return vm.isAuth;
        };

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (newVal, oldVal) {
            if (oldVal && newVal && oldVal.branchNumber !== newVal.branchNumber) {
                //This collection may not be available at the newly selected branch
                vm.CollectionsGoBack();
            }
        });

        vm.addToCartDisabled = function () {
            //console.log(datacontext.cust);
            var myCustomer = datacontext.cust.mycust;
            if (myCustomer != null) {
                if (myCustomer.cartItemDisabledReason != null) { return true; } //User Suspended Next Delivery, or Branch Cutoff Hours, etc.
                if (myCustomer.lockUser === true) { return true; } //User account locked or on billing hold
            }
            return false;
        };

        vm.showOutOfStock = function (product) {
            //console.log(product);
            return datacontext.products.showOutOfStock(product);
        };
        vm.getProductOverlayBanner = function (product) {
            return datacontext.products.showOverlayBanner(product);
        };

        vm.DisableOutOfStockProducts = function (branchNumber) {
            if (vm.isAuthenticated() === true && vm.addToCartDisabled() === false) {

                var impossibleGroups = [];
                angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                    var outOfStockItems = [];
                    angular.forEach(group.productCollectionGroupItems, function (groupItem) {
                        if (vm.products[groupItem.productId] == null
                            || vm.showOutOfStock(groupItem.productId)
                            || vm.getProductOverlayBanner(groupItem.productId) !== null
                        ) {
                            outOfStockItems.push(groupItem.productId);
                        }
                    });
                    if (outOfStockItems.length == group.productCollectionGroupItems.length
                        || (group.productCollectionGroupItems.length - outOfStockItems.length) < group.minRequired
                    ) {
                        //All of the items in this group are out of stock OR not enough are in stock to satisfy min selection qty
                        impossibleGroups.push(group.id);
                    }
                });
                if (impossibleGroups.length > 0) {
                    //It would be impossible for the user to add this collection to their cart
                    vm.satisfyQuantityImpossible = true;
                }
            }
        };

        // If user logged in, pre-select group items where there is only one option and at least one is required
        vm.PreSelectGroupsOfOne = function () {
            if (vm.isAuthenticated() === true && vm.addToCartDisabled() === false) {


                angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                    group.selectedProducts = [];
                    if (group.productCollectionGroupItems.length == 1 && group.minRequired > 0) {
                        var collectionGroupItem = group.productCollectionGroupItems[0];
                        //was groupItem.productID (etc.) but groupItem didnt exist
                        if (vm.products[collectionGroupItem.productId] != null
                            && vm.showOutOfStock(collectionGroupItem.productId)==false
                            && vm.getProductOverlayBanner(collectionGroupItem.productId) == null
                            )
                        {

                            collectionGroupItem.selected = true;
                            collectionGroupItem.quantity = 1;
                            group.selectedProducts.push(collectionGroupItem.productId);
                        };
                    };
                });
                //Validates and sets the use message telling them how many more to select
                validateSelections();
            }
        };

        vm.ToggleSelectedCollectionItem = function (collectionGroupItem, collectionGroup) {
            if (!vm.isAuthenticated() || vm.addToCartDisabled() || vm.satisfyQuantityImpossible) { return; }
            if (vm.showOutOfStock(collectionGroupItem.productId) || vm.getProductOverlayBanner(collectionGroupItem.productId) !== null) { return; }

            if (collectionGroupItem && collectionGroupItem.selected) {
                //Do not allow users to un-select items if there is only one product option in the group
                if (collectionGroup.productCollectionGroupItems.length > 1) {
                    collectionGroupItem.selected = false;
                    collectionGroupItem.quantity = 0;
                    //Remove from the array of user-selected products
                    collectionGroup.selectedProducts = collectionGroup.selectedProducts.filter(e => e !== collectionGroupItem.productId);
                    validateSelections();
                }
            } else {
                if (!collectionGroup.maxAllowed || collectionGroup.selectedProducts.length < collectionGroup.maxAllowed) {
                    collectionGroupItem.selected = true;
                    collectionGroupItem.quantity = 1;
                    collectionGroup.selectedProducts.push(collectionGroupItem.productId);
                    validateSelections();
                }
            }
        };

        function validateSelections() {
            if (!vm.selectedProductCollection) { return; }

            var satisfiedGroups = 0;
            angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                group.minQtySatisfied = group.selectedProducts.length >= group.minRequired;
                if (group.minQtySatisfied) {
                    satisfiedGroups++;
                    group.userMessage = "Selection Complete";
                } else {
                    var delta = group.minRequired - group.selectedProducts.length;
                    group.userMessage = "Please select " + delta + " more option" + (delta === 1 ? "" : "s");
                }
            });

            //The user selections are valid when the min quantities of all groups have been satisfied
            vm.collectionSelectionsValid = satisfiedGroups === vm.selectedProductCollection.productCollectionGroup.length;
        };

        vm.ValidCollectionAddToCart = function () {
            common.$broadcast(config.events.spinnerToggle, { show: true });

            //Users are allowed to purchase any collection valid for the branch, but they only get the discount if it's valid for their price code
            if (vm.selectedProductCollection.validForPriceCode==true) {
                //Need to commit the customer update right now so that cart item updates will account for the discount
                //This also saves the assignment of specific products to each CollectionGroupItem, required for discount math when multiple collections in play
                vm.selectedProductCollection.custId = datacontext.cust.mycust.id;
                vm.selectedProductCollection.newCustomerSignUp = false;
                datacontext.cust.updateSelectedProductCollection(datacontext.cust.mycust.id, vm.selectedProductCollection);
            }

            //Make sure user selections are all added to the cart
            var newCartItems = [];
            angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                angular.forEach(group.selectedProducts, function (selectedProduct) {
                    var p = vm.products[selectedProduct];
                    if (p) {
                        p.standingQuantity = 0;
                        p.nextQuantity = 1;
                        p.nextQuantityOriginal = 0;
                        p.changed = true;
                        newCartItems.push(p);
                    }
                });
            });

            try {
                datacontext.order.PostOrderDetailUpdate(newCartItems).then(
                    function (result) {
                        vm.saveSuccess = true;
                        vm.showCollectionSaveResultPopup = true;
                        common.$broadcast(config.events.spinnerToggle, { show: false });

                        //this does not actually work but leaving it in for now in case it just needs a tweak
                        datacontext.forceCartRefresh(); //signals productCatalogController to refresh cart arrays used on the UI
                    },
                    function () {
                        vm.saveSuccess = false;
                        vm.showCollectionSaveResultPopup = true;
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    }
                );
            }
            catch (err) {
                vm.saveSuccess = false;
                vm.showCollectionSaveResultPopup = true;
                common.$broadcast(config.events.spinnerToggle, { show: false });
            }
        };

        vm.goShoppingCart = function () {
            $state.go('shopping.cart', {
                reload: true,
                inherit: false,
                notify: true
            });
        };

        vm.CollectionsGoBack = function () {
            $scope.SelectedCollection = null;
            var routeBase = vm.isAuth ? 'shopping' : 'browsing';
            $state.go(routeBase + '.categorycollections', {
                productViewId: 'collections',
                location: true,
                inherit: true,
                reload: false,
                notify: true
            });
        };

        vm.CloseSaveResultPopup = function (nextAction) {
            vm.showCollectionSaveResultPopup = false;
            $('body').removeClass('modal-open'); //Hack. Modal close is supposed to do this, but it's not.
            switch (nextAction) {
                case 'none':
                    break;
                case 'gotocart':
                    //vm.goShoppingCart();
                    $window.location.href = "/home-delivery/shopping/cart"; //force cart refresh
                    break;
                case 'continue':
                    //vm.CollectionsGoBack();
                    //replaced with a temp window.location to force a refresh and populate the cart ui
                    $window.location.href = "/home-delivery/shopping/category/collections";
                    break;
                default:
            };
        };

        (function activate() {
            vm.selectedProductCollection = $scope.SelectedCollection;
            if (vm.selectedProductCollection != null) {
                vm.DisableOutOfStockProducts(vm.currentBranch);
                vm.PreSelectGroupsOfOne();
            }
        })();

     }

})();
;
(function () {
    var controllerId = 'curatorContactRequestController';

    angular.module('app-hd').controller(controllerId,
        ['$scope', '$http', '$q', '$state', '$cookies', 'datacontext', 'common', curatorContactRequestController]);


    function curatorContactRequestController($scope, $http, $q, $state, $cookies, datacontext, common) {
        var vm = this;

        vm.contactRequest = {};

        vm.sendContactRequest = function () {
            vm.sentSuccess = false;
            vm.message = "";

            if (common.validateForm("#curatorContact")) {

                var defer = $q.defer();

                $http.post('api/curator/contactRequest/', vm.contactRequest).then(function (response) {
                    vm.sentSuccess = true;
                    vm.contactRequest = {};
                    vm.message = "Contact request has been sent.";

                    defer.resolve(response.data);
                    return;
                }, function () {
                    vm.message = "Can not send Contact Request. Please try again later.";
                    defer.reject();
                });
                return defer.promise;
            }
        };

        function activate() {

        }

        activate();
    }
})();;
(function () {
    var controllerId = 'curatorController';

    angular.module('app-hd').controller(controllerId,
        ['$scope', '$http', '$q', '$state', '$cookies', 'datacontext', 'common', curatorController]);


    function curatorController($scope, $http, $q, $state, $cookies, datacontext, common) {
        var vm = this;
        vm.ChangeTo = $scope.$parent.vm ? $scope.$parent.vm.ChangeTo : function () { };

        vm.curator = { useDeliveryAddress: true, parentSalesId: $cookies.get("salesId") };
        vm.paymentMethod = {};
        vm.address = {};

        vm.submit = function () {
            //console.log(vm.curator)
            if (common.validateForm("#curatorForm")) {

                if (!vm.curator.customerId) {
                    vm.errorMessage = "Something went wrong. Please try again.";
                    return;
                }
                else if (!vm.curator.useDeliveryAddress) {
                    vm.curator.CuratorAddress = [vm.address];
                }
                else if (!vm.curator.SSN) {
                    vm.errorMessage = 'Please enter a valid SSN';
                    return;
                }

                var defer = $q.defer();

                $http.post('api/curator/SignCuratorAgreement/', vm.curator).then(function (response) {
                    //console.log(response.data);
                    if (vm.isNewStart) {
                        vm.ChangeTo(8);
                    }
                    else {
                        $state.go('curator-confirmation');
                    }

                    defer.resolve(response.data);
                    return;
                }, function () {
                    vm.errorMessage = "Can not create Curator agreement at this time.  Please try later or contact customer support.";
                    defer.reject();
                });
                return defer.promise;

            }
        };

        vm.resetErrorMessage = function () {
            vm.enroll_Message = "";
        };

        vm.LookupBankName = function() {
            if (('' + vm.curator.BankRoutingNumber).length >= 8) {
                return $http.get("api/customers/getBankName?rounteNum=" + vm.curator.BankRoutingNumber)
                    .success(querySucceeded);
            }

            function querySucceeded(data) {
                vm.resetErrorMessage();
                vm.curator.bankName = data;
            }
        };


        function activate() {
            common.disableBrowserBack();

            vm.isNewStart = $state.current.name === 'sign-up.101';

            vm.hideSalesPersonId = $cookies.get("salesId") != null;

            common.activateController([], controllerId)
                .then(function () {
                    datacontext.primeCustomer().then(function () {
                        vm.datacontext = datacontext;
                        vm.customer = vm.datacontext.cust.mycust;
                        vm.curator.customerId = vm.datacontext.cust.mycust.id;
                        vm.curator.SSN = '';
                    });
                });
        }

        activate();
    }
})();;
(function () {

    var controllerId = 'deliveryAuditController';
    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , "datacontext"
            , "deliveryFeedback"
            , "common"
            , "config"
            , deliveryAuditController]);

    function deliveryAuditController(
        $stateParams
        , $scope
        , datacontext
        , deliveryFeedback
        , common
        , config ) {

        vm = this;
        
        vm.feedbackForm = {
            CustomerId: null,
            DeliveryFeedbackImages: [],
            DeliveryDate: null,
            DateUploaded: null,
            Branch: null,
            Route: null,    
            Notes: null,
        }

        vm.overLimit = false;
        vm.isError = false;
        vm.errorMessageText = "1 or more files was over 10MB or not an acceptable file type"
        $scope.fileNames = [];

        $scope.filesAreUploaded = false;
        $scope.pastDeliveryDates = []
        
        function setPastDeliveryDates() {
            var pastDatesToAdd = 3;
            var nextDeliveryDay = new Date(datacontext.cust.mycust.nextDeliveryDate)

            var todayDate = new Date();
            todayDate.setHours(0, 0, 0, 0);
            if (nextDeliveryDay.getTime() == todayDate.getTime()) {
                $scope.pastDeliveryDates.push(todayDate.toLocaleString().split(',')[0])
                pastDatesToAdd = 2;
            }

            for (let i = 1; i <= pastDatesToAdd; i++) {
                var pastDeliveryDate = new Date(nextDeliveryDay.setDate(nextDeliveryDay.getDate() - 7 )).toLocaleString().split(',')[0];
                $scope.pastDeliveryDates.push(pastDeliveryDate)
            }
        }

        vm.uploadPhotos = async function (element) {

            vm.isError = false;
            if (element.currentTarget.files.length > 5) {
                vm.isError = true;
                vm.errorMessageText = "Please upload no more than 5 images";
                document.getElementById("DeliveryFeedbackImages").value = "";
                $scope.filesAreUploaded = false;
                $scope.$apply();
                return
            } else {
                vm.isError = false;
                $scope.$apply();
            }
            
            var files = element.currentTarget.files;
            const acceptedImageTypes = ['image/gif', 'image/jpeg', 'image/png'];
            var rejectedFiles = 0;

            Object.values(files).forEach(eachFile => {
                const reader = new FileReader();
                var file = eachFile;
                var fileByteArray = [];

                if (file.size < 10000000 && acceptedImageTypes.includes(file.type) && $scope.fileNames.length < 5) {
                    $scope.filesAreUploaded = true;
                    reader.readAsArrayBuffer(file);

                    reader.onload = (e) => {
                        if (e.target.readyState === FileReader.DONE) {
                            //build byte array
                            const arrayBuffer = e.target.result,
                                array = new Uint8Array(arrayBuffer);
                            for (const a of array) {
                                fileByteArray.push(a);
                            }

                            var image = {
                                Id: null,
                                CustomerFeedbackId: null,
                                Image: fileByteArray,
                                ImageType: file.type
                            };

                            vm.feedbackForm.DeliveryFeedbackImages.push(image);
                            $scope.fileNames.push(file.name);
                            $scope.$apply();
                        }
                    };


                } else {
                    if ($scope.fileNames.length === 5) {
                        vm.overLimit = true;
                    }
                    rejectedFiles += 1;
                }
            })

            if (rejectedFiles > 0) {
                vm.isError = true;
                if (vm.overLimit) {
                    vm.errorMessageText = "Max upload limit (5) reached.";
                }
            } else {
                vm.isError = false;
            }
        }

        vm.toBase64 = file => new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => resolve(reader.result);
            reader.onerror = error => reject(error);
        });

        vm.removeFile = function (index) {
            vm.feedbackForm.DeliveryFeedbackImages.splice(index, 1)
            $scope.fileNames.splice(index, 1)
            if ($scope.fileNames.length == 0) { document.getElementById('DeliveryFeedbackImages').value = ""; $scope.filesAreUploaded = false }
        }

        vm.submitForm = function () {
            if (vm.feedbackForm.DeliveryFeedbackImages.length < 1) {
                vm.isError = true;
                vm.errorMessageText = "Please upload at least 1 image of your delivery inside the cooler.";
            }
            else {
                vm.feedbackForm.DeliveryDate = new Date(vm.feedbackForm.DeliveryDate)
                vm.feedbackForm.CustomerId = datacontext.cust.mycust.id;
                vm.feedbackForm.DateUploaded = new Date()
                vm.feedbackForm.Branch = datacontext.cust.mycust.branch
                vm.feedbackForm.Route = datacontext.cust.mycust.routeNumber
                deliveryFeedback.submitFeedback(vm.feedbackForm)

                //clear form and 
                $scope.deliveryFeedbackForm.$setUntouched();
                vm.feedbackForm = {
                    CustomerId: null,
                    DeliveryFeedbackImages: [],
                    DeliveryDate: null,
                    DateUploaded: null,
                    Branch: null,
                    Route: null,
                    Notes: null,
                }
                $scope.fileNames = []
                $scope.filesAreUploaded = false
            }
        }

        ;(function activate() {
            common.$broadcast(config.events.spinnerToggle, { show: true });

            common.activateController([datacontext.primeCustomer()], controllerId)
                .then(function () {
                    // Now the customer context is loaded.
                    setPastDeliveryDates()
                });
        })();
    }

})();


;
(function () {
    "use strict";
    var controllerId = "discountController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$state", "$http", "$filter", "config", "common", "datacontext", "authService", discountController]);

    function discountController($scope, $state, $http, $filter, config, common, datacontext, authService) {

        var vm = this;

        vm.showDeliveryDiscount = function () { return false; };
        vm.showDollarsOffDiscount = function () { return false; };

        vm.hideOneTimeModal = datacontext.hideOneTimeDeliveryDiscountModal;

        vm.cancelOneTimeModal = function () {
            vm.hideOneTimeModal = datacontext.hideOneTimeDeliveryDiscountModal = true;
        };

        vm.discount = {
            delivery: {
                target: 0,
                spent: 0,
                remaining: 0
            },
            dollarsOff: {
                target: 0,
                spent: 0,
                remaining: 0,
                //type: 0,
                //discountAmount: 0,
                discountAmountFormatted: ''
            }, 
            graduated: {
                productGroups: [{
                    target: 0,
                    description: ''
                }],
                spent: 0,
                remaining: 0,
            }
        }

        vm.achieved = function () {
            return (vm.discount.delivery.spent >= vm.discount.delivery.target) || datacontext.cust.mycust.removedOOSProduct;
        };

        vm.dollarsOffAchieved = function () {
            return vm.discount.dollarsOff.spent >= vm.discount.dollarsOff.target;
        };

        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal) {
                var c = datacontext.cust.mycust;

                vm.showDeliveryDiscount = function () {
                    return c.hasDeliveryDiscount && c.slidingDeliveryDiscountTarget > 0;
                }

                vm.discount.delivery.target = datacontext.cust.mycust.slidingDeliveryDiscountTarget;
                vm.discount.delivery.remaining = vm.discount.delivery.target - vm.discount.delivery.spent;

                vm.discount.dollarsOff.target = datacontext.cust.mycust.slidingDollarOffDiscountTarget;
                vm.discount.dollarsOff.remaining = vm.discount.dollarsOff.target - vm.discount.dollarsOff.spent;
                vm.discount.dollarsOff.discountAmountFormatted = datacontext.cust.mycust.dollarOffAmountFormatted;
               
                vm.showDollarsOffDiscount = function () {
                    return c.hasDollarsOffDiscount && c.slidingDollarOffDiscountTarget > 0 && vm.discount.dollarsOff.discountAmountFormatted != '';
                }

                vm.discount.graduated.productGroups = datacontext.cust.mycust.slidingGraduatedDiscountTarget;

                vm.showGraduatedDiscount = function () {
                    return c.hasGraduatedDiscount &&
                        //c.slidingGraduatedDiscountTarget > 0 && 
                        vm.discount.graduated.productGroups.length > 0;
                }
            }
        });

        $scope.$watch(function () { return datacontext.order.orderTotals }, function (oldVal, newVal) {

            if (oldVal) {
                var next = datacontext.order.orderTotals.nextTotals
                if (next) {

                    vm.discount.delivery.spent = next.subtotal + next.discount; //discount will be negative // - next.deliveryCharge;
                    vm.discount.delivery.remaining = vm.discount.delivery.target - vm.discount.delivery.spent;

                    vm.discount.dollarsOff.spent = next.subtotal + next.discount - next.specialPromotionsDiscount; //discount will be negative // - next.deliveryCharge;
                    vm.discount.dollarsOff.remaining = vm.discount.dollarsOff.target - vm.discount.dollarsOff.spent;

                    vm.discount.graduated.spent = next.subtotal + next.discount; //discount will be negative // - next.deliveryCharge;
                    vm.discount.graduated.remaining = vm.discount.graduated.target - vm.discount.graduated.spent;
                }
            }
        });

        activate();
        function activate() {
            common.activateController([
                datacontext.primeCustomer().then(function () {
                    //var c = datacontext.cust.mycust;

                    //vm.showDeliveryDiscount = function () {
                    //    return c.hasDeliveryDiscount && c.slidingDeliveryDiscountTarget > 0;
                    //}

                    //vm.discount.delivery.target = datacontext.cust.mycust.slidingDeliveryDiscountTarget;
                    //vm.discount.delivery.remaining = vm.discount.delivery.target - vm.discount.delivery.spent;


                    //vm.discount.dollarsOff.target = datacontext.cust.mycust.slidingDollarOffDiscountTarget;
                    //vm.discount.dollarsOff.remaining = vm.discount.delivery.target - vm.discount.delivery.spent;
                    //vm.discount.dollarsOff.discountAmountFormatted = datacontext.cust.mycust.dollarOffAmountFormatted;

                    //vm.showDollarsOffDiscount = function () {
                    //    return c.hasSlidingDollarOffDiscount && c.slidingDollarOffDiscountTarget > 0 && vm.discount.dollarsOff.discountAmountFormatted != '';
                    //}

                    //vm.discount.graduated = datacontext.cust.mycust.slidingGraduatedDiscountTarget;

                    //vm.showGraduatedDiscount = function () {
                    //    return c.hasSlidingGraduatedDiscount && c.slidingGraduatedDiscountTarget > 0 && vm.discount.graduatedProductGroup.length > 0;
                    //}
                })
            ], controllerId);
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "eGiftCardController";

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$rootScope"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "$filter"
            , "$http"
            , "config"
            , "common"
            , "datacontext"
            , "authService"
            , "$q"
            , "eGiftCardService"
            , eGiftCardController]);

    function eGiftCardController(
        $stateParams
        , $rootScope
        , $scope
        , $state
        , $timeout
        , $window
        , $filter
        , $http
        , config
        , common
        , datacontext
        , authService
        , $q
        , eGiftCardService) {

        var vm = this;
        vm.giftCardHistory = true;
        vm.giftCardsPurchased = false;

        vm.customerGiftCards = [];
        vm.totalGiftCardBalance = 0.00;
        vm.showLimitModal = false;
        vm.toggleLimitModal = toggleLimitModal;
        
        function toggleLimitModal() {
            vm.showLimitModal = !vm.showLimitModal;
        }
        
        vm.changeGiftCardPreference = function () {
            if (vm.giftCardPreferences.limitGiftCardAmount !== null) {
                vm.limitButton = false;
            }
            var url = "/api/egift-card/preferences/";
            
            $http.post(url, vm.giftCardPreferences).then(function (response) {
                loadCustomerGiftCardPreferences();
            });

        };
        
        vm.doNotLimitGiftCard = function () {
            if (vm.limitButton) {
                vm.giftCardPreferences.limitGiftCardAmount = null;
            }
            else {
                vm.giftCardPreferences.limitGiftCardAmount = 5;

            }
            vm.changeGiftCardPreference();
        }
        
        function getTotalGiftCardBalance() {
            var deferred = $q.defer();
            var url = "/api/egift-card/balance/"
            $http.get(url).then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }
        
        function getGiftCardPreferences() {
            var deferred = $q.defer();
            var url = "/api/egift-card/preferences/"
            $http.get(url).then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }
        
        function loadCustomerGiftCardPreferences() {
            getGiftCardPreferences().then(function (response) {
                vm.giftCardPreferences = response.data;
                if (vm.giftCardPreferences.limitGiftCardAmount !== null) {
                    vm.limitButton = false;
                }
                else {
                    vm.limitButton = true;
                }
            });
        }
        
        function loadCustomerGiftCards() {
            getCustomerGiftCards().then(function (response) {
                vm.customerGiftCards = filterGiftCards(response.data);
                for (var i = 0; i < vm.customerGiftCards.length; i++) {
                    vm.customerGiftCards[i].action = "Details [+]";

                }
            });
            getTotalGiftCardBalance().then(function (response) {
                vm.totalGiftCardBalance = response.data;
            });
            getCustomerPurchaseOrders().then(function (response) {
                vm.customersPurchasedGiftCards = response.data;
                for (var i = 0; i < vm.customersPurchasedGiftCards.length; i++) {
                    vm.customersPurchasedGiftCards[i].action = "Details [+]";
                }
            });
        }
        
        function filterGiftCards(eGiftCards) {
            var emptyGiftCards = eGiftCards.filter(function (gc) {
                return gc.balance == 0;
            });
            var gcWithValues = eGiftCards.filter(function (gc) {
                return gc.balance > 0;
            });
            var filteredGiftCards = [];
            for (var i = 0; i < gcWithValues.length; i++) {
                filteredGiftCards.push(gcWithValues[i]);
            }
            for (var i = 0; i < emptyGiftCards.length; i++) {
                filteredGiftCards.push(emptyGiftCards[i]);
            }

            return filteredGiftCards;

            
        }
        
        vm.toggleHistory = function (gc) {
            if (gc.action == "Details [+]") {
                getGiftCardTransactions(gc.id).then(function (response) {
                    gc.currentGiftCardHistory = response.data;
                });
                gc.action = "Details [-]";

            }
            else if (gc.action == "Details [-]") {
                gc.currentGiftCardHistory = [];
                gc.action = "Details [+]";
            }
          
        };

        function getGiftCardTransactions(id) {
            var deferred = $q.defer();
            var url = "/api/egift-card/cards/" + id + "/ledger-entries";
            $http.get(url).then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }

        function getCustomerGiftCards() {
            var deferred = $q.defer();

            $http.get('/api/egift-card/cards/').then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }
        
        function activate() {
            loadCustomerGiftCards();
            loadCustomerGiftCardPreferences();
        }
        
        activate();

        vm.togglePOHistory = function (po) {
            if (po.action == "Details [+]") {
                getGiftCardPODetails(po.id).then(function (response) {
                    po.currentPurchaseOrderHistory = response.data;
                });
                po.action = "Details [-]";

            }
            else if (po.action == "Details [-]") {
                po.currentPurchaseOrderHistory = [];
                po.action = "Details [+]";
            }

        };
        
        function getCustomerPurchaseOrders() {
            var deferred = $q.defer();
            $http.get('/api/egift-card/purchase-orders/').then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });
            return deferred.promise;
        }
        
        function getGiftCardPODetails(id) {
            var deferred = $q.defer();

            var url = "/api/egift-card/purchase-orders/" + id + "/details/";
            $http.get(url).then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }

        $scope.claimCode = "";
        vm.claimCodeError = null;
        vm.claimCodeLoading = false;
        
        vm.claimState = {
            loading: false,
            error: null,
            completed: false
        }
        
        vm.addGiftCardToAccount = function(claimCode) {
            if (claimCode.length < 16) {
                vm.claimCodeError = "Invalid Claim Code";
                return;
            }
            
            vm.claimCodeLoading = true;
            eGiftCardService
                .getUnclaimedEGiftCardStatus(claimCode)
                .then(function(response) {
                    if (response && response.data && response.data.isValid) {
                        vm.claimCodeError = null;
                        $state.go("shopping.claimEGiftCard", { claimCode })
                        
                    } else {
                        vm.claimCodeError = "Invalid Claim Code"
                    }
                })
                .catch(function(error) {
                    vm.claimCodeError = "System error, please try again later."
                })
                .finally(function() {
                    vm.claimCodeLoading = false;
                });
        }
    }
})();
;
(function () {
    var controllerId = 'farmController';

    angular.module('app-hd').controller(controllerId,
	['$scope', '$http', farmController]);


    function farmController($scope, $http) {


        var vm = this;
        return $http.get("api/Farm/GetFarmsInSequence")
                    .success(farmQuerySucceeded);


        // Sets the retrieval of the farms in the farms object
        function farmQuerySucceeded(result) {
            $scope.farms = result;
        }

        $scope.getFarms = function () {
            return $scope.farms;
        }


        //var vm = this;
        //vm.farms = [
        //    { 'name': 'Vanderstappen Farm', 'location': 'Hebron, IL' },
        //    { 'name': 'Peterson Farm', 'location': 'Hebron, IL' },
        //    { 'name': 'Lois Holsteins', 'location': 'Burlington, WI' },
        //    { 'name': 'Diedrich\'s Production Unlimited', 'location': 'Twin Lakes, WI' },
        //    { 'name': 'DeBell Dairy', 'location': 'Salem, WI' },
        //    { 'name': 'DeBell Dairy', 'location': 'Kansasville, WI' },
        //    { 'name': 'Davis Farm', 'location': 'Sharon, WI' },
        //    { 'name': 'Koehl Farm', 'location': 'Darien, WI' },
        //    { 'name': 'Funk\'s Farview Acres', 'location': 'Janesville, WI' },
        //    { 'name': 'Hurtgen Farm', 'location': 'Elkhorn, WI' },
        //    { 'name': 'Lauderdale Farm', 'location': 'Elkhorn, WI' },
        //    { 'name': 'Friemoth Farm', 'location': 'Elkhorn, WI' },
        //    { 'name': 'Lauber Farm', 'location': 'Union Grove, WI' },
        //    { 'name': 'Ransom Farm', 'location': 'Avalon, WI' },
        //];
    }
})();;
(function () {
    var controllerId = 'feedbackController';
    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , '$http'
            , "$state"
            , "$window"
            , "$cookies"
            , "$filter"
            , "datacontext"
            , "authService"
            , "common"
            , feedback]);

    function feedback(
         $stateParams
        , $scope
        , $http
        , $state
        , $window
        , $cookies
        , $filter
        , datacontext
        , authService
        , common) {

        var vm = this;
        var $q = common.$q;

        vm.initializeFeedbackPage = initializeFeedbackPage;
        vm.showFeedbackModal = _showFeedbackModal;
        vm.submitFeedback = _submitFeedback;
        vm.hideFeedbackBar = _hideFeedbackBar;
        vm.open = _open;
        vm.feedbacktypechanged = _feedbacktypechanged;
        vm.preventkeypress = _preventkeypress;
        vm.feedback = {};

        vm.showRelatesToSelector = _showRelatesToSelector;
        vm.showStoreFeedback = _showStoreFeedback;
        vm.showOtherFeedback = _showOtherFeedback;

        vm.submitLocation = _submitLocation;

        vm.hstep = 1;
        vm.mstep = 15;

        vm.showModal = false;
        vm.sendSuccess = false;
        vm.isAuth = authService.authentication.isAuth;
        vm.showFeedbackBar = true;
        vm.feedbackHidden = false;
        function resetdefaults() {
            vm.feedback = {};
            vm.dairyStore = "";
            vm.feedbackType = "null";
        }
        function _showFeedbackModal() {
            showFeedbackBar();

            //$("#feedbackForm").validate().resetForm();
            if (datacontext.cust.mycust === null ||
                !datacontext.cust.mycust.eMail) {
                var hash = $state.$current.url.prefix;
                var id = $state.params.id || ""
                var productViewId = $state.params.productViewId || '';
                var subViewId = $state.params.subViewId || '';
                if (hash.indexOf('/home-delivery') >= 0) {
                    return $state.go('sign-in', {
                        rqst: $state.current.name,
                        rqstParams: {
                            id: id,
                            productViewId: productViewId,
                            subViewId: subViewId
                        }
                    });
                    
                } else {
                    return $window.location = 'home-delivery/log-in';
                    
                }
            }
            vm.showEmailField = !(datacontext.cust.mycust.eMail && datacontext.cust.mycust.eMail !== '');
            vm.feedback.customerFeedbackEmail = datacontext.cust.mycust.eMail;
            vm.isAuth = authService.authentication.isAuth;
            vm.showModal = true;
            vm.sendSuccess = false;
            resetdefaults();

            $("label.customErrorClass").text("");

            initializeFormValidation();
        }
        function _preventkeypress($event) {
            $event.preventDefault();
        }
        function _submitFeedback() {

            initializeFormValidation();

            if ($("#feedbackForm").valid()) {
                if (vm.isAuth) {
                    vm.feedback.customerNumber = datacontext.cust.mycust.customerNumber;
                    vm.feedback.userName = datacontext.cust.mycust.userName;
                }
                vm.sendSuccess = datacontext.cust.postCustomerFeedback(vm.feedback);
                vm.sendSuccess = true;
                if (vm.sendSuccess) {
                    vm.feedback = {};
                }
            }
        }

        function _hideFeedbackBar() {
            common.setCustomerSettingsCookie("showFeedbackBar", false, 365);
            vm.showFeedbackBar = false;
        }


        function showFeedbackBar() {
            common.setCustomerSettingsCookie("showFeedbackBar", true, 365);
            vm.showFeedbackBar = true;
        }

        function getFeedbackButtonCookie() {
            var obj = common.getCustomerSettingsCookie();

            if (obj.showFeedbackBar === false) {
                vm.showFeedbackBar = false;
            }
            else {
                vm.showFeedbackBar = true;
            }
            if (window.location.href.indexOf('happylicious-rewards') != -1) {
                vm.feedbackHidden = true;
            }
            else {
                vm.feedbackHidden = false;

            }
        }

        function initializeFormValidation() {
            $("#feedbackForm").validate({
                errorClass: 'customErrorClass'
            });
        }
        function _open($event) {
            $event.preventDefault();
            $event.stopPropagation();

            vm.opened = true;
        };

        function _feedbacktypechanged() {
            if (vm.feedbackType === "HD") {
                vm.feedback.customerFeedbackType = "HomeDelivery";
            } else if (vm.feedbackType === "DS") {
                vm.feedback.customerFeedbackType = "DairyStores";
            } else {
                vm.feedback.customerFeedbackType = "Other";
            }
        }

        activate();

        function activate() {
            getFeedbackButtonCookie();
            resetdefaults();
        }

        function initializeFeedbackPage() {
            getFeedbackButtonCookie();
            initializeFormValidation();
            _feedbacktypechanged();
        }

        function _submitLocation() {
            var store = datacontext.store.getSelectedStore();
            window.location = store.feedbackUrl;
        }

        function _showRelatesToSelector(){
            return vm.feedbackType === 'null';
        }
        function _showStoreFeedback() {
            return vm.feedbackType === 'DS';
        }

        function _showOtherFeedback() {
            return !vm.showRelatesToSelector() && !vm.showStoreFeedback();
        }
    }
})();;
(function () {

    var app = angular.module("app-hd");

    app.controller('fileUpload', [
        '$scope', 'Upload', '$timeout',
        function ($scope, Upload, $timeout) {
            
            $scope.$watch('files', function () {
                $scope.upload($scope.files);
            });
            $scope.$watch('file', function () {
                if ($scope.file != null) {
                    $scope.files = [$scope.file];
                }
            });
            $scope.log = '';
            $scope.inx = Date.now();
            $scope.upload = function (files) {
                if (files && files.length) {
                         $scope.$parent.vm.imageSrc = [];
                       
                    var pid = $scope.$parent.vm.selectedId;
                    var fileId = files[0];
                    $scope.$parent.vm.imageSrc = [];
                    var idType = 'category';
                    var parentName = $scope.$parent.vm.controllerName;
                    if (parentName == 'productSetupController') {
                        idType = 'product;';
                        fileId = pid;///$scope.$parent.vm.selectProduct.id;
                    } else {
                        fileId =  pid;//$scope.$parent.vm.categoryDC.selectedCategory.id;
                    }
                    $scope.inx++;

                    for (var i = 0; i < files.length; i++) {
                        var file = files[i];
                        if (!file.$error) {
                            Upload.upload({
                                url: 'api/Products/picUploader?fileId=' + pid + '&idtype=' + idType,
                                data: {
                                    name:file.name,
                                    fileInput: file
                                    //file: file
                                }
                            }).then(function(resp) {
                               

                                $timeout(function() {
                                    $scope.log = 'file: ' +
                                        //resp.config.data.file.name +
                                        ', Response: ' + JSON.stringify(resp.data) +
                                        '\n' + $scope.log;
                                });
                                $scope.$parent.vm.imageSrc = [pid];
                         
                            }, null, function(evt) {
                                    var progressPercentage = parseInt(100.0 *
                                        evt.loaded / evt.total);
                                    $scope.log = 'progress: ' + progressPercentage +
                                        '% ' + evt.config.data.name + '\n' +
                                        $scope.log;
                                });
                            }
                    }
                }
            };
        }
    ]);


})();
(function () {
    var controllerId = 'findStoreController';
    angular.module('app-hd').controller(controllerId,
        ['$scope', '$rootScope', '$q', '$http', '$state', '$window', '$anchorScroll', 'common', 'config', 'uiGmapGoogleMapApi', 'uiGmapIsReady', findStoreController]);

    function findStoreController($scope, $rootScope, $q, $http, $state, $window, $anchorScroll, common, config, uiGmapGoogleMapApi, uiGmapIsReady, findAStore) {
        var vm = this;
        vm.retail = false;

        vm.setQueryParam = function () {
            vm.retail = $state.current.data.retail;

            if (vm.retail) {

                vm.request = {
                    address: "",
                    oberweisStores: false,
                    groceryStores: true
                }
            }
            else {
                var storageRequest = JSON.parse(sessionStorage.getItem('findStoreRequest'));
                //if there is a session storage request, the route comes from the dropdown controller
                if (storageRequest != null) {
                    vm.request = {
                        address: storageRequest.address,
                        oberweisStores: storageRequest.oberweisStores,
                        groceryStores: storageRequest.groceryStores
                    }
                    sessionStorage.removeItem('findStoreRequest');
                    $scope.$watch(function () { return $window.document.getElementById("address-search-input") }, function () {
                        if ($window.document.getElementById("address-search-input") != null) {
                            $window.document.getElementById("address-search-input").value = vm.request.address;
                        }

                    });

                }
                else {
                    vm.request = {
                        address: "",
                        oberweisStores: true,
                        groceryStores: false
                    }
                }

            }
        }
        vm.searchBox = {
            template: 'searchbox.tpl.html',
            options: {
                autocomplete: true,
                componentRestrictions:
                {
                    'country': ['us']
                },
                types: ['(regions)']
            }
        }
        vm.autocompleteEvents = {
            "place_changed": function (autocompelte) {
                var place = autocompelte.getPlace();
                var location = place.geometry.location;
                var pos = { coords: { latitude: location.lat(), longitude: location.lng() } }
                vm.request.address = place.formatted_address;
                centerMap(pos);
                findStores(pos);

            }

        }
        vm.setQueryParam();


        vm.position = { coords: { latitude: 41.79818400000001, longitude: -88.348431 } };
        vm.map = {
            center: { latitude: vm.position.coords.latitude, longitude: vm.position.coords.longitude }
            , zoom: 11
            , options: { scrollwheel: false }
            , events: {
                dragend: function (data) {
                    var position = {
                        coords: {
                            latitude: data.center.lat(),
                            longitude: data.center.lng()                 
                        }
                    }
                    var geocoder = new google.maps.Geocoder();
                    var latlng = {
                        lat: position.coords.latitude,
                        lng: position.coords.longitude
                    }
                    geocoder
                        .geocode({ location: latlng })
                        .then((response) => {
                            var num = response.results.length;
                            for (var i = 0; i < num; i++) {
                                if (response.results[i].types.includes("locality")) {
                                    vm.request.address = response.results[i].formatted_address;
                                    $window.document.getElementById("address-search-input").value = response.results[i].formatted_address;

                                }
                            }
                        });
                    findStores(position);
                    centerMap(position);
                },
                zoom_changed: function (data) {
                    var position = {
                        coords: {
                            latitude: data.center.lat(),
                            longitude: data.center.lng()
                        }
                    }
                    var geocoder = new google.maps.Geocoder();
                    var latlng = {
                        lat: position.coords.latitude,
                        lng: position.coords.longitude
                    }
                    geocoder
                        .geocode({ location: latlng })
                        .then((response) => {
                            var num = response.results.length;
                            for (var i = 0; i < num; i++) {
                                if (response.results[i].types.includes("locality")) {
                                    vm.request.address = response.results[i].formatted_address;
                                    $window.document.getElementById("address-search-input").value = response.results[i].formatted_address;

                                }
                            }
                        });
                    if (data.zoom > vm.map.zoom) {
                        vm.distanceSelected = vm.distanceSelected / 2
                    }
                    if (data.zoom < vm.map.zoom) {
                        vm.distanceSelected = vm.distanceSelected * 2
                    }
                    findStores(position);
                    centerMap(position);
                }
            }
        };

        vm.distanceOptions = [5, 10, 20, 40, 80, 160, 320];
        vm.distanceSelected = 20;
        vm.mobileBrakepoint = 680;
        vm.showMap = true;
        vm.stores = { oberweis: {}, retail: {}, loaded: false };


        vm.canGeolocate = canGeolocate;
        vm.findStores = findStores;
        vm.gotoGeolocation = gotoGeolocation;
        vm.gotoAddress = gotoAddress;
        vm.gotoMarker = gotoMarker;
        vm.showNoStores = showNoStores;

        vm.windowOptions = {
            pixelOffset: {
                height: -30,
                width: 0
            }
        };
        uiGmapGoogleMapApi.then(function (maps) {
            vm.refreshGeoLocation();
        });

        vm.refreshGeoLocation = function () {
            if (vm.request && vm.request.address) {
                gotoAddress();
            } else {
                if (canGeolocate()) {
                    gotoGeolocation();
                }
            }
        }


        vm.store = {};
        vm.retailer = {};

        vm.markerEvents = {
            click: function (gMarker, eventName, store) {
                if ($(window).width() > vm.mobileBrakepoint) {
                    $anchorScroll.yOffset = $('#find-a-store-list').position().top;
                    $anchorScroll();
                }
                gotoMarker(store);
            }
        };

        function gotoGeolocation() {
            geolocate().then(function (position) {
                var geocoder = new google.maps.Geocoder();
                var latlng = {
                    lat: position.coords.latitude,
                    lng: position.coords.longitude
                }
                geocoder
                    .geocode({ location: latlng })
                    .then((response) => {
                        var num = response.results.length;
                        for (var i = 0; i < num; i++) {
                            if (response.results[i].types.includes("locality")) {
                                vm.request.address = response.results[i].formatted_address;
                                $window.document.getElementById("address-search-input").value = response.results[i].formatted_address;

                            }
                        }
                    });
                centerMap(position);

                findStores(position);
            }, function () {
                centerMap(vm.position);
                findStores(vm.position);
            });
        }

        function centerMap(position) {
            vm.map.center.latitude = position.coords.latitude;
            vm.map.center.longitude = position.coords.longitude;
        }

        function canGeolocate() {
            return ("geolocation" in navigator);
        }

        function findLocation(address) {
            var geocoder = new google.maps.Geocoder();
            var coords = vm.map.center;

            var d = $q.defer();

            if (address == '') {
                d.reject("Address can't be empty.");
            } else {
                geocoder.geocode({ 'address': address }, function (results, status) {
                    if (status == google.maps.GeocoderStatus.OK) {
                        var location = results[0].geometry.location
                        d.resolve({ coords: { latitude: location.lat(), longitude: location.lng() } });
                    }
                    else {
                        var reason = "We're sorry.  You provided invalid information.  Please enter a valid address or zip code.";
                        d.reject(reason);
                        console.log("reject reason in findLocation: " + reason);
                    }
                });
            }

            return d.promise;
        }

        function gotoAddress() {

            if (vm.request.address) {
                findLocation(vm.request.address).then(function (position) {
                    centerMap(position);
                    findStores(position);
                }, function (reason) {
                    alert(reason);
                });
            }
            else {
                vm.gotoGeolocation();
            }
        }

        function gotoMarker(store) {
            vm.showMap = true;
            $("html, body").animate({ scrollTop: $("#map-container").offset().top - 120 }, 500);

            if (vm.store) {
                vm.store.show = false;
            }
            if (vm.retailer) {
                vm.retailer.show = false;
            }
            store.show = true;
            if (store.isOberweis) {
                vm.store = store;
            }
            else {
                vm.retailer = store;
            }
        }

        $scope.oberweisStores = [];
        $scope.retailStores = [];

        function findStores(position) {
            var data = {
                latitude: position.coords.latitude,
                longitude: position.coords.longitude,
                searchOberweis: vm.request.oberweisStores,
                searchRetail: vm.request.groceryStores,
                distance: vm.distanceSelected
            };

            $http.post('api/StoreFinder', data).success(
                function (response) {
                    vm.stores.oberweis = response.oberweis;
                    vm.stores.retail = response.retail;

                    angular.forEach(vm.stores.oberweis, function (store, key) {
                        store.id = 'oberweis.' + key;
                        store.isOberweis = true;
                        store.icon = $scope.CDNImageBaseURL + '/website/images/map-icon-store.png';
                        store.closeClick = function () {
                            store.show = false;
                        };
                    });
                    angular.forEach(vm.stores.retail, function (store, key) {
                        store.id = 'retail.' + key;
                        store.isOberweis = false;
                        store.icon = $scope.CDNImageBaseURL + '/website/images/map-icon-retailer.png';
                        store.closeClick = function () {
                            store.show = false;
                        };
                    });
                    vm.stores.loaded = true;
                    $scope.oberweisStores = vm.stores.oberweis;
                    $scope.retailStores = vm.stores.retail;
                });
        }

        function geolocate() {
            var d = $q.defer();
            navigator.geolocation.getCurrentPosition(d.resolve, d.reject);
            return d.promise;
        }

        function showNoStores() {
            return !vm.stores.retail.length > 0 && !vm.stores.oberweis.length > 0 && vm.stores.loaded
        }
    }
})();;
(function () {
    var controllerId = 'findStoreDropDownController';
    angular.module('app-hd').controller(controllerId,
                                       ['$scope', '$rootScope', '$q', '$http', '$location', '$state', '$window', '$anchorScroll', 'common', 'config', 'uiGmapGoogleMapApi', 'datacontext', findStoreDropDownController]);

    function findStoreDropDownController($scope, $rootScope, $q, $http, $location, $state, $window, $anchorScroll, common, config, uiGmapGoogleMapApi, datacontext) {
        var vm = this;
        vm.gotoFindStore = gotoFindStore;
        vm.initAutocomplete = initAutocomplete;
        vm.initAutocompleteGroceryStore = initAutocompleteGroceryStore;

        vm.request = {
            address: "",
            oberweisStores: true,
            groceryStores: false
        }


        vm.showFindStore = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }
        function initAutocompleteGroceryStore() {
            var input = $window.document.getElementById('addressBox');
            var autocomplete = new google.maps.places.Autocomplete(input, {
                componentRestrictions:
                {
                    'country': ['us']
                },
                types: ['(regions)']
            });
            autocomplete.addListener('place_changed', function () {
                var place = autocomplete.getPlace();
                var address = place.formatted_address;
                var url = "/search/find-a-store";
                var findStoreRequest =
                {
                    address: address,
                    oberweisStores: false,
                    groceryStores: true
                };
                sessionStorage.setItem('findStoreRequest', JSON.stringify(findStoreRequest));
                $window.location = url

            });
        }
        function initAutocomplete(findPage) {
            if (findPage) {
                var input = $window.document.getElementById('address1');
                var oberweisStore = $window.document.getElementById("oberweisStores1").checked;
                var groceryStore = $window.document.getElementById("groceryStores1").checked;
                var insertType = "Store Search";


            }
            else {
                var input = $window.document.getElementById('address');
                var oberweisStore = $window.document.getElementById("oberweisStores").checked;
                var groceryStore = $window.document.getElementById("groceryStores").checked;
            }

            var autocomplete = new google.maps.places.Autocomplete(input, {
                componentRestrictions:
                {
                    'country': ['us']
                },
                types: ['(regions)']
            });
            autocomplete.addListener('place_changed', function () {

                if (findPage) {
                    common.insertLinkTrack(insertType).then(function (result) {
                        var place = autocomplete.getPlace();
                        var address = place.formatted_address;
                        var url = "/search/find-a-store";
                        var findStoreRequest =
                        {
                            address: address,
                            oberweisStores: oberweisStore,
                            groceryStores: groceryStore
                        };
                        sessionStorage.setItem('findStoreRequest', JSON.stringify(findStoreRequest));
                        $window.location = url;
                    });
                }
                else {
                    var place = autocomplete.getPlace();
                    var address = place.formatted_address;
                    var url = "/search/find-a-store";
                    var findStoreRequest =
                    {
                        address: address,
                        oberweisStores: oberweisStore,
                        groceryStores: groceryStore
                    };
                    sessionStorage.setItem('findStoreRequest', JSON.stringify(findStoreRequest));
                    $window.location = url;
                }


            });
        }


        function gotoFindStore() {
            //$window.sessionStorage.setItem("findStoreRequest", JSON.stringify(vm.request));
            //var url = "/search/find-a-store?address=" + vm.request.address + "&oberweisStores=" + vm.request.oberweisStores + "&groceryStores=" + vm.request.groceryStores;
            //$window.location = url

            //$state.go('find-a-store', {
            //    'address': vm.request.address,
            //    'oberweisStores': vm.request.oberweisStores,
            //    'groceryStores': vm.request.groceryStores
            //}, { reload: true });
        }
    }
})();;
(function () {
    var controllerId = 'fountainMenuController';
    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , "$state"
            , "datacontext"
            , "authService"
            , "common"
            , fountainMenu]);

    function fountainMenu(
        $stateParams
        , $scope
        , $state
        , datacontext
        , authService
        , common) {
        var vm = this;

        vm.showNutritionModal = false;
        vm.showAlergen = false;

        //vm.nutrition = {};

        vm.openNutritionModal = function (product) {
            vm.showNutritionModal = true;
            vm.showAlergen = false;

            vm.selectedSizeIndex = 0;
            vm.selectedTypeIndex = 0;
            vm.selectedType = product.nutrition[0].type;

            vm.nutrition = product.nutrition;

            //console.log(vm.nutrition)
        };

        vm.getProductNutritionInfo = function (productId) {
            datacontext.products.getFountainMenuProductNutrition(productId).then(function (result) {
                vm.showNutritionModal = true;
                vm.showAlergen = false;
                vm.selectedSizeIndex = 0;
                vm.selectedTypeIndex = 0;
                vm.selectedType = result[0].type;

                vm.nutrition = result;
            });
        };

        vm.getProductUrl = function (categoryName, productName) {
            return ("/fountain-menu/" + categoryName + "/" + productName).toLowerCase();
            //.replace(/ /g, '-')
        }

        vm.showAlergenFromModal = function (show) {
            vm.showAlergen = show;
            $(".modal-nutritional").scrollTop(0);
        }

        vm.categories = [];
        //activate();

        vm.initializeSlider = function () {
            $(".carousel").bind("slid.bs.carousel", "", function () {
                checkItem(this);
            });// on caroussel move

            $(document).ready(function () {
                $('.carousel').carousel({
                    interval: 0,
                    wrap: false
                })
            });

            function checkItem(carousel) {
                var $this = $(carousel);

                if ($this.find(".carousel-inner .item:first").hasClass("active")) {
                    $this.find(".left").hide();
                    $this.find(".right").show();
                } else if ($this.find(".carousel-inner .item:last").hasClass("active")) {
                    $this.find(".right").hide();
                    $this.find(".left").show();
                } else {
                    $this.find(".carousel-control").show();
                }
            };
        }

        vm.getProducts = function () {

            datacontext.products.getFountainMenuProducts().then(function (data) {
                vm.categories = data;
            })


        }
    }
})();;
(function() {
    "use strict";
    const controllerId = "giftCardController";

    angular.module("app-hd").controller(controllerId, ["$scope", "giftCardService", giftCardController]);

    function giftCardController($scope, giftCardService) {
        const vm = this;

        vm.loadingGiftCards = true;
        vm.loadingLinkGiftCard = false;
        vm.initialLoading = true;
        vm.loadingValidCardBalance = false;
        vm.cardBalanceLoaded = false;

        vm.showRelinkHelpModal = false;

        vm.giftCards = [];
        vm.validGiftCardBalance = {};
        vm.giftCardRefreshStatus = {};
        vm.linkError = null;
        vm.giftCardNumber = "";
        vm.cardRegCode = "";

        vm.linkGiftCard = linkGiftCard;
        vm.refreshGiftCardStatus = refreshGiftCardStatus;
        vm.getValidCardBalance = getValidCardBalance;

        vm.spinnerOptions = {
            position: "relative",
            radius: 10,
            lines: 7,
            length: 0,
            width: 7.5,
            speed: 1.7,
            corners: 1.0,
            trail: 100,
            color: "#ec1f30"
        };

        vm.buttonSpinnerOptions = {
            position: "relative",
            radius: 6,
            lines: 7,
            length: 0,
            width: 4,
            speed: 1.7,
            corners: 1.0,
            trail: 100,
            color: "#ec1f30"
        };

        activate().then(() => {
            vm.initialLoading = false;
            $scope.$apply();
        });

        async function activate() {
            await loadLinkedGiftCards();
        }

        async function loadLinkedGiftCards() {
            vm.loadingGiftCards = true;
            vm.giftCards = await giftCardService.getLinkedGiftCards();
            vm.loadingGiftCards = false;
            $scope.$apply();
        }

        async function linkGiftCard() {
            vm.linkError = null;
            vm.loadingLinkGiftCard = true;
            const results = await giftCardService.linkGiftCard(vm.giftCardNumber, vm.cardRegCode);
            if (results.success) {
                vm.giftCardNumber = "";
                vm.cardRegCode = "";
                await activate();
            } else {
                vm.linkError = results.message;
            }
            vm.loadingLinkGiftCard = true;
            $scope.$apply();
        }

        async function getValidCardBalance() {
            vm.loadingValidCardBalance = true;
            const validCardBalance = await giftCardService.getValidCardBalance();

            vm.validGiftCardBalance = validCardBalance.reduce((acc, card) => {
                acc[card.id] = card.balance;
                return acc;
            }, {});

            vm.loadingValidCardBalance = false;
            vm.cardBalanceLoaded = true;
            console.log(vm.validGiftCardBalance);
            $scope.$apply();
        }

        async function refreshGiftCardStatus(giftCardId) {
            vm.giftCardRefreshStatus[giftCardId] = {loading: true};
            const result = await giftCardService.refreshGiftCardStatus(giftCardId);
            if (result.success) {
                vm.giftCardRefreshStatus[giftCardId] = {balance: result.data.balance, loading: false};
            } else {
                vm.giftCardRefreshStatus[giftCardId] = {balance: "$0.00", loading: false};
            }
            $scope.$apply();
        }

    }
})();
;
(function () {
    "use strict";
    var controllerId = "historyController";
    angular.module("app-hd").controller(controllerId, ["$state", "$scope", "$http", "config", "common", "datacontext", historyController]);

    function historyController($state, $scope, $http, config, common, datacontext) {
        var vm = this;
        vm.baseUrl = config.baseUrl;

        vm.orderHistoryData = {};

        vm.canSubmit = true;
        //vm.customerDC = datacontext.cust;
        //$scope.customerDC = datacontext.cust;
        $scope.Message = "";
        vm.baseUrl = config.baseUrl;
        vm.showDetailsModal = false;

        vm.rowClicked = function (row) {
            row.expand = !row.expand;
        }

        vm.showDetail = function (h) {
            //console.log(h);
            vm.selectedDetail = h;
            vm.showDetailsModal = true;
        }

        vm.paymentsummary = {};

        activate();
        function activate() {
            common.activateController([
                datacontext.primeProducts(),
					datacontext.order.getOrderHistory(),
				datacontext.cust.getPaymentSummary()

            ], controllerId)
				.then(function (data) {
				    vm.orderHistoryData = datacontext.order.orderHistoryData;
				    vm.paymentsummary = datacontext.cust.paymentsummary;
				});
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "jobPostingController";

    angular.module("app-hd").controller(controllerId,
        ["$http", "$scope", '$timeout', 'Upload', jobPosting]);

    function jobPosting($http, $scope, $timeout, Upload) {
        var vm = this;
        var jobCode = '';
        var status = '';
        var location = '';
        var title = '';
        var email = '';
        var contactEmail = '';
        var senderEmail = '';
        vm.senderEmail = '';
        vm.fileUploadComplete = false;
        vm.showjobPostingPopup = false;
        vm.selectedJob = {};
        vm.jobSenderEmail = '';

        vm.jobs = [];
        var fetchingJobs = false;

        vm.clickedJob = function (job, senderEmail) {
            vm.selectedJob = job;

            // Populate the details of the job
            if (job != null) {
                jobCode = job.jobCode;
                location = job.location;
                status = job.status;
                email = job.contactEmail;
                title = job.title;
                senderEmail = vm.senderEmail;
            }

            vm.showjobPostingPopup = true;
        }

        $scope.uploadFiles = function (files) {

            $scope.files = files;
            if (files && files.length) {
                Upload.upload({
                    url: 'api/JobPosting/SubmitResume?toEmailAddress=' + email + '&applicantEmailAddress=' + vm.senderEmail + '&jobCode=' + jobCode + '&status=' + status + '&location=' + location + '&title=' + title + '&senderEmail=' + senderEmail,
                    data: {
                        files: files
                    }
                }).then(function (response) {
                    $timeout(function () {
                        $scope.result = response.data;
                    });
                }, function (response) {
                    if (response.status > 0) {
                        $scope.errorMsg = response.data;
                    }
                }, function (evt) {
                    $scope.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));

                    vm.selectedJob = {};
                    vm.showjobPostingPopup = false;
                    vm.fileUploadComplete = false;
                    vm.selectedJob = null;
                });
            }
        }


        function readJobPostings() {
            var self = this;

            $http.post("api/JobPosting/GetJobPostings")
                .then(function (response) {
                    angular.copy(response.data, vm.jobs);
                    return;
                },
                function (response) {
                });
        }

        activate();

        function activate() {
            readJobPostings();
        }
    }
})();;
(function() {
    var controllerId = "legacyClaimEGiftCardCodeController";

    angular.module("app-hd").controller(controllerId, ["$scope", "$http", "$stateParams", "legacyEGiftCardService", legacyClaimEGiftCardCodeController]);

    function legacyClaimEGiftCardCodeController($scope, $http, $stateParams, legacyEGiftCardService) {
        var vm = this;
        let claimCode = null;
        vm.loadedDetails = false;
        vm.cardDetails = null;

        vm.claimState = {
            error: null, completed: false, loading: false
        };

        (function activate() {
            claimCode = $stateParams.claimCode;

            legacyEGiftCardService
                .getUnclaimedEGiftCardDetails(claimCode)
                .then(function (response) {
                    if (response.data) {
                        vm.cardDetails = response.data;
                    }
                })
                .catch(function() {
                })
                .finally(function() {
                    vm.loadedDetails = true;
                });
        })();

        vm.applyToAccount = function() {
            vm.claimState.loading = true;
            legacyEGiftCardService
                .applyEgiftCardToAccount(claimCode)
                .then(function() {
                    vm.claimState.error = null;
                    vm.claimState.completed = true;
                })
                .catch(function(error) {
                    console.log("my error", error);
                    vm.claimState.error = error;
                })
                .finally(function() {
                    vm.claimState.loading = false;
                });
        };
    }
})();

;
(function () {
    "use strict";
    angular
        .module("app-hd")
        .controller("locationSelectController", ["$scope", "$state","unauthenticatedBranch", "datacontext", locationSelectController]);

    function locationSelectController($scope, $state , unauthenticatedBranch, datacontext) {
        var vm = this;
        vm.unauthenticatedBranch = unauthenticatedBranch;
        vm.showInitialLocationSelect = false;
        vm.showChangeLocationSelect = false;

        vm.updateCatalog = function () {
            unauthenticatedBranch.state.loadingCatalogUpdate = true;
            unauthenticatedBranch.state.loadingCatalogUpdateError = null;
            datacontext.products.getProductPartialsForPriceCode(
                unauthenticatedBranch.state.selectedLocationBranch.priceSchedule,
                null,
                unauthenticatedBranch.state.selectedLocationBranch.branchNumber
            ).then(function () {
                unauthenticatedBranch.state.loadingCatalogUpdate = true;
            }).catch(function () {
                unauthenticatedBranch.state.loadingCatalogUpdate = false;
                unauthenticatedBranch.state.loadingCatalogUpdateError = "Error product catalog"
            });
        }
        vm.setSeoMetaData = function () {
            $scope.getSeoMetadata("browsing", 7)
        };

        vm.setLocation = function (location) {
            if (!location)
                return
            
            if (location.redirectUrl) {
                window.location.href = location.redirectUrl;
            } else {
                vm.unauthenticatedBranch.state.selectedLocationBranch = location;
            }
        }
        
        $scope.$watch(unauthenticatedBranch.showInitialLocationSelect,
            function (showInitialLocationSelect) {
                vm.showInitialLocationSelect = showInitialLocationSelect;
            });

        $scope.$watch(unauthenticatedBranch.showChangeLocationSelect,
            function (showChangeLocationSelect) {
                vm.showChangeLocationSelect = showChangeLocationSelect;
            }
        );
    }
})();
;
(function () {
    "use strict";
    var controllerId = "lookbookController";

    angular.module("app-hd").controller(controllerId, ["$scope", "$sce", "datacontext", "unauthenticatedBranch", lookbookController]);

    function lookbookController($scope, $sce, datacontext, unauthenticatedBranch) {
        var vm = this;
        var curBranch;

        var lookbookIdByBranchNumber = {
            1: 1,
            7: 1,
            8: 1,
            9: 1,
            10: 1,
            11: 1,
            12: 1,
            445: 1,
            15: 2,
            18: 2,
            19: 3,
        }


        //find out the current branch 
        var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
        if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
            curBranch = datacontext.cust.mycust.branch;
        } else if (selectedBranchLocation !== null) {
            curBranch = selectedBranchLocation.branchNumber;
        }

        //get the look book version based on branch
        var lookbookVersionId = getLookbookVersionIdByBranchId(curBranch);

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (oldVal, newVal) {
            if (oldVal && oldVal.branchNumber !== newVal.branchNumber) {
                curBranch = unauthenticatedBranch.state.selectedLocationBranch.branchNumber;
                lookbookVersionId = getLookbookVersionIdByBranchId(curBranch);
                vm.lookBookUrl = createLookbookUrl()
                vm.lookBookArchive = createLookbookArchive(lookbookVersionId);
                setIframeHeight('menuIframe');
            }
        });
        
        function createLookbookUrl() {
            // return $sce.trustAsResourceUrl("https://79ea073a.flowpaper.com/" + date.getFullYear().toString() + (("0" + (date.getMonth() + 1)).slice(-2)) + lookbookVersionId);
            return $sce.trustAsResourceUrl("https://79ea073a.flowpaper.com/202309" + lookbookVersionId);
        }
        
        function getLookbookVersionIdByBranchId(branchNum) {
            if (lookbookIdByBranchNumber[branchNum] === undefined)
                return 1;
            return lookbookIdByBranchNumber[branchNum];

        }
        vm.replaceLookbookUrl = function (endpoint) {
            if (endpoint != null) {
                //create a new iframe with the src as the replace link
                var ifrm = document.createElement('iframe');
                ifrm.setAttribute('id', 'menuIframe');
                ifrm.setAttribute('allowfullscreen', '');
                ifrm.setAttribute('src', "https://79ea073a.flowpaper.com/" + endpoint);
                //replace the iframe in the browser with the one you created
                document.getElementById('iframeContainer').replaceChild(ifrm, document.getElementById('menuIframe'));
                //resize the iframe in the broswer to fit the screen
                setIframeHeight('menuIframe');       

            }
        };
        
        vm.lookBookArchive = createLookbookArchive(lookbookVersionId);

        function createLookbookArchive(versionNumber) {
            var date = new Date();
            // var month = date.getMonth();
            var month = 8;
            var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]

            var year = date.getFullYear();
            var lookbook = [];


            for (var i = month; i > month - 12; i--) {

                var currentMonth = i;
                var currentYear = year;
                if (i < 0) {
                    currentYear = year - 1;
                    currentMonth = i + 12;
                }

                var name = months[currentMonth] + " " + currentYear;
                var endpoint = currentYear + ("0" + (currentMonth + 1)).slice(-2) + versionNumber;

                lookbook.push({ name, endpoint });

            }
            return lookbook;
        }

        function getDocHeight(doc) {
            doc = doc || document;
            // stackoverflow.com/questions/1145850/
            var body = doc.body, html = doc.documentElement;
            var height = Math.max(body.scrollHeight, body.offsetHeight,
                html.clientHeight, html.scrollHeight, html.offsetHeight);
            if (vm.previousHeight == 0) {
                vm.previousHeight = height;
            }
            if (height == 812) {
                height = 700;
                vm.previousHeight = height;
            }
            //set max height to 730 bc the document that gets rendered when archive is visible is too large 
            else if (height > vm.previousHeight)
            {              
                height = vm.previousHeight;
            }
            return height;
        }

        function getDocWidth(doc) {
            doc = doc || document;
            var body = doc.body, html = doc.documentElement;
            var width = Math.max(body.scrollWidth, body.offsetWidth,
                html.clientWidth, html.scrollWidth, html.offsetWidth);
            return width;
        }

        function setIframeHeight(id) {
            var ifrm = document.getElementById(id);
            ifrm.style.visibility = 'hidden';
            ifrm.style.height = "10px"; // reset to minimal height ...
            ifrm.style.width = "10px";
            ifrm.style.height = getDocHeight(null) - ifrm.offsetTop - 55 + "px";
            ifrm.style.width = getDocWidth(null) + "px";
            ifrm.style.visibility = 'visible';
        }

    }
})();
;
(function () {
    "use strict";
    var controllerId = "mapController";

    angular.module("app-hd").controller(controllerId,
        ["$scope"
            , "datacontext"
            , "uiGmapGoogleMapApi"
            , "uiGmapIsReady"
            , mapController]);

    function mapController(
        $scope
        , datacontext
        , uiGmapGoogleMapApi
        , uiGmapIsReady
        ) {

        var vm = this;

        vm.isNewCustomer = false;
        
        vm.position = { coords: { latitude: 41.79818400000001, longitude: -88.348431 } };

        vm.markers = [];
        vm.map = {
            center: { latitude: vm.position.coords.latitude, longitude: vm.position.coords.longitude }
            , zoom: 16
            , options: { scrollwheel: true, mapTypeId: 'satellite' }
            , control: {}
        };

        uiGmapGoogleMapApi.then(function (maps) {

        });

        if (datacontext.isNewCustomer) {
            activate();
        }

        function activate() {
            vm.isNewCustomer = datacontext.isNewCustomer;

            datacontext.primeCustomer().then(function () {
                vm.markers = [];

                if (datacontext.cust.mycust.stdAddress) {
                    var lat = datacontext.cust.mycust.stdAddress.latitude;
                    var lng = datacontext.cust.mycust.stdAddress.longitude;

                    vm.markers.push({
                        id: 1
                        , coordinates: { latitude: lat, longitude: lng }
                        , icon: $scope.CDNImageBaseURL + "/website/images/transparent.png"
                    });

                    vm.map.center.latitude = lat;
                    vm.map.center.longitude = lng;

                }
                uiGmapIsReady.promise().then(function (maps) {
                    vm.map.control.refresh();
                });

            });

            return;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "marketingPopupController";

    angular.module("app-hd").controller(controllerId, ["$scope", "authService", "common", "datacontext", catalogPopupController]);

    function catalogPopupController($scope, authService, common, datacontext) {
        var now = new Date();

        var vm = this;

        // The order of these matter, if you edit the order, shopping-marketing-popup.html needs to be updated too.
        vm.modals = [
            {
                name: "catalog",
                frequency: "first_day_month",
                requireAuth: false,
                enabled: function () {
                    return false;
                },
                show: false
            },
            {
                name: "referral",
                frequency: "every_14_days",
                requireAuth: true,
                enabled: function (datacontext) {
                    var mycust = datacontext.cust.mycust;
                    return mycust.referralProgram && mycust.referralProgram.campaign && mycust.referralProgram.campaign.showModal;
                },
                show: false
            },
            {
                name: "subscription",
                frequency: "every_14_days",
                requireAuth: true,
                enabled: function (datacontext) {
                    return datacontext.subscription.defaultSubscriptionOfferId != 0
                        && datacontext.subscription.hasActiveSubscription == 0;
                },
                show: false
            },
            {
                name: "df", // dutch farms
                frequency: "every_7_days",
                requireAuth: false,
                enabled: function () {
                    return true;
                },
                show: false
            }
        ]

        function openNextAvailableModal() {
            var displayedMarketingCookieName = "dm";
            if ($scope.getCookie(displayedMarketingCookieName))
                return;
            
            for (var i = 0; i < vm.modals.length; i++) {
                var modal = vm.modals[i];
                var cookieName = "displayed_" + modal.name
                if (navigator.cookieEnabled && !$scope.getCookie(cookieName) &&
                    ((modal.requireAuth && authService.authentication.isAuth) || !modal.requireAuth) &&
                    modal.enabled(datacontext)
                ) {

                    modal.show = true;

                    var expiration = new Date(now.getDate() + 1);
                    if (modal.frequency === "first_day_month") {
                        expiration = new Date(now.getFullYear(), now.getMonth() + 1, 1);
                    }
                    if (modal.frequency === "every_14_days") {
                        expiration = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 14);
                    }
                    if (modal.frequency === "every_7_days") {
                        expiration = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 7);
                    }

                    $scope.setCookie(cookieName, true, expiration);
                    $scope.setCookie(displayedMarketingCookieName, true, new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1))

                    break;
                }
            }
        }

        // Activate
        (function () {
            common.activateController([
                datacontext.primeCustomer(),
                datacontext.subscription.getDefaultSubscriptionOfferId(),
                datacontext.subscription.getHasActiveSubscription()
            ], controllerId)
                .then(function () {
                    openNextAvailableModal();
                });
        })();

        vm.closeModal = function (modal) {
            modal.show = false;
        }

        vm.overlayImageFileName = now.getFullYear().toString() + (("0" + (now.getMonth() + 1)).slice(-2)) + ".jpg";
        
        vm.getReferralCampaignImage = function () {
            if (datacontext && 
                datacontext.cust &&
                datacontext.cust.mycust &&
                datacontext.cust.mycust.referralProgram &&
                datacontext.cust.mycust.referralProgram.campaign) {
                return datacontext.cust.mycust.referralProgram.campaign.sendModalFileName;
            }
        }
        
        $("#lookbook-mobile").one("error",
            function () {
                $(this).attr("src", $scope.CDNImageBaseURL + "/assets/images/lookbook/mobile/fallback.jpg");
            });

        $("#lookbook-desktop").one("error",
            function () {
                $(this).attr("src", $scope.CDNImageBaseURL+ "/assets/images/lookbook/desktop/fallback.jpg");
            });
    }
})();
;
(function () {
    const controllerId = 'newStartClaimGiftCardController';

    angular.module('app-hd').controller(controllerId, ['$scope', '$http', 'datacontext', 'common', 'eGiftCardService', newStartClaimGiftCardController]);

    function newStartClaimGiftCardController($scope, $http, datacontext, common, eGiftCardService) {
        const vm = this;
        vm.show = false;
        vm.giftCards = [];
        
        vm.claimCodeState = {
            error: null,
            loading: false
        };

        (function activate(){
            refreshSignUpGiftCards();
        })();
        
        function refreshSignUpGiftCards() {
            eGiftCardService.getSignUpGiftCards(datacontext.cust.getCustId())
                .then(function (response) {
                    vm.giftCards = response.data;
                });
        }

        vm.claimCode = "";
        vm.applyToAccount = function(claimCode) {
            vm.claimCodeState.loading = true;
            eGiftCardService
                .applyEgiftCardToAccount(claimCode, true, datacontext.cust.getCustId())
                .then(function() {
                    vm.claimCodeState.error = null;
                    vm.claimCode = "";
                    refreshSignUpGiftCards();
                })
                .catch(function(error) {
                    vm.claimCodeState.error = error;
                })
                .finally(function () {
                    vm.claimCodeState.loading = false;
                })
        }
    }
})()

;
(function () {
    "use strict";
    var controllerId = "paymentController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$q", "$http", "$state", "$sce", "$window", "config", "common", "datacontext", "giftCardService", paymentController]);

    function paymentController($scope, $q, $http, $state, $sce, $window, config, common, datacontext, giftCardService) {
        var vm = this;
        vm.baseUrl = config.baseUrl;
        vm.title = "Payments Controller";
        $scope.isEditMode = false;
        $scope.delay = 0;
        $scope.minDuration = 0;
        $scope.message = 'Verifying Account Information...';
        $scope.backdrop = true;
        $scope.promise = null;
        $scope.oneTimePaymentSubmitted = false;
        $scope.showOneTimePaymentComplete = false;
        vm.showOrderWontBeDeliveredMessage = false;
        var beforeEditPaymentInfo = {};
        var blankpaymentData = {
            billCode: "",
            customerNumber: null,
            paymentMethod: null,
            creditCard: "",
            expireMonth: "",
            expireYear: "",
            routingNumber: "",
            accountNumber: "",
            ZipCode: "",
        };

        vm.customerDC = datacontext.cust;
        $scope.customerDC = datacontext.cust;
        $scope.showOneTimePayment = false;
        $scope.hasPaymentMethod = false;
        vm.expireYearOptions = [];
        $scope.pageReady = false;

        vm.otp_success = false;
        vm.otp_message = "";
        vm.creditUpdate_success = false;
        vm.creditUpdate_message = '';

        vm.customerDetails_message = "";
        vm.customerDetails_success = false;

        vm.baseUrl = config.baseUrl;

        vm.OneTimePayment = {
            billCode: 0,
            id: 0,
            customerNumber: 0,
            paymentMethod: null,
            isChecking: false,
            isWeeklyBilling: false,
            creditCard: null,
            expireMonth: null,
            expireYear: null,
            routingNumber: null,
            accountNumber: null,
            zipCode: null,
            payer_Id: null,
            date_Created: null,
            date_Deleted: null,
            bankName: null,
            amountToPay: null,
            amountToCharge: null
        };

        vm.calculatedPaymentdetails = {
            lastPaymentDate: null,
            previousBalance: 0.00,
            RecentPayments: 0.00,
            currentCharges: 0.00,
            currentAdjustments: 0.00,
            currentBalance: 0.00,
        };

        $scope.enroll_Message = "";
        $scope.enroll_success = true;
        vm.errrorsReset = function () {
            $scope.enroll_Message = "";
            $scope.enroll_success = true;
        };
        var originalRouting = "";
        vm.paymentMethod = {
            paymentMethod: ''
        };

        vm.lookupBankName = _lookupBankName;

        vm.updatePaymentInfo = function () {
            vm.customerDetails_success = false;
            vm.customerDetails_message = "";
            $scope.isEditMode = true;
            angular.copy(vm.paymentMethod, beforeEditPaymentInfo);
            vm.paymentMethod.creditCard = "";

            if (!vm.paymentMethod.isChecking) {
                vm.editCreditCard();
            }
        }

        vm.showIframe = false;

        vm.loadCreditCardForm = function () {

            vm.otp_message = "";

            if (common.validateForm('#oneTimePayment')) {
                vm.showIframe = true;

                var returnUrl = '/home-delivery/shopping/account/payments';

                datacontext.cust.getTransactionUrl(vm.OneTimePayment.AmountToPay, returnUrl).then(function (result) {
                    vm.paymentIframeUrl = $sce.trustAsResourceUrl(result.iFrameUrl);
                    common.includePaymentScripts();
                }, function () {
                    vm.otp_message = config.paymentServiceErrorMessage;
                    vm.otp_success = false;
                });
            }
        }

        vm.editCreditCard = function () {
            var returnUrl = '/home-delivery/shopping/account/paymentMethod';

            datacontext.cust.getAuthenticationUrl(returnUrl).then(function (result) {
                vm.paymentIframeUrl = $sce.trustAsResourceUrl(result.iFrameUrl);
                common.includePaymentScripts();
            }, function () {
                vm.customerDetails_message = config.paymentServiceErrorMessage
                vm.customerDetails_success = false;
            });
        }

        /* Disable the save checking account save button if any of the following conditions are true */
        vm.disableSaveButton = function () {
            if (vm.paymentMethod.isChecking) {
                if (vm.paymentMethod.bankName == null || vm.paymentMethod.bankName == '') {
                    return true;
                }
                if (vm.paymentMethod.routingNumber == null || vm.paymentMethod.routingNumber == '' || vm.paymentMethod.routingNumber.length < 9) {
                    return true;
                }
                if (vm.paymentMethod.accountNumber == null || vm.paymentMethod.accountNumber == '' || vm.paymentMethod.accountNumber.length < 7) {
                    return true;
                }
            }
            return false;
        }

        vm.canSwitchPayMethod = function () {
            if (vm.paymentMethod && vm.paymentHistory && (vm.paymentMethod.isChecking || vm.paymentHistory.length > 4))
                return true;
            else
                return false;
        }

        vm.switchPaymentInfo = function () {
            angular.copy(vm.paymentMethod, beforeEditPaymentInfo);

            vm.paymentMethod.isChecking = !vm.paymentMethod.isChecking;
            $scope.isEditMode = true;

            vm.paymentMethod.creditCard = "";
            vm.paymentMethod.accountNumber = "";
            vm.paymentMethod.routingNumber = "";
            vm.paymentMethod.expireMonth = null
            vm.paymentMethod.expireYear = null;
            vm.paymentMethod.ZipCode = null;

            if (!vm.paymentMethod.isChecking) {
                vm.editCreditCard();
            }
        } //vm.isWeeklyBilling = function () { return (vm.paymentMethod.billCode == '10' || vm.paymentMethod.billCode == '11'); }

        vm.getSwitchText = function () { return vm.paymentMethod.isChecking ? 'Credit Card' : 'Checking Account'; };

        vm.enrollChecking = function () {
            setupEnrollPaymentType(true);
        }

        vm.enrollCreditCard = function () {
            setupEnrollPaymentType(false);
        }

        function setupEnrollPaymentType(isChecking) {
            $scope.isEditMode = true;
            angular.copy(blankpaymentData, vm.paymentMethod);
            vm.paymentMethod.isChecking = isChecking;
            vm.paymentMethod.billCode = isChecking ? "11" : "10";
            if (!isChecking) {
                vm.editCreditCard();
            }
            $scope.enrolling = true;
        }

        vm.changedCardType = function () {
            vm.OneTimePayment.CreditCard = null;
            vm.OneTimePayment.ExpireMonth = null;
            vm.OneTimePayment.ExpireYear = null;
            vm.OneTimePayment.zipCode = null;
        }

        function _lookupBankName() {
            if (('' + vm.paymentMethod.routingNumber).length >= 8) {
                return $http.get("api/customers/getBankName?rounteNum=" + vm.paymentMethod.routingNumber)
                    .success(querySucceeded);
            }

            function querySucceeded(data) {
                vm.resetErrorMessage();
                vm.paymentMethod.bankName = data;
            }
        }

        vm.validateChecking = function () {
            if (vm.paymentMethod.isChecking) {
                if (!vm.paymentMethod.bankName) {
                    vm.customerDetails_success = false;
                    vm.customerDetails_message = "Invalid Routing Number.";
                    return false;
                }
            }
            return true;
        }

        vm.resetErrorMessage = function () {
            vm.customerDetails_message = "";
        }
        
        function postCreditCardUpdate(chaseUID) {
            $scope.isEditMode = false;
            $scope.message = "Setting your payment information...";
            common.$broadcast(config.events.spinnerToggle, { show: true });
            return $scope.promise = $http.post("api/payments/PostCreditCardUpdate/" + chaseUID)
                .success(function (response) {
                    vm.paymentMethod.isChecking = false;
                    vm.customerDetails_success = true;
                    vm.customerDetails_message = response;
                    $scope.hasPaymentMethod = true;
                    $scope.enrolling = false;
                    getpaymentMethod();
                })
                .error(function (data, status, headers, config) {
                    $scope.isEditMode = true;
                    $scope.hasPaymentMethod = false;
                    vm.customerDetails_success = false;
                    vm.customerDetails_message = vm.handleError(data);
                    vm.OneTimePayment.paymentMethod = "otherCard";
                })
                .finally(function () {
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });
            
        }

        function postOtherCardOneTimePayment(chaseUID) {
            if (common.validateForm('#oneTimePayment')) {
                $scope.message = "Processing your payment ...";
                vm.otp_message = "";
                vm.otp_success = true;
                $scope.oneTimePaymentSubmitted = true;
                $scope.showOneTimePaymentComplete = false;
                common.$broadcast(config.events.spinnerToggle, { show: true });
                return $scope.promise = $http.post("api/payments/PostOtherCardOneTimePayment/" + chaseUID)
                    .success(function (response) {
                        var prts = response.split('~');
                        if (prts.length > 1) {
                            if (prts[1] == 'removeAdminLock') {
                                datacontext.order.removeSuspension();
                                datacontext.order.reloadOrder();
                                datacontext.cust.mycust.adminLockout = false;
                                vm.nextDeliveryDay = moment(datacontext.cust.mycust.nextDeliveryDate).format("L");
                                var today = moment().format("L");
                                if (vm.nextDeliveryDay === today) {
                                    vm.showOrderWontBeDeliveredMessage = true;
                                }
                            }
                        }
                        vm.otp_message = prts[0];


                        $q.all([
                            vm.customerDC.getAccountBalanceSummary(true),
                            datacontext.cust.getPaymentSummary(true).then(function () {
                                $scope.getPaymentHistory();
                            })
                        ])
                        $scope.showOneTimePaymentComplete = true;
                        //vm.showOneTimePayment = false;
                    })
                    .error(function (data, status, headers, config) {
                        vm.otp_success = false;
                        vm.otp_message = vm.handleError(data);
                        vm.OneTimePayment = {};

                    }).finally(function () {
                        $scope.oneTimePaymentSubmitted = false;

                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    });
            }
        }

        function postPaymentUpdate() {
            $scope.isEditMode = false;
            $scope.message = "Setting your payment information...";
            common.$broadcast(config.events.spinnerToggle, { show: true });
            return $scope.promise = $http.post("api/payments/PostPaymentUpdate", vm.paymentMethod)
                .success(function (response) {
                    var acctlen = ('' + vm.paymentMethod.creditCard).length;
                    var last4 = vm.paymentMethod.creditCard.substr(acctlen - 4, 4);
                    var starword = "";
                    for (var inx = 0; inx < acctlen - 4; inx++) starword += "*";
                    if (acctlen == 0) {
                        vm.paymentMethod.isChecking = true;
                    }
                    else {
                        vm.paymentMethod.isChecking = false;
                    }


                    starword += last4;
                    vm.paymentMethod.creditCard = starword;
                    vm.customerDetails_success = true;
                    vm.customerDetails_message = response;
                    $scope.hasPaymentMethod = true;
                    $scope.enrolling = false;
                    getpaymentMethod();
                })
                .error(function (data, status, headers, config) {
                    $scope.isEditMode = true;
                    $scope.hasPaymentMethod = false;
                    vm.customerDetails_success = false;
                    vm.customerDetails_message = vm.handleError(data);
                    vm.OneTimePayment.paymentMethod = "otherCard";
                })
                .finally(function () {
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });
        }

        vm.submitUpdate = function () {
            if (common.validateForm("#paymentMethodForm") && vm.validateChecking()) {
                postPaymentUpdate()
            }
        }

        vm.handleError = function (error) {
            var msg = '';

            if (error.length > 0) {
                angular.forEach(error, function (value, key) {
                    msg += value + " ";
                });
            } else {
                msg = error;
            }

            return msg;
        }

        vm.cancelEdits = function () {
            $scope.isEditMode = false;
            $scope.enrolling = false;
            angular.copy(beforeEditPaymentInfo, vm.paymentMethod);
        }

        function getpaymentMethod() {
            return $http.get("api/payments/getPaymentMethod")
                .success(function (response) {
                    if (response == null) {
                        $scope.hasPaymentMethod = false;
                        vm.OneTimePayment.paymentMethod = "otherCard";
                    } else {
                        $scope.hasPaymentMethod = true;
                        vm.paymentMethod = response;

                        vm.paymentMethod.creditCard = vm.paymentMethod.accountNumber;
                        vm.originalRouting = vm.paymentMethod.routingNumber;
                        vm.OneTimePayment.paymentMethod = (vm.paymentMethod.isChecking) ? "otherCard" : "cardonfile";
                    }
                })
                .error(function (data, status, headers, config) {
                    $scope.hasPaymentMethod = false;
                    vm.OneTimePayment.paymentMethod = "otherCard";
                });
        }

        vm.paymentHistory = {};

        function getPaymentHistory() {
            //
            //	this will probably be moved into the customer object
            //	so that it stays around after it is initially obtained.
            //	this fills out the list on the bottom of the payment screen
            //

            return $http.get("api/payments/getPaymentsHistory")
                .success(function (response) {
                    vm.paymentHistory = response;
                })
                .error(function (data, status, headers, config) {

                });
        }

        vm.paymentsummary = {};
        vm.makeOneTimePayment = makeOneTimePayment;

        function makeOneTimePayment(withRefresh) {
            if (common.validateForm('#oneTimePayment')) {
                $scope.message = "Processing your payment ...";
                vm.otp_message = "";
                vm.otp_success = true;
                $scope.oneTimePaymentSubmitted = true;
                $scope.showOneTimePaymentComplete = false;
                common.$broadcast(config.events.spinnerToggle, { show: true });
                console.log(vm.OneTimePayment);
                return $scope.promise = $http.post("api/payments/PostOneTimePayment", vm.OneTimePayment)
                    .success(function (response) {
                        var prts = response.split('~');
                        if (prts.length > 1) {
                            if (prts[1] == 'removeAdminLock') {
                                datacontext.order.removeSuspension();
                                datacontext.order.reloadOrder();
                                datacontext.cust.mycust.adminLockout = false;
                                vm.nextDeliveryDay = moment(datacontext.cust.mycust.nextDeliveryDate).format("L");
                                var today = moment().format("L");
                                if (vm.nextDeliveryDay === today) {
                                    vm.showOrderWontBeDeliveredMessage = true;
                                }
                            }
                        }
                        vm.otp_message = prts[0];


                        $q.all([
                            vm.customerDC.getAccountBalanceSummary(true),
                            datacontext.cust.getPaymentSummary(true).then(function () {
                                $scope.getPaymentHistory();
                            })
                        ])
                        $scope.showOneTimePaymentComplete = true;
                        //vm.showOneTimePayment = false;
                    })
                    .error(function (data, status, headers, config) {
                        vm.otp_success = false;
                        vm.otp_message = vm.handleError(data);
                        vm.OneTimePayment = {};

                    }).finally(function () {
                        $scope.oneTimePaymentSubmitted = false;

                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    });
            }
        }

        vm.oneTimePaymentCloseDialog = oneTimePaymentCloseDialog;

        function oneTimePaymentCloseDialog() {
            $scope.oneTimePaymentSubmitted = false;
            $scope.showOneTimePaymentComplete = false;
            vm.showOneTimePayment = false;
            vm.otp_message = '';
        }

        $window.submitPaymentSuccess = function (data) {
            vm.paymentIframeUrl = "";
            vm.otp_success = true;
            vm.showIframe = false;

            if (data.code !== "000" && data.message.toLower !== "success") {
                vm.customerDetails_message = data.message;
                vm.customerDetails_success = false;
                vm.clearQueryStringParameters();
                vm.editCreditCard();
                return;
            }

            if (vm.activeTab === 'paymentMethod') {
                postCreditCardUpdate(data.uID);
            } else if (vm.activeTab === 'payments') {
                postOtherCardOneTimePayment(data.uID)
            }
        }

        vm.completePayment = function (orderId, responseCode, responseCodeText) {
            datacontext.cust.getPaymentData(orderId).then(function (result) {
                var starword = '************' + result.span;

                if (vm.activeTab === 'paymentMethod') {
                    if ((responseCode == 1) && responseCode && responseCodeText.toLowerCase() == "success") {
                        vm.paymentMethod.paymentMethod = 'Credit Card';
                        vm.paymentMethod.maskedCreditCard = starword;
                        vm.paymentMethod.creditCard = starword;
                        vm.paymentMethod.last4CreditCard = result.span;
                        vm.paymentMethod.payerId = result.payer_identifier;
                        vm.paymentMethod.payer_Id = result.payer_identifier;
                        vm.paymentMethod.paymentOrderIdString = result.order_id;
                        vm.paymentMethod.expireMonth = result.expire_month;
                        vm.paymentMethod.expireYear = result.expire_year;
                        vm.paymentMethod.creditCard = starword;
                        vm.paymentMethod.accountNumber = '';
                        vm.paymentMethod.routingNumber = '';
                        vm.paymentMethod.zipCode = result.billing_zip_code;
                        vm.paymentMethod.isChecking = false;

                        vm.clearQueryStringParameters();
                        postPaymentUpdate();
                    }
                    else {
                        vm.customerDetails_message = responseCodeText;
                        vm.customerDetails_success = false;
                        //$location.url($location.path());
                        //$location.search('');
                        vm.clearQueryStringParameters();
                        vm.editCreditCard();
                    }
                }
                else if (vm.activeTab === 'payments') {
                    vm.OneTimePayment.paymentMethod = "otherCard";
                    vm.OneTimePayment.CreditCard = starword;
                    vm.OneTimePayment.ExpireMonth = result.expire_month;
                    vm.OneTimePayment.ExpireYear = result.expire_year;
                    vm.OneTimePayment.zipCode = result.billing_zip_code;
                    vm.OneTimePayment.AmountToPay = result.authorized_amount;
                    vm.OneTimePayment.ApprovalCode = result.bank_approval_code;
                    vm.OneTimePayment.RefrenceNumber = result.order_id;
                    vm.OneTimePayment.ResponseCode = result.original_response_code;
                    vm.OneTimePayment.ResponseCodeText = result.original_response_code_text;
                    vm.OneTimePayment.Payer_Id = result.payer_Id;
                    vm.OneTimePayment.Id = result.id;

                    vm.clearQueryStringParameters();
                    makeOneTimePayment().then(function () {
                        //vm.showOneTimePayment = true;
                    });

                    if (responseCode != 1) {
                        vm.otp_success = false;
                        vm.otp_message = responseCodeText;
                        vm.OneTimePayment = {};
                    }
                    vm.showOneTimePayment = true;
                }
            }, function () {
                vm.clearQueryStringParameters();
                vm.customerDetails_message = config.paymentServiceErrorMessage;
                vm.customerDetails_success = false;
            })
        }
        
        function validateCreditCard() {
            if (($state.params.response_code) && ($state.params.response_code.length > 0)) {

                $scope.isEditMode = true;

                if (($state.params.response_code)) {
                    //console.log($state.params.order_id)
                    vm.completePayment($state.params.order_id, $state.params.response_code, $state.params.response_code_text);
                }
            }
        }

        vm.showPaymentModal = function () {
             $scope.oneTimePaymentSubmitted = false;
            $scope.showOneTimePaymentComplete = false;
            vm.showOneTimePayment = false;
            vm.otp_message = '';

            vm.showOneTimePayment = true;
            vm.showIframe = false;
        }
        vm.closeOrderWontBeDeliveredMessage = function () {
            vm.showOrderWontBeDeliveredMessage = false;
        }
        vm.clearQueryStringParameters = function () {
            $state.go('shopping.account', {
                tab: $state.params.tab,
                order_id: null,
                response_code: null,
                secondary_response_code: null,
                response_code_text: null
            }, {
                notify: false,
                location: 'replace'
            });
        }

        vm.makeGiftCardPayment = async function() {
            vm.giftCardPaymentData = null;
            $scope.oneTimePaymentSubmitted = true;
            common.$broadcast(config.events.spinnerToggle, { show: true });
            const result = await giftCardService.postOneTimePayment(vm.OneTimePayment.AmountToPay);
            if (result.success) {
                vm.otp_message = `Your gift card payment of ${result.data.totalRedeemed} has been processed.`
                vm.otp_success = true;
                $scope.showOneTimePaymentComplete = true;
                vm.giftCardPaymentData = result.data;
            } else {
                vm.otp_message = result.message;
                vm.otp_success = false;
            }

            common.$broadcast(config.events.spinnerToggle, { show: false });
            $scope.oneTimePaymentSubmitted = false;
            $scope.$apply();
        };

        activate();


        function activate() {

            common.activateController([
                getPaymentHistory(),
                getpaymentMethod()
            ], controllerId)
                .then(function (data) {

                    vm.activeTab = $state.params.tab;

                    datacontext.primeCustomer().then(function () {
                        validateCreditCard();
                    });

                    var dt = new Date();
                    for (var i = 0; i < 12; i++) {
                        vm.expireYearOptions.push(i + dt.getFullYear());
                    }
                    $scope.pageReady = true;
                    vm.paymentsummary = datacontext.cust.paymentsummary;
                });
        }

        //vm.LookupBankName = function () {
        //    if (vm.paymentMethod.routingNumber.length >= 9) {
        //        return $http.get("api/customers/getBankName?rounteNum=" + vm.paymentMethod.routingNumber)
        //            .success(querySucceeded);
        //    }

        //    function querySucceeded(data) {
        //        vm.paymentMethod.bankName = data;
        //    }
        //};
    }
})();;
(function () {
    var controllerId = 'popupMessageController';
    angular.module("app-hd").controller(controllerId,
        [ "$scope" , "common", popupMessage]);

    function popupMessage($scope, common) {

        var vm = this;

        vm.title = "Oberweis Dairy";
        vm.message = "Invalid request.";
        vm.showPopup = true;
        vm.closePopup = _closePopup;
        vm.setMessageAndShowPopup = _setMessageAndShowPopup;

        function _closePopup() {
            vm.showPopup = false;
        }

        function _setMessageAndShowPopup(message, hideFooter, title) {

            vm.message = message;
            vm.hideFooter = hideFooter;    
            if (title && title != 'undefined') {
                vm.title = title;
            }
            if (message && message != 'undefined') {
                vm.showPopup = true;
            }
        }

        activate();

        function activate() {
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "preOrderController";

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$rootScope"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "$filter"
            , "$http"
            , "config"
            , "common"
            , "datacontext"
            , "authService"
            , "$q"
            , "unauthenticatedBranch"
            , preOrderController]);

    function preOrderController(
        $stateParams
        , $rootScope
        , $scope
        , $state
        , $timeout
        , $window
        , $filter
        , $http
        , config
        , common
        , datacontext
        , authService
        , $q
        , unauthenticatedBranch) {

        var vm = this;

        vm.preOrderProducts = [];
        vm.customerPreOrderProducts = [];
        vm.showOrderEdits = true;
        vm.currentBranch = 1;

        vm.showSave = function (prod, type) {
            var id = prod.id;
            if (prod.deliveryDate !== null && ((type === 'create' && prod.nextQuantity > 0) || type !== 'create')) {
                document.getElementById('submit_preOrder_' + type + id).removeAttribute("disabled");
            }
            else if (prod.deliveryDate !== null && (type === 'create' && prod.nextQuantity === 0)) {
                document.getElementById('submit_preOrder_' + type + id).setAttribute("disabled", "");

            }
        };

        vm.allowOrderEdits = _allowOrderEdits;

        function _allowOrderEdits(prod, type) {
            if (type === 'create') {
                return (prod.availableQuantity > 0 && vm.isAuth && prod.availableForPreOrder);
            }
            else {
                return (vm.isAuth && prod.availableForPreOrder);

            }
        };
        function getPreOrderProducts() {
            var deferred = $q.defer();
            var onlyActive = true;

            $http.get('/api/ProductPreOrder/GetPreOrderProduct/' + onlyActive).then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        };

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (oldVal, newVal) {
            if (oldVal && oldVal.branchNumber !== newVal.branchNumber) {
                setActiveProds();
            }
        });

        function setActiveProds() {

            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            vm.currentBranch = curBranch;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
                vm.currentBranch = curBranch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
                vm.currentBranch = curBranch;
            }
            var prodList = vm.preOrderProducts;
            //sets all info for adding new preorder items 
            for (var i = 0; i < prodList.length; i++) {
                for (var j = 0; j < prodList[i].preOrderProductBranch.length; j++) {
                    var preOrderBranch = prodList[i].preOrderProductBranch[j];
                    if (curBranch === preOrderBranch.branchNumber) {
                        var currentItem = prodList[i];
                        if (currentItem) {
                            currentItem.branchPreOrderStartDate = new Date(preOrderBranch.preOrderStartDate).toLocaleDateString();
                            currentItem.branchPreOrderEndDate = new Date(preOrderBranch.preOrderEndDate).toLocaleDateString();
                            currentItem.branchDeliveryWindowStartDate = new Date(preOrderBranch.deliveryWindowStartDate).toLocaleDateString();
                            currentItem.branchDeliveryWindowEndDate = new Date(preOrderBranch.deliveryWindowEndDate).toLocaleDateString();
                            currentItem.possibleDates = getDatesAvailableForPreOrder(new Date(preOrderBranch.deliveryWindowStartDate), new Date(preOrderBranch.deliveryWindowEndDate));
                            currentItem.deliveryDate = null;
                            currentItem.onOrder = false;
                            currentItem.availableForPreOrder = isAvailableForOrder(preOrderBranch);
                            currentItem.availableQuantity = getTotalQuantityAvailable(currentItem.maxQuantityPerOrder, currentItem.availableQuantity);
                            currentItem.message = generateMessage(currentItem);
                        }
                    }
                }
            }
        };

        function generateMessage(item) {
            if (item.availableQuantity <= 0) {
                return "Out of Stock";
            }
            if (!item.availableForPreOrder) {
                return "No longer editable in your area";
            }
            else {
                return "";
            }
        };

        function isAvailableForOrder(curBranchDetail) {
            var timeElapsed = Date.now();
            var today = new Date(timeElapsed);
            today.setHours(0, 0, 0, 0);
            var startDate = new Date(curBranchDetail.preOrderStartDate);
            var endDate = new Date(curBranchDetail.preOrderEndDate);
            //if it is not available for pre order, return false immediately
            if (curBranchDetail.allowPreOrder) {
                //it is not within the branch deliver window
                if (startDate <= today && endDate >= today) {
                    return true;
                }
                else {
                    return false;
                }
            }
            else {
                return false;
            }
        };

        function adjustCustomerProducts() {
            for (var i = 0; i < vm.customerPreOrderProducts.length; i++) {

                var currentItem = vm.customerPreOrderProducts[i];
                var branchProduct = vm.customerPreOrderProducts[i].preOrderProduct.preOrderProductBranch.find(item => item.branchNumber === vm.currentBranch);
                currentItem.branchPreOrderStartDate = new Date(branchProduct.preOrderStartDate).toLocaleDateString();
                currentItem.branchPreOrderEndDate = new Date(branchProduct.preOrderEndDate).toLocaleDateString();
                currentItem.branchDeliveryWindowStartDate = new Date(branchProduct.deliveryWindowStartDate).toLocaleDateString();
                currentItem.branchDeliveryWindowEndDate = new Date(branchProduct.deliveryWindowEndDate).toLocaleDateString();
                currentItem.possibleDates = getDatesAvailableForPreOrder(new Date(branchProduct.deliveryWindowStartDate), new Date(branchProduct.deliveryWindowEndDate), currentItem.deliveryDate);
                currentItem.deliveryDate = new Date(currentItem.deliveryDate).toDateString();
                currentItem.availableQuantity = getTotalQuantityAvailable(currentItem.preOrderProduct.maxQuantityPerOrder, currentItem.preOrderProduct.availableQuantity + currentItem.nextQuantity);
                currentItem.onOrder = true;
                currentItem.availableForPreOrder = isAvailableForOrder(branchProduct);
                currentItem.message = generateMessage(currentItem);

            }

        };
        function getTotalQuantityAvailable(prodMax, availableQuant) {
            if (availableQuant > prodMax) {
                return prodMax;
            }
            else {
                return availableQuant;
            }
        };
        function getCustomerPreOrderedProds() {
            var deferred = $q.defer();

            $http.get('/api/ProductPreOrder/GetCustomerPreOrderProduct/').then(
                function (response) {
                    deferred.resolve(response);
                }, function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        };

        function getPreOrderFirstDateAllowed(startDate) {
            var preOrderFirstDateAllowed;
            var dayOfWeek;
            if (datacontext.cust && datacontext.cust.mycust) {
                dayOfWeek = datacontext.cust.mycust.deliveryDay;
            }

            switch (dayOfWeek) {
                case 'SUN':
                    dayOfWeek = 0; break;
                case 'MON':
                    dayOfWeek = 1; break;
                case 'TUE':
                    dayOfWeek = 2; break;
                case 'WED':
                    dayOfWeek = 3; break;
                case 'THU':
                    dayOfWeek = 4; break;
                case 'FRI':
                    dayOfWeek = 5; break;
                case 'SAT':
                    dayOfWeek = 6; break;
                default:
                    dayOfWeek = 0;
            }
            while (startDate.getDay() !== dayOfWeek) {
                startDate.setDate(startDate.getDate() + 1);
            }

            preOrderFirstDateAllowed = startDate;


            return preOrderFirstDateAllowed;

        };

        function getPreOrderLastDateAllowed(endDate) {
            var preOrderLastDateAllowed;

            var dayOfWeek;
            if (datacontext.cust && datacontext.cust.mycust) {
                dayOfWeek = datacontext.cust.mycust.deliveryDay;
            }

            switch (dayOfWeek) {
                case 'SUN':
                    dayOfWeek = 0; break;
                case 'MON':
                    dayOfWeek = 1; break;
                case 'TUE':
                    dayOfWeek = 2; break;
                case 'WED':
                    dayOfWeek = 3; break;
                case 'THU':
                    dayOfWeek = 4; break;
                case 'FRI':
                    dayOfWeek = 5; break;
                case 'SAT':
                    dayOfWeek = 6; break;
                default:
                    dayOfWeek = 0;
            }
            while (endDate.getDay() !== dayOfWeek) {
                endDate.setDate(endDate.getDate() - 1);
            }

            preOrderLastDateAllowed = endDate;
            return preOrderLastDateAllowed;

        };

        function getDatesAvailableForPreOrder(startDate, endDate, deliveryDate) {
            var eow;
            if (datacontext.cust && datacontext.cust.mycust) {
                eow = datacontext.cust.mycust.EOW;
            }
            eow = eow ? eow : 0;

            var datesAvailable = [];
            var start = getPreOrderFirstDateAllowed(startDate);
            var end = getPreOrderLastDateAllowed(endDate);
            while (start <= end) {
                var s = moment(start);
                if (availableDay(s, eow)) {
                    s = moment(s).toDate();
                    if (moment(s).diff(moment(deliveryDate)) === 0) {
                        deliveryDate = new Date(deliveryDate).toDateString();
                        datesAvailable.push(deliveryDate);
                    }
                    else {
                        datesAvailable.push(start.toDateString());
                    }
                }
                start.setDate(start.getDate() + 7);
            }

            return datesAvailable;
        };

        function availableDay(dt, eow) {
            return common.availableDay(dt, eow);

        };

        vm.isAuth = authService.authentication.isAuth;

        vm.submitPreOrder = function (type, preOrder) {

            var preOrderObj = {
                nextQuantity: preOrder.nextQuantity,
                customerId: datacontext.cust.mycust.id,
                createdBy: datacontext.cust.mycust.userName,
                productNumber: preOrder.productNumber,
                deliveryDate: preOrder.deliveryDate
            };

            switch (type) {
                case "update":
                    preOrderObj.id = preOrder.id;
                    preOrderObj.preOrderProductId = preOrder.preOrderProductId;
                    if (preOrderObj.nextQuantity <= 0) {
                        confirmRemoval(preOrderObj);
                    }
                    else {
                        updateCustomerPreOrder(preOrderObj);
                    }
                    break;
                case "create":
                    preOrderObj.preOrderProductId = preOrder.id;
                    createCustomerPreOrder(preOrderObj);
                    break;
                default:
                    console.log("bad", preOrderObj);

            }
        };
        vm.showConfirmRemoval = false;
        function confirmRemoval(preOrder) {
            vm.pendingPreOrderRemoval = preOrder;
            vm.showConfirmRemoval = true;
        };
        vm.continueSubmit = function () {
            vm.showConfirmRemoval = false;
            updateCustomerPreOrder(vm.pendingPreOrderRemoval);
        };

        vm.cancelSubmit = function () {
            vm.pendingPreOrderRemoval = null;
            vm.showConfirmRemoval = false;
        };
        function updateCustomerPreOrder(preOrder) {
            var url = "api/ProductPreOrder/UpdateCustomerPreOrder";
            $http.post(url, preOrder).then(
                function (response) {
                    activate();
                }, function (err, status) {
                });
        };


        function createCustomerPreOrder(preOrder) {
            var url = "api/ProductPreOrder/CreateCustomerPreOrder";
            $http.post(url, preOrder).success(
                function (response) {
                    activate();
                }, function (err, status) {
                });

        };

        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal && oldVal !== newVal) {
                activate();
            }
        });
        function activate() {
            vm.preOrderProducts = [];
            vm.customerPreOrderProducts = [];

            getPreOrderProducts().then(function (response) {
                vm.preOrderProducts = response.data;
                setActiveProds();
            });
            getCustomerPreOrderedProds().then(function (response) {
                vm.customerPreOrderProducts = response.data;
                adjustCustomerProducts();
            });
        };

        activate();
    }
})();
;
(function () {
    "use strict";
    var controllerId = "productCatalogController";

    // Shared across all controller instances.
    var originalOnDemandCustomer;

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$rootScope"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "$filter"
            , "$http"
            , "config"
            , "common"
            , "datacontext"
            , "authService"
            , "unauthenticatedBranch"
            , productsCatalog]);

    function productsCatalog(
        $stateParams
        , $rootScope
        , $scope
        , $state
        , $timeout
        , $window
        , $filter
        , $http
        , config
        , common
        , datacontext
        , authService
        , unauthenticatedBranch) {

        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        var keyCodes = config.keyCodes;
        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;
        vm.localCutoff = "";
        vm.datacontext = datacontext;
        vm.activeCats = [];
        vm.subModalVisible = false;
        vm.subNotificationModalVisible = false;
        vm.subProduct;
        vm.customerSubstitutionPreferences = {};
        vm.customerProductPreference = {};
        vm.showMergedCartOrder = false;
        vm.showProductMergeMessage = false;
        vm.checkoutWarning = false;
        vm.showScheduledDeliveryOffer = false;
        vm.GetProductOnlyTotals = _getProductOnlyDeliveryTotals;
        vm.newCustMaxSpendThreshold = 0;
        vm.showFirstOrderOverThresholdModal = false;
        vm.showPaymentIsRequiredModal = false;
        //remove 8 from here after testing, add 1 to view
        vm.produceBranchAvailable = [];

        vm.customerProduceContainer = {
            produceProducts: null,
            totalCost: 0
        };


        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (newVal, oldVal) {
            if (oldVal && newVal && oldVal.branchNumber !== newVal.branchNumber) {
                var c = $("#shopping-carousel");
                if (c) {
                    c.carousel(0);
                }
                setActiveCats();
                getPreOrderProds();
            }
            if (newVal && (vm.produceBranchAvailable.indexOf(newVal.branchNumber) !== -1)) {
                vm.produceViewAvailable = true;

            }
            else {
                vm.produceViewAvailable = false;

            }
        });

        //TODO - Replace this ability to refresh from another controller with something more elegant and robust
        //This allows another controller in a sub-page to force the local arrays refresh when adding items to cart from other controllers
        datacontext.forceCartRefresh = function () {
            //none of this seems to make any difference, leaving it in for now but it's likely a waste of time
            var orderItems = vm.orderDC.getOrderItems();
            vm.productItems = angular.copy(orderItems);

            var orderProduceItems = vm.orderDC.getProduceItems();
            vm.produceItems = angular.copy(orderProduceItems);
            vm.loadCustomerProduceProducts();

            vm.refreshGridItems();
            vm.refreshOrderItems();
            vm.GetNextDeliveryTotals();
        };

        function setActiveCats() {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
            if (vm.produceBranchAvailable.indexOf(curBranch) !== -1) {
                vm.produceViewAvailable = true;
            }
            else {
                vm.produceViewAvailable = false;
            }
            var catlist = vm.categoryDC.productViewCategorys;
            vm.activeCats = [];
            for (var i = 0; i < catlist.length; i++) {

                if (!catlist[i].inactiveBranches.includes(curBranch)) {

                    vm.activeCats.push(catlist[i]);
                }
            }

        }

        vm.subClick = function (product) {
            vm.subProduct = product;
            vm.subModalVisible = true;
        }

        vm.showModal = function () {
            return vm.subModalVisible && typeof vm.subProduct === 'number';
        }

        vm.showSubNotificationModal = function () {
            return vm.subNotificationModalVisible
        }

        vm.updateCustomerSubstitutionPreferences = function (product, event) {
            vm.customerSubstitutionPreferences[product] = event.target.checked;
            datacontext.order.setCustomerProductPreferences(vm.customerSubstitutionPreferences, datacontext.cust.mycust.order[0].customerId);
        }

        vm.decideClasses = function (productNumber) {
            var classes = "";
            if (vm.isMobile) { classes += "col-md-4"; }
            if (vm.products[productNumber] != undefined) {
                if (vm.products[productNumber].substitutions.length > 0) {
                    classes += " one-third";
                } else {
                    classes += " one-half"
                }
            }

            return classes
        }
        $('#substitudeModal').modal({ backdrop: true, show: false })

        $('#substitudeModal').on('hidden.bs.modal', function (e) {
            vm.subModalVisible = false;
            vm.subProduct = null;
        })

        $('#substituteFeatureNotification').modal({ backdrop: true, show: false })

        $('#substituteFeatureNotification').on('hidden.bs.modal', function (e) {
            vm.subNotificationModalVisisble = false;
        })

        vm.branchInCategory = function (category) {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            if (!category) {
                return true;
            }
            var curBranch = 1;
            var inactiveBranches = category.inactiveBranches;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }

            for (var i = 0; i < inactiveBranches.length; i++) {
                if (inactiveBranches[i] === curBranch) {
                    return false;
                }

            }
            return true;
        }

        $scope.tempMessage = 'As a family owned company, Oberweis recognizes the Christmas holiday as a time to celebrate with family and friends. In order to extend this celebration to all employees we will not be providing home delivery services on Friday, December 25th.';

        $scope.$state = $state;

        $scope.userSuspended = function () {
            return false;
        }

        vm.isFirstDelivery = true;
        vm.showOrderFail = false;
        vm.showProduceOrderFail = false;
        vm.showDeliveryLockoutModal = false;
        vm.skipDeliveryModal = false;
        vm.incompleteCustomerSignup = false;
        vm.isNewStart = false;
        vm.showOrderAdjustmentModal = false;
        vm.totalsRefreshing = false;
        vm.isRecipeView = false; // set from recipe view
        vm.webReinstate = { reinstated: false, isCampaignMember: false, campaignDescription: '' }

        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal) {
                $scope.userSuspended = function () {
                    return datacontext.cust.mycust.userSuspended;
                }

                vm.incompleteCustomerSignup = datacontext.cust.mycust.incompleteCustomerSignup;

                vm.localCutoff = datacontext.cust.mycust.localCutoff;
                vm.isNewStart = (datacontext.cust.mycust.incompleteCustomerSignup || datacontext.isNewCustomer);

                if (vm.incompleteCustomerSignup && !vm.isRecipeView) {
                    redirectToIncompleteSignUp()
                }

                vm.webReinstate = datacontext.cust.mycust.webReinstate;
            }
        });

        function redirectToIncompleteSignUp() {
            if (vm.incompleteCustomerSignup) {
                var target = $state.current.name.toLowerCase();
                if (target.indexOf('cart') >= 0) {
                    $state.go('sign-up.2.cart');
                }
                else {
                    $state.go('sign-up.2.category');
                }
            }
        }

        vm.appVersion = appVersion;
        vm.productClass = function (productId) { }
        vm.showAddItem = function (productId) { }
        vm.showRemoveItem = function (productId) { }

        /* Determines if a delivery day lockout is in effect */
        vm.lockUser = function () {
            return datacontext.cust.mycust.lockUser;
        }

        // Was the order suspended by the user
        vm.isUserSuspended = function () {
            return false;
        }

        // Close the delivery lockout modal
        vm.cancelUserLockoutModal = function () {
            vm.showDeliveryLockoutModal = false;
        }

        // Close order fail modal
        vm.cancelFailed = function () {
            vm.showOrderFail = false;
        }
        vm.cancelProduceFailed = function () {
            vm.showProduceOrderFail = false;
        };

        vm.cancelMerged = function () {
            vm.showMergedCartOrder = false;
        }

        vm.cancelMergedProduct = function () {
            vm.showProductMergeMessage = false;
        }

        // Close the warning modal
        vm.cancelWarningModal = function () {
            vm.showOrderThresholdWarning = false;
        }

        // Close the warning modal
        vm.cancelFirstOrderModal = function () {
            vm.showFirstOrderOverThresholdModal = false;
        }

        // Cancels the skip delivery modal
        vm.cancelSkipDeliveryModal = function () {
            vm.skipDeliveryModal = false;
        }

        // Cancels the skip delivery and opens the suspend modal
        vm.disableSkipDeliveryModal = function () {
            vm.skipDeliveryModal = false;
            //vm.showSuspendModal = true;
        }

        vm.closeOrderAdjustmentModal = function () {
            vm.showOrderAdjustmentModal = false;
        };

        vm.isCategoryEmpty = function (category) {
            // this code is commented out because the flag needs to be reset after the customer information
            // is added to the local data and items are removed because they are out of stock.
            //  since they are not rest it is being evaluated every time

            var catHasProducts = checkCategoryForProducts(category);
            category.emptyFlag = !catHasProducts;

            return category.emptyFlag;
        }

        vm.checkOnlyCategoryForProducts = function (cat) {
            var visibleProd = false;
            var prodList = cat.prods;
            for (var inx = 0; inx < prodList.length; inx++) {
                var prod = vm.products[prodList[inx]];
                if (prod.showOnWeb) {
                    visibleProd = true;
                    break;
                }
            }
            return visibleProd;
        }

        vm.isAuthenticated = function () {
            vm.isAuth = authService.authentication.isAuth;
            return vm.isAuth;
        }

        // Get the bottle discount
        vm.getGlassBottleDiscount = function () {
            if (datacontext.cust != null) {
                if (datacontext.cust.mycust != null) {
                    for (var i = -0; i < datacontext.cust.mycust.depositItems.length; i++) {
                        if (datacontext.cust.mycust.depositItems[i].id == 4990) {
                            return '$' + datacontext.cust.mycust.depositItems[i].price.toFixed(2);
                        }
                    }
                }
                else {
                    return "(Price Not Currently Available)";
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }
        // Get the produce tote discount
        vm.getProduceToteDiscount = function () {
            if (datacontext.cust != null) {
                if (datacontext.cust.mycust != null) {
                    for (var i = -0; i < datacontext.cust.mycust.depositItems.length; i++) {
                        if (datacontext.cust.mycust.depositItems[i].id == 4972) {
                            return '$' + datacontext.cust.mycust.depositItems[i].price.toFixed(2);
                        }
                    }
                }
                else {
                    return "(Price Not Currently Available)";
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }

        // Gets the dry ice cartridge discount
        vm.getDryIceDiscount = function () {
            if (datacontext.cust != null && datacontext.cust.mycust != null && datacontext.cust.mycust.depositItems != null) {
                for (var i = -0; i < datacontext.cust.mycust.depositItems.length; i++) {
                    if (datacontext.cust.mycust.depositItems[i].id == 4907) {
                        return '$' + datacontext.cust.mycust.depositItems[i].price.toFixed(2);
                    }
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }

        // Gets the porch box price
        //this really shouldn't be used... see porchBoxController.getPorchBoxPrice()
        vm.getPorchBoxPrice = function () {
            if (datacontext.cust != null) {
                if (datacontext.cust.mycust != null) {
                    return '$' + datacontext.cust.mycust.porchBoxItems.productPrice.toFixed(2);
                }
                else {
                    return "(Price Not Currently Available)";
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }

        // Gets the ice cream bag discount
        vm.getIceCreamBagDiscount = function () {
            if (datacontext.cust != null && datacontext.cust.mycust != null && datacontext.cust.mycust.depositItems != null) {
                for (var i = -0; i < datacontext.cust.mycust.depositItems.length; i++) {
                    if (datacontext.cust.mycust.depositItems[i].id == 4906) {
                        return '$' + datacontext.cust.mycust.depositItems[i].price.toFixed(2);
                    }
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }


        vm.showOrderEdits = vm.isAuthenticated() || datacontext.isNewCustomer || datacontext.isReturning || vm.incompleteCustomerSignup;

        function checkCategoryForProducts(cat) {
            var visibleProd = false;
            var prodList = cat.prods;
            for (var inx = 0; inx < prodList.length; inx++) {
                var prod = vm.products[prodList[inx]];

                // here needs to check for out of stock noshow flag
                if ((prod) && prod.showOnWeb) {
                    visibleProd = true;
                    break;
                } else {
                    var not = prod;
                }
            }
            if (!visibleProd)
                visibleProd = CheckKidsForProducts(cat);
            return visibleProd;
        }

        function CheckKidsForProducts(category) {
            var visibleProd = false;
            for (var inx = 0; inx < category.sortedChildren.length; inx++) {
                if (checkCategoryForProducts(category.sortedChildren[inx]))
                    return true;
            }
            return false;
        }

        vm.continueButtonClicked = function () {
            datacontext.cust.mycust.hideReminder = true;
            if (!vm.minQuantityAlert()) {
                var event_name = 'signup_step_2_complete';
                var eventData = {
                    customerId: datacontext.cust.mycust.id,
                    email: datacontext.cust.mycust.eMail,
                    state: datacontext.cust.mycust.state,
                    zip: datacontext.cust.mycust.zip
                };
                $scope.$parent.vm.NavigateToNext(event_name, eventData);
            }
        }

        vm.isActiveGroup = function (group) {
            return ($state.params.productViewId) && $state.params.productViewId.indexOf(group) >= 0;
        }

        $scope.$root.SwitchToListView = function (viewType) {
            datacontext.cust.mycust.listView = viewType;
        }

        $scope.$root.getCurrentMenuUrl = function () {
            var date = new Date();
            return "home-delivery/menu/" + date.getFullYear() + "/" + (date.getMonth() + 1);
        }

        $scope.$root.isListView = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.listView;
        }

        vm.isActiveCategory = function (category) {
            if ($state.params.subViewId)
                return ($state.params.subViewId.indexOf(category) >= 0);
            else {
                return false;
            }
        }

        vm.showcartButton = function () {
            return ($state.current.name.indexOf('cart') < 0 && $state.current.name.indexOf('order-change') < 0) && vm.showOrderEdits;
        }

        vm.checkoutButtonClicked = function () {
            vm.showStickycart = false;
            // Determine how to construct the shopping cart route and then go there.
            var nurl = $state.current.name.indexOf('product') >= 0 ? '^.^.' : '^.';
            if ($state.current.name == 'sign-up.2.product') {
                nurl = '^.';
            }
            $state.go(nurl + 'cart');
        }

        vm.continueStandingOrderModal = function () {
            vm.showStandingOrderModal = false;
        }

        vm.getCategory = function (product) {
            if (product.brand == 'Oberweis') return product.categoryName;
        }

        vm.changeSubCategory = changeSubCategory;
        vm.baseUrl = config.baseUrl;
        vm.mycust = datacontext.cust.mycust;
        vm.isAuth = authService.authentication.isAuth;


        vm.logOut = logOut;
        function logOut() {
            authService.logOut();
            $state.go("sign-in");
        }

        vm.animationsEnabled = true;
        vm.title = "Products";

        vm.prodSearchTxt = $state.params.search || '';
        vm.searchText = '';
        vm.filteredProds = [];
        vm.prodsFilter = prodsFilter;


        vm.isMobile = ($window.innerWidth < 768);

        vm.isMdSize = ($window.innerWidth > 992);

        angular.element($window).on('resize', function () {
            vm.isMobile = ($window.innerWidth < 768)
            vm.isMdSize = ($window.innerWidth > 992);
            $scope.$apply();
        });

        $scope.$root.productSearch = search;
        $scope.$root.catalogViewShowLookbook = function () {
            vm.ChangecategoryView('lookbook');
        }

        vm.preOrderSelected = false;
        $scope.$root.catalogViewShowPreOrder = function () {
            vm.preOrderSelected = true;
            vm.ChangecategoryView('preorder');
        }

        $scope.$root.catalogViewShowCollections = function () {
            vm.ChangecategoryView('collections');
        }
        $scope.$root.catalogViewShowProduce = function () {
            vm.ChangecategoryView('produce');
        }

        var timeOut;
        function search(searchText) {
            clearTimeout(timeOut);
            timeOut = setTimeout(function () {
                vm.productsDC.searchText = searchText;
                window.scrollTo(0, 0);
                if (!vm.productsDC.searchText || vm.productsDC.searchText === '') {
                    vm.productsDC.searchText = '';
                    datacontext.category.setProductViewName(vm.productViewId);
                    if (datacontext.category !== undefined) {
                        vm.subcategoryid = datacontext.category.selectedCategory.name;
                        vm.changeSubCategory(vm.subcategoryid);
                    }
                    applyFilter();
                } else {
                    datacontext.category.setProductViewName('all');
                    applyFilter();
                }
            }, 300);
        }

        function prodsFilter(prod) {
            var textContains = common.textContains;
            var searchText = vm.productsDC.searchText;
            var isMatch = searchText ?
                textContains(prod.title, searchText)
                || textContains(prod.seoKeywords, searchText)
                || textContains(prod.description, searchText)
                || textContains(prod.fullDisplayText, searchText)
                || textContains(prod.volume, searchText)
                : true;
            prod.noMatch = !isMatch;

            return isMatch;
        }

        vm.hasData = false;

        vm.orderItems = [];
        vm.DeliveryDate = {};
        vm.CutoffDate = {};

        // vm.products = datacontext.products.entityItems;
        vm.custDC = datacontext.cust;
        vm.categoryDC = datacontext.category;
        vm.productsDC = datacontext.products;
        vm.orderDC = datacontext.order;

        // vm.categories = vm.categoryDC.categories;

        vm.gotoProductDetail = gotoProductDetail;
        vm.saveChange = saveChange;
        vm.step = datacontext.cust.NewCustomerStep;

        // to do: grab these values from a DB
        vm.showOutOfStock = function (prd) {
            if (!datacontext.products.partialsMappedLoaded) return false;

            return datacontext.products.showOutOfStock(prd);
        }

        vm.allowOrderEdits = function (prd) {
            if (!datacontext.products.partialsMappedLoaded) return false;
            return datacontext.products.allowOrderEdits(prd);
        }

        /* Returns whether a minimum quantity exists for either the standing or next order total*/
        vm.minQuantityAlert = function () {
            if (datacontext.order.GetNextOrderItemsCount != null && datacontext.order.GetStandingOrderItemsCount != null) {
                var nextOrderTotal = datacontext.order.GetNextOrderItemsCount();
                var standingOrderTotal = datacontext.order.GetStandingOrderItemsCount();
                return (nextOrderTotal == 0 || standingOrderTotal == 0);
            }
            return false;
        }

        /* Returns whether or not this is an on-demand customer */
        vm.onDemandCustomer = function () {
            if (vm.custDC && vm.custDC.mycust) {
                if (vm.custDC.mycust != null) {
                    return vm.custDC.mycust.onDemandCustomer;
                }
            }
            else {
                return false;
            }
        }

        vm.GetNextDeliveryTotals = function () {
            return datacontext.order.GetNextDeliveryTotals();
        }

        vm.GetStandingDeliveryTotals = function () {
            return datacontext.order.GetStandingDeliveryTotals();
        }

        vm.Remove = _remove;
        vm.checkOut = checkOut;
        vm.activate = activate;
        vm.noindexProducts = [];
        vm.showCart = false;
        vm.showStickycart = false;
        vm.showOneTimeModal = false;


        vm.ProcessOneTimeModal = function () {
            vm.showHouseModal = false;
            vm.showApartmentModal = false;
            vm.showHouseApartmentModal = false;
            vm.showOneTimeModal = false;
            vm.showOrderErrorModal = false;
            datacontext.cust.setShowOneTimePopup(false);
            datacontext.cust.setShowOneTimePopupApartment(false);
            datacontext.cust.setShowOneTimePopupHouse(false);
            return false;
        }

        vm.GoToVideoTutorial = function () {
            vm.showOneTimeModal = false;
            datacontext.cust.setShowOneTimePopup(false);
            $('.modal-backdrop.fade.in').remove();
            window.location.href = "/home-delivery/shopping/tutorial";
        }

        vm.cartMessage = '';
        vm.showCartMessage = showCartMessage;
        vm.refreshOrderItems = refreshOrderItems;
        vm.refreshGridItems = refreshGridItems;

        vm.TopMiscProducts_Message = "Other Fantastic Products";

        vm.showExtraProductsHeader = function () {
            return vm.categoryDC.categories.length > 0
                && vm.categoryDC.productViewCategory.prods.length > 0;
        }

        vm.showMyAccountLink = function () {
            if ($state.current.url.indexOf('account') >= 0)
                return false;
            else
                return true;
        }

        vm.showShoppingLink = function () {
            if ($state.current.url.indexOf('account') >= 0)
                return true;
            else
                return false;
        }

        vm.showOnWebFilter = function (productNumber) {
            if (vm.products[productNumber])
                return vm.products[productNumber].showOnWeb;
            else
                return false;
        }

        /**
         * @summary Returns true if there are any products in the provided number array that has showOnWeb enabled.
         * @param {number[]} products
         * @return {boolean}
         */
        vm.hasShowOnWeb = function (products) {
            for (var i = 0; i < products.length; i++) {
                var product = vm.productsDC.entityItems[products[i]];
                if (product && product.showOnWeb) {
                    return true;
                }
            }

            return false;
        }

        var applyFilter = function () { };

        function _remove(product) {
            product.nextQuantity = 0;
            //no longer remove standing order per marketing team direction
            //product.standingQuantity = 0;
            vm.saveChange(product);
        }

        vm.showDetail = function () { return false; };
        vm.gotoThumbs = function () { $state.go('^.all'); };
        vm.changeNextQuantity = changeNextQuantity;
        vm.checkForUnMergedEdits = checkForUnMergedEdits;
        vm.products = [];// vm.productsDC.entityItems;}

        vm.nextDelivery = function (item) {
            return item && item.nextQuantity && item.nextQuantity > 0;
        }

        vm.standingDelivery = function (item) {
            return item && item.standingQuantity && item.standingQuantity > 0;
        }

        function resetOOSFlagToFalse() {
            var cust = datacontext.cust.mycust;
            var url = "api/order/ChangeOOSFlag";
            $http.post(url, cust).success(function (data) {
                datacontext.cust.mycust.removedOOSProduct = data;

            });
        }

        vm.checkoutWarningCheck = function () {
            if (datacontext && datacontext.cust && datacontext.cust.mycust) {
                if (datacontext.cust.mycust.editsMadeAfterLastCheckout) {
                    return true;
                }
                else {

                    return false;
                }
            }
            else {
                return false;
            }
        }

        function needsToCheckout() {
            datacontext.order.editsMadeAfterLastCheckout();
        }

        function _getProductOnlyDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.productTotals) ? datacontext.order.orderTotals.productTotals : 0;
        };
        function newCustFirstDelivery() {
            checkIfFirstDelivery().then(function (result) {
                var paymentHistory = result;
                //it is not their first order
                if (paymentHistory.length > 0) {
                    vm.checkForUnMergedEdits();
                }
                else {
                    GetNewCustMaxSpendThreshold().then(function (result) {
                        vm.newCustMaxSpendThreshold = result;
                        var productTotal = vm.GetProductOnlyTotals();
                        //their total is greater than the threshold
                        if (productTotal.total > vm.newCustMaxSpendThreshold) {
                            vm.showFirstOrderOverThresholdModal = true;
                        }
                        else {
                            vm.checkForUnMergedEdits();
                        }
                    });

                }

            }, function () {
                vm.showOrderErrorModal = true;
            });
        };

        vm.checkIfPaymentRequired = function () {
            var newOrderTotal = vm.GetNextDeliveryTotals();

            $http.post('api/payments/GetPaymentRequiredToSaveOrder', newOrderTotal.total)
                .success(function (response) {
                    if (response.amountRequired === 0) {
                        //The customer does not need to make any additional payments
                        vm.checkForUnMergedEdits();
                        vm.checkoutPaymentData = null;
                    }
                    else {
                        //The new order total exists what was previously paid and the rules require this customer to payt he difference now
                        vm.checkoutPaymentData = {
                            cartTotal: newOrderTotal.total,
                            priorBalance: response.existingCreditAmt,
                            amountRequired: response.amountRequired
                        };

                        //show them a modal and make them confirm the additional payment or press cancel
                        vm.showPaymentIsRequiredModal = true;
                    }
                })
                .error(function (data) {
                    vm.showOrderErrorModal = true;
                });
        };

        vm.payAndSubmitOrder = function () {
            vm.checkOut();
        };

        vm.cancelPaymentRequiredModal = function () {
            vm.showPaymentIsRequiredModal = false;
        };

        function checkForUnMergedEdits() {
            var cust = datacontext.cust.mycust;
            var currentCustEditTime = cust.orderHeaderUpdatedOn;
            var oldOrder = angular.copy(cust.order[0]);
            var url = "api/order/UnmergedEdits";
            $http.get(url).then(function (result) {
                var customerDBOrder = result.data;
                var lastUpdatedTime = customerDBOrder.updatedOn;
                if (lastUpdatedTime > currentCustEditTime) {
                    vm.showMergedCartOrder = true;
                    common.$broadcast(config.events.spinnerToggle, { show: true });

                    datacontext.order.PostOrderDetailUpdate().then(function () {
                        vm.refreshGridItems();
                        vm.refreshOrderItems();
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    });

                    for (var i = 0; i < customerDBOrder.orderDetail.length; i++) {
                        var oldOrderItem = oldOrder.orderDetail.find(x => x.productId == customerDBOrder.orderDetail[i].productId);
                        if (oldOrderItem) {
                            if (oldOrderItem.nextQuantity !== customerDBOrder.orderDetail[i].nextQuantity ||
                                oldOrderItem.standingQuantity !== customerDBOrder.orderDetail[i].standingQuantity) {
                                if (vm.products[customerDBOrder.orderDetail[i].productId]) {
                                    vm.products[customerDBOrder.orderDetail[i].productId].merged = true;
                                    if ((customerDBOrder.orderDetail[i].nextQuantity == 0 && customerDBOrder.orderDetail[i].nextQuantity !== vm.products[customerDBOrder.orderDetail[i].productId].nextQuantity) ||
                                        (customerDBOrder.orderDetail[i].standingQuantity == 0 && customerDBOrder.orderDetail[i].standingQuantity !== vm.products[customerDBOrder.orderDetail[i].productId].standingQuantity)) {
                                        vm.products[customerDBOrder.orderDetail[i].productId].isRemoved = true;
                                    }
                                }
                            }
                            else {
                                if (vm.products[customerDBOrder.orderDetail[i].productId])
                                    vm.products[customerDBOrder.orderDetail[i].productId].merged = false;
                            }
                        }
                        else {
                            //prod was removed/added by another user 
                            if (vm.products[customerDBOrder.orderDetail[i].productId]) {
                                vm.products[customerDBOrder.orderDetail[i].productId].merged = true;
                                if ((customerDBOrder.orderDetail[i].nextQuantity == 0 && customerDBOrder.orderDetail[i].nextQuantity !== vm.products[customerDBOrder.orderDetail[i].productId].nextQuantity) ||
                                    (customerDBOrder.orderDetail[i].standingQuantity == 0 && customerDBOrder.orderDetail[i].standingQuantity !== vm.products[customerDBOrder.orderDetail[i].productId].standingQuantity)) {
                                    vm.products[customerDBOrder.orderDetail[i].productId].isRemoved = true;
                                }
                            }
                        }
                    }
                }
                else {
                    for (var i = 0; i < customerDBOrder.orderDetail.length; i++) {
                        if (vm.products[customerDBOrder.orderDetail[i].productId])
                            vm.products[customerDBOrder.orderDetail[i].productId].merged = false;
                    }
                    vm.checkOut();
                }

            });
        }

        function changeNextQuantity(product, quantity) {
            // Checks if threshold warning message has not been displayed already
            if (vm.showedOrderThresholdWarning == false) {
                // EPOCH
                //sets the default time zone to be used for moment() to central becuase all of the branch cutoffs are sent in central
                moment.tz.setDefault("America/Chicago");

                //Sets the cutoff time to the branch cutoff and appends the central TZ to it and parses it into miliseconds UTC
                var cutoffDateTime = Date.parse(moment(datacontext.cust.mycust.branchCutoff).format());

                //grabs the current time in the chicago timezone
                var currentTime = moment().format();

                // Displays threshold warning if current time is greater than 8:45pm
                if (cutoffDateTime - 900000 <= currentTime) {
                    vm.showOrderThresholdWarning = true;
                    vm.showedOrderThresholdWarning = true;
                }

                moment.tz.setDefault();
            }

            if (!vm.updateDisabled) {

                var orgProd = angular.copy(product);

                var p = product;
                if (vm.products[p.id])
                    vm.products[p.id].merged = false;

                if (p.nextQuantity) {
                    p.nextQuantity = p.nextQuantity + quantity;
                } else if (quantity > 0) {
                    p.nextQuantity = quantity;
                }
                if (!vm.isAuth && product.categoryName != "Merchandise") {
                    if (p.standingQuantity) {
                        p.standingQuantity = p.standingQuantity + quantity;
                    } else if (quantity > 0) {
                        p.standingQuantity = quantity;
                    }
                }


                p.changed = true;

                vm.saveChange(p);
                if (product.outOfStock === true || product.OOSEdgeCaseFlag === true) {
                    var orderDetails = datacontext.cust.mycust.order[0].orderDetail;
                    var lengthOfOrder = datacontext.cust.mycust.order[0].orderDetail.length;

                    for (var i = 0; i < lengthOfOrder; i++) {
                        if (orderDetails[i].productId === product.id) {
                            var previouslyOrderedQuant = orderDetails[i].nextQuantityOriginal;
                        }
                    }
                    if (product.nextQuantity >= previouslyOrderedQuant) {
                        product.outOfStock = true;
                        product.OOSEdgeCaseFlag = false;
                    }
                    else {
                        product.outOfStock = false;
                        product.OOSEdgeCaseFlag = true;

                    }
                }
                else {
                    product.outOfStock = false;
                }
                correctCartScrolling(orgProd);
            }
        }

        function correctCartScrolling(product) {
            var target = $state.current.name.toLowerCase();
            if (target.indexOf('cart') >= 0 && product.nextQuantity == 0 && !product.isRemoved) {
                var $container = $('#cart-outer');
                var $innerContainer = $('#cart-inner');
                var body = document.body;
                var initialHeight = $container.height();

                $container.css("overflow", "hidden").css("height", initialHeight);

                var timer = window.setInterval(function () {
                    var scrollDiff = ($innerContainer.height() - initialHeight);
                    if (scrollDiff != 0) {
                        clearInterval(timer);
                        $container.css("overflow", "hidden").css("height", "100%");
                        body.scrollTop += scrollDiff;
                    }
                }, 50);
            }
        }

        function refreshOrderItems() {
            vm.productItems = vm.orderDC.getOrderItems(true);
            var orderProduceItems = vm.orderDC.getProduceItems(true);
            vm.produceItems = angular.copy(orderProduceItems);
            vm.loadCustomerProduceProducts();
            vm.loadDefaultProduceBox();


        }

        function refreshGridItems() {
            vm.products = datacontext.products.entityItems;
        }

        function checkOut() {
            datacontext.cust.mycust.hideReminder = true;

            //sets the TZ to central bc all branch cutoffs are in central
            moment.tz.setDefault("America/Chicago");

            // EPOCH
            var cutoffDateTime = Date.parse(moment(datacontext.cust.mycust.branchCutoff).format());

            //grabs the current time in the chicago timezone
            var currentTime = moment().format();

            // Submitted after 9pm tell them it failed and skip the push to AS400
            if (currentTime >= cutoffDateTime) {
                vm.showOrderFail = true;
            }
            else {
                if ((vm.minQuantityAlert() && vm.onDemandCustomer())
                    || !vm.minQuantityAlert()
                    || !$scope.userSuspended) {

                    // If the server says that additional payment is required, then charge the customer before proceeding
                    if (vm.checkoutPaymentData && vm.checkoutPaymentData.amountRequired && vm.checkoutPaymentData.amountRequired > 0) {

                        //Only create the fields we need to post from a card on file using the Payment Processor Token
                        var oneTimePayment = {
                            customerNumber: 0,
                            paymentMethod: "cardonfile",
                            amountToPay: vm.checkoutPaymentData.amountRequired
                        };

                        $http.post("api/payments/PostOneTimePayment", oneTimePayment)
                            .then(function(response) {
                                //Payment Succeeded
                                pushOrderAndRefresh();

                                $q.all([
                                    vm.customerDC.getAccountBalanceSummary(true),
                                    datacontext.cust.getPaymentSummary(true).then(function() {
                                        $scope.getPaymentHistory();
                                    })
                                ]);
                            })
                            .catch(function(data, status, headers, config) {
                                //Payment Failed
                                console.log("error");
                                vm.showOrderErrorModal = true;
                            });
                    }
                    else {
                        pushOrderAndRefresh();
                    }
                }
            }

            moment.tz.setDefault();

            function pushOrderAndRefresh() {
                datacontext.order.PushOrderToAS400()
                    .success(function (data) {
                        datacontext.order.isDirty = false;
                        $state.go("^.order-change");
                        originalOnDemandCustomer = datacontext.cust.mycust.onDemandCustomer;
                        vm.showScheduledDeliveryOffer = originalOnDemandCustomer;
                        checkOrderAdjustments(data);

                        var customerProductPreferences = $(".product-pref-checkbox")

                        for (let i = 0; i < customerProductPreferences.length; i++) {
                            var id = Number(customerProductPreferences[i].id)
                            var checked = customerProductPreferences[i].checked
                            vm.customerSubstitutionPreferences[id] = checked
                        }

                        datacontext.order.setCustomerProductPreferences(vm.customerSubstitutionPreferences, datacontext.cust.mycust.order[0].customerId);
                    })
                    .error(function () {
                        vm.showOrderErrorModal = true;
                    });
            };
        }

        function checkOrderAdjustments(products) {
            if (products.length > 0) {
                vm.adjustedItems = products;

                products.forEach(function (item) {
                    var product = vm.products[item.productNumber];
                    product.nextQuantity = item.newQuantity;

                    product.outOfStock = true;
                });

                vm.showOrderAdjustmentModal = true;
            }
        }

        function showNextOrderEdits() {
            return vm.isAuth || (datacontext.cust.mycust.startupStep == '0' || datacontext.cust.mycust.startupStep == '2');
        }

        function showStandingOrderEdits() {
            return vm.isAuth || (datacontext.cust.mycust.startupStep == '0' || datacontext.cust.mycust.startupStep == '3');
        }

        vm.getProductMessage = getProductMessage;

        function getProductMessage(productIndex) {
            var message = '';
            var product = vm.products[productIndex];

            // If the product isn't found, then log it and return.
            if (!product) {
                return;
            }

            // Format the delivery date
            var date = moment(vm.DeliveryDate).format("L");

            // If the product is out of stock, then show that message
            if (product.OutOfStock) {
                message = "Sold out for " + date;
            }

            // If the customer object is null, then return
            if (!datacontext.cust == null) {
                return;
            }

            if (datacontext.cust.mycust.vendorLock && product.categoryName.indexOf('Produce') >= 0) {
                message = "Produce is not available on " + date + " due to our supplier's holiday schedule";
            }

            if (datacontext.cust.mycust.twoDayCutoff && product.twoDayLeadRequired) {
                message = "Must be ordered 2 days prior to delivery.";
            }

            return message;
        }

        vm.showIceCreamBagModal = false;

        vm.rowClicked = function (row) {
            row.expand = !row.expand;
        }

        vm.onImageLoad = function (evt) {
            console.log(evt)
            var results = $('img-responsive')
            console.log(results)
        }

        vm.IceCreamBagOption = "purchase";
        vm.ProcessBagOption = ProcessBagOption;
        function ProcessBagOption() {
            //
            // this is called when the continue button is pressed.
            var bag = [];

            switch ("" + vm.IceCreamBagOption) {
                case "purchase":
                    //Purchase an ice cream bag (defaulted)
                    //o    Add to Next Delivery product code 4906
                    //o    Add to Standing Order product code 27

                    bag.push(
                        {
                            productId: 4906,
                            standingQuantity: 0,
                            nextQuantity: 1,
                        });

                    resetIceCreamBagRemoveFlag();

                    bag.push(
                        {
                            productId: 27,
                            standingQuantity: 1,
                            nextQuantity: 1
                        });

                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;
                case "own":
                    // o    Add to both Next Delivery and Standing Order product code 26

                    bag.push({
                        productId: 27,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;
                case "knock":
                    //o    Add to both Next Delivery and Standing Order product code 27
                    bag.push({
                        productId: 26,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;

            }
            bag.push(vm.IceCreamBagitem);

            datacontext.order.PostOrderDetailUpdate(bag)
                .then(function () {
                    vm.refreshGridItems();
                    vm.refreshOrderItems();
                });
            vm.showIceCreamBagModal = false;
        };

        vm.IceCreamBagitem;

        vm.RejectBagOption = RejectBagOption;

        function RejectBagOption() {
            vm.IceCreamBagitem.nextQuantity = 0;
            vm.IceCreamBagitem.standingQuantity = 0;
            vm.showIceCreamBagModal = false;
        };

        function checkPorchBoxDiscount(itm) {

            var freePorchBox = datacontext.cust.mycust.promoCode && datacontext.cust.mycust.promoCode.allowCoolerFree && datacontext.cust.mycust.porchBox == 'FREE';

            if (itm.productId == 4901) {
                datacontext.order.PostOrderDetailUpdate({
                    productId: 8408,
                    standingQuantity: 0,
                    nextQuantity: (itm.nextQuantity > 0 && freePorchBox) ? 1 : 0
                }).then(function () {
                    vm.refreshGridItems();
                    vm.refreshOrderItems();
                });
            }
        }

        function saveChange(itm) {
            //customer edits are type 4
            itm.updateType = 4;
            if (itm.standingQuantity === undefined) {
                itm.standingQuantity = 0;
            }
            if (datacontext.cust.mycust.removedOOSProduct === true) {
                resetOOSFlagToFalse();
            }
            if (!(itm.standingQuantity == null || itm.nextQuantity == null)) {

                datacontext.cust.mycust.orderChanged = true;

                itm.isRemoved = (itm.standingQuantity === 0 && itm.nextQuantity === 0);

                if (angular.isDefined(itm.requiresIceCreamBag) && (!datacontext.cust.mycust.hasIceCreamBag) && (itm.requiresIceCreamBag)) {
                    vm.IceCreamBagitem = itm;
                    vm.showIceCreamBagModal = true;
                    datacontext.cust.mycust.showIceCreamBagModal = true;
                }

                try {
                    vm.totalsRefreshing = true;
                    datacontext.order.PostOrderDetailUpdate(itm).then(function (result) {
                        needsToCheckout();
                        if (itm.isRemoved && itm.requiresIceCreamBag == 1) {
                            RemoveIceCreamBagCheck();
                        }



                        vm.refreshGridItems();
                        vm.refreshOrderItems();

                        checkPorchBoxDiscount(itm);
                        vm.totalsRefreshing = false;
                    },
                        function () {
                            vm.refreshGridItems();
                            vm.refreshOrderItems();
                            vm.totalsRefreshing = false;
                        });
                }
                catch (err) {
                    vm.refreshGridItems();
                    vm.refreshOrderItems();
                    vm.totalsRefreshing = false;
                }

            }
        }

        function resetIceCreamBagRemoveFlag() {
            var itm = datacontext.products.entityItems[4906];
            if (itm) {
                itm.isRemoved = false;
            }

        }

        function RemoveIceCreamBagCheck() {
            var orderItems = datacontext.order.getOrderItems();
            var requiresIceCreamBag = false;
            angular.forEach(orderItems, function (item) {
                if (item.requiresIceCreamBag == 1) {
                    requiresIceCreamBag = true;
                }
            });

            if (!requiresIceCreamBag) {
                var itm = datacontext.products.entityItems[4906];
                itm.isRemoved = true;
                itm.nextQuantity = 0;
                itm.standingQuantity = 0;
                datacontext.order.PostOrderDetailUpdate(itm);
                datacontext.cust.mycust.hasIceCreamBag = false;
            }
        }

        vm.showAccountMessage = false;

        vm.goToAccountHideModal = goToAccountHideModal;
        function goToAccountHideModal() {
            vm.showAccountMessage = false;
            $timeout(function () {
                // this was added because it is necessary to wait for the background to be removed before the navigation occurs
                $state.go("^.account");
            }, 1000);
        }

        vm.NameSelectedCategory = "";

        vm.productViewId = ($state.params.productViewId || '').toLowerCase();
        vm.subcategoryid = ($state.params.subViewId || '').toLowerCase();

        function changeSubCategory(newSubCategory) {
            if (vm.productViewId == 'products') {
                if (newSubCategory && (newSubCategory.length > 0)) {
                    datacontext.category.selectcategory(newSubCategory);
                }
            }
        }

        function NeedsReroute() {
            //Three route params are used in the SPA
            //Categories and the recipe/product grid use prodView and subView
            //specific recipes and products use IDs
            var params = $state.params;
            var cat = params.productViewId;
            var sub = params.subViewId;
            var id = params.id;
            var toParams = { productViewId: cat, subViewId: sub, id: id };

            //  this section redirects based on a user trying to go to
            //  open market from the logged in market.  basically keeps
            //  in the logged in market
            var target = $state.current.name.toLowerCase();
            if (target.indexOf('cart') >= 0) {
                return false;
            }
            //alert(target)
            if ((target.indexOf('browsing') >= 0) && (vm.isAuth)) {
                //  this prevents a user that is currently shopping to try to go to
                //  browsing mode // huh? -> the first state stops the routing because of the spinner
                target = target.replace('browsing', 'shopping');

                $state.go(target, toParams, {
                    reload: false,
                    inherit: false,
                    notify: true
                });
                return true;
            }

            return false;
        }

        function getMarketviewType() {
            return !vm.isAuth ? 'browsing' : 'shopping';
        }

        vm.changeState = changeState;
        function changeState(targetview, targetSubview, targetState) {
            // targetState category/detail/cart

            if (!(targetState) || targetState.length == 0) targetState = 'category';

            var currentState = $state.current.name.toLowerCase();
            if (targetState.length > 0 && currentState.indexOf(targetState) < 0) {
                // not viewing requested state needs to route
                var prefix = '';
                var newParms = {
                    productViewId: targetview, subViewId: targetSubview
                };

                newParms = getViewParms(newParms)

                if (targetState.indexOf('.') < 0) {
                    var statePrts = currentState.split('.');
                    var prefix = '';
                    for (var inx = 1; inx < statePrts.length; inx++) {
                        prefix += '^.';
                    }
                    if (prefix.length == 0) prefix += '.';
                }
                $state.go(prefix + targetState, newParms, {
                    reload: false,
                    inherit: false,
                    notify: true,
                }).then(function () {
                    if (targetState.indexOf('category') >= 0)
                        changecategoryView(targetview, targetSubview);
                    else {
                        changecategoryView(targetview, targetSubview, true);
                    }
                });
            } else {
                if (targetState.indexOf('category') < 0)
                    changecategoryView(targetview, targetSubview, true);
                else
                    changecategoryView(targetview, targetSubview);
            }
        }

        // Methods to change the displayed category

        function getSubViewId(productViewId) {
            var ret = datacontext.cust.getLastcategoryParam(productViewId);
            if (ret == undefined || ret.length == 0)
                if (productViewId == 'products') {
                    return 'dairy';
                }
            return ret;
        }

        function getPreviousOrDefaultView() {
            var ret = datacontext.cust.getLastcategory();
            return (ret) && (ret.length > 0) ? ret : config.defaultCategory;
        }

        function getViewParms(toParams) {
            var ret = {
                productViewId: (toParams.productViewId && toParams.productViewId.length > 0)
                    ? toParams.productViewId : getPreviousOrDefaultView()
            };

            ret.subViewId = (toParams.subViewId && (toParams.subViewId.length > 0))
                ? toParams.subViewId
                : getSubViewId(ret.productViewId);
            return ret;
        }

        vm.goDetails = function (productId) {
            $state.go('^.product', {
                id: productId,
                reload: false,
                inherit: false,
                notify: true
            });
            return;
        }

        vm.goCollectionDetail = function (productCollection) {
            $scope.SelectedCollection = productCollection;

            var routeBase = vm.isAuthenticated() === true ? 'shopping' : 'browsing';
            $state.go(routeBase + '.collection', {
                id: productCollection.id,
                reload: false,
                inherit: false,
                notify: true
            });
            return;
        }

        vm.changeCategoryView = function (cat2, cat3) {

            var subViewName = cat2.name;
            var categoryView = $state.params.productViewId || '';

            vm.categoryDC.selectcategory(subViewName);
            datacontext.cust.putLastcategoryParam(categoryView, subViewName);
            $state.go('^.category', { productViewId: categoryView, subViewId: subViewName }, {
                reload: false,
                inherit: false,
                notify: true
            });


            if (cat3) {
                setTimeout(function () {
                    scrollToCategory(cat2.id, cat3.id);
                }, 100);
            }
        }

        vm.ChangecategoryView = changecategoryView;

        function changecategoryView(categoryView, subViewName, doNotPerformGo) {
            vm.hideSlider = false;
            categoryView = (categoryView) && (categoryView.length > 0) ? categoryView.toLowerCase() : config.defaultCategory;

            var newParms = getViewParms({ productViewId: categoryView, subViewId: subViewName });
            vm.productViewId = newParms.productViewId;
            vm.subcategoryid = newParms.subViewId;
            datacontext.category.setProductViewName(vm.productViewId);

            if (vm.productViewId == 'products') {
                if (vm.subcategoryid && (vm.subcategoryid.length > 0)) {
                    datacontext.category.selectcategory(vm.subcategoryid);
                }
                datacontext.category.setProductViewName(vm.productViewId);
            }
            datacontext.cust.putLastcategoryParam(categoryView, subViewName);
            datacontext.cust.putLastcategory(categoryView);
            if (vm.isAuth && datacontext.cust.mycust.customerNumber < 10000000) {
                if (vm.productViewId == 'produce') {
                    $scope.screenWidth = $window.innerWidth;
                    if ($scope.screenWidth <= 768) {
                        var chatBox = document.getElementById("twilio-customer-frame");
                        if (chatBox && chatBox.style) {
                            chatBox.style.display = "none";
                        }
                    }
                }
                else {
                    var chatBox = document.getElementById("twilio-customer-frame");
                    if (chatBox && chatBox.style) {
                        chatBox.style.display = "block";
                    }
                }
            }


            if (!doNotPerformGo) {
                // this is necessary so that the category is set and ready to display when it returns to the
                // categroy view
                $state.go('^.category', newParms, {
                    reload: false,
                    inherit: false,
                    notify: true,
                    location: 'replace'
                });
            }
        }

        vm.ChangeSubCategoryView = function (elem) {
            var subViewName = elem.cat2.name;
            var categoryView = $state.params.productViewId || '';

            vm.categoryDC.selectcategory(subViewName);
            datacontext.cust.putLastcategoryParam(categoryView, subViewName);
            $('.category-submenu').height(0);

            $state.go('^.category', { productViewId: categoryView, subViewId: subViewName }, {
                reload: false,
                inherit: false,
                notify: true
            });
        }

        vm.postProductFeedback = function (productId, rating, currentRating) {
            if (rating != currentRating) {
                datacontext.cust.postProductFeedback(productId, rating).success(function () {
                    //vm.getProductFeedback(productId);
                });
            }
        }

        vm.feedback = {};

        vm.getProductFeedback = function (productId) {
            if (productId != null) {
                datacontext.cust.getProductFeedback(productId).then(function (feedback) {
                    if (feedback != null) {
                        vm.products[productId].feedback = feedback;
                    }
                });
            }
        }

        vm.hideCarousel = function (cat) {
            vm.hideSlider = true;

            vm.categoryDC.categories.forEach(function (part, index, arr) {
                arr[index].sort = arr[index].sortOrder;
            });
            cat.sort = 0;

            vm.categoryDC.categories = $filter('orderBy')(vm.categoryDC.categories, 'sort');

            vm.activeCats = vm.categoryDC.categories;
            var topHeight = document.getElementById("shopping-carousel").scrollHeight + document.getElementById("sliding-menu").scrollHeight;
            window.scroll({ top: topHeight });
        }

        function onDestroy() {
            //
            //  this should fire when we leave the new customer process
            //
            $scope.$on('$destroy', function () {
                //$scope.$onDestroy = function () {
                var staySignedIn = datacontext.cust.getStaySignedIn();
                if (!staySignedIn) {
                    authService.logOut();
                }
            });
        }
        $scope.$on('$destroy', function () {

        });

        $scope.$on('browserBack', function () {
            //$state.reload();
        });

        function setState() {
            var currentState = $state.current.name.toLowerCase();
            var statePrts = currentState.split('.');
            var targetState = currentState = statePrts.length > 1 ? statePrts[statePrts.length - 1] : '';

            var productView = ($state.params.productViewId || '').toLowerCase();
            var subViewId = ($state.params.subViewId || '').toLowerCase();


            if (productView == '') {
                if ((!datacontext.isNewCustomer) && ((datacontext.cust.mycust) && (datacontext.cust.mycust.showFeatured))) {
                    productView = 'featured';
                    subViewId = '';
                } else {
                    productView = 'products';
                }
            }
            changeState(productView, subViewId, targetState);
        }
        vm.categories = [];
        vm.productItems = [];
        vm.produceItems = [];


        activate();
        function activate() {
            if (datacontext.isNewCustomer) {
                if ((datacontext.cust.mycust == null) && ($state.$current.name.indexOf('sign-up.1') < 0)) {
                    $state.go('sign-up.1', null, { reload: true });
                    return;
                }
            }
            if (NeedsReroute()) {
                // neeedsreroute checkes if browsing or shopping is requested and makes sure it is
                // approprate to the use being logged in
                //
                // this controller should not be initialized because it is
                // issuing a state go to reload
                return;
            }

            // the f0llowing block initializes the data from the cache if it exisits

            datacontext.products.getProductPartialsForLocalInitialization();
            datacontext.category.getCatTreelocal();
            angular.copy(datacontext.products.entityData, vm.noindexProducts);
            angular.copy(datacontext.products.entityItems, vm.products);

            ; (function activate() {
                common.activateController([datacontext.primeCustomer(), datacontext.primeProducts()], controllerId)
                    .then(function () {
                        vm.isUserSuspended = function () {
                            return datacontext.cust.mycust.userSuspended;
                        }
                        vm.SugarTaxCompliant = function () {
                            if (datacontext.cust.mycust.sugarTaxInEffect) {
                                return true;
                            } else {
                                return false;
                            }
                        }
                        var hash = $window.location.href;

                        if (!originalOnDemandCustomer) {
                            originalOnDemandCustomer = datacontext.cust.mycust.onDemandCustomer;
                        }
                        vm.showScheduledDeliveryOffer = originalOnDemandCustomer;

                        if (hash.indexOf('sign-up') >= 0) {
                            common.validateCustomerNumber(datacontext.cust.mycust.customerNumber);
                        }

                        vm.hasData = true;

                        vm.noindexProducts = datacontext.products.entityData;
                        // point products to the indexed products array

                        vm.products = vm.entityProducts = datacontext.products.entityItems;
                        vm.showOrderEdits = vm.isAuth || datacontext.isNewCustomer;

                        //shows substitution feature popup 
                        //if (Object.keys(datacontext.cust.mycust.customerProductPreference).length === 0
                        //    && datacontext.cust.mycust.order.length > 0) {

                        //    var orderDetails = datacontext.cust.mycust.order[0].orderDetail;
                        //    for (let i = 0; i < orderDetails.length; i++) {
                        //        var product = vm.entityProducts[orderDetails[i].productId]
                        //        if (product == null) { continue}
                        //         if (product.substitutions.length > 0) {
                        //            vm.subNotificationModalVisible = true;
                        //            break;
                        //        }
                        //    }
                        //}

                        vm.categories = vm.categoryDC.categories;
                        datacontext.products.clearSearch();

                        datacontext.products.entityData.forEach(function (prod) { prod.noMatch = false; });
                        vm.filteredProds = datacontext.products.entityData;
                        applyFilter = common.createSearchThrottle(vm, 'noindexProducts', 'filteredProds', 'prodsFilter', 15);
                        if (vm.prodSearchTxt.length > 0) applyFilter();
                        var orderItems = vm.orderDC.getOrderItems();
                        vm.productItems = angular.copy(orderItems);

                        var orderProduceItems = vm.orderDC.getProduceItems();
                        vm.produceItems = angular.copy(orderProduceItems);
                        vm.loadDefaultProduceBox();
                        vm.loadCustomerProduceProducts();

                        common.$broadcast(config.events.spinnerToggle, { show: false });


                        vm.updateDeliveryDate();
                        vm.salesAdding = datacontext.cust.salesAdding;

                        // Recipe views are not managed by UI Router.
                        if (!vm.isRecipeView) {
                            setState();
                        }

                        vm.initializeModals();
                        //right here we need to re evaluate the catagory empty flags.  For performance reasons it makes use of a static flag
                        //otherwise it would walk the tree of each category several times for each load.  Quick work around is to
                        //eliminate use of the static empty flag  -  this is currently in use



                        vm.productClass = function (productId) {
                            if (vm.products[productId]) {
                                var cls = (vm.products[productId].nextQuantity > 0)
                                    && vm.showOrderEdits
                                    ? 'shopping-grid-item-in-cart'
                                    : '';

                                cls += (vm.products[productId].outOfStock)
                                    ? ' out-of-stock'
                                    : '';
                                cls += (vm.products[productId].productOverlayText !== null)
                                    ? ' product-overlay'
                                    : '';

                                return cls;
                            }

                        }

                        vm.showAddItem = function (productId) {
                            return vm.showOrderEdits
                                && vm.products[productId]
                                && vm.allowOrderEdits(productId)
                                && !vm.products[productId].outOfStock
                                && vm.allowAdd(productId);

                        }
                        vm.allowAdd = function (productId) {
                            if (vm.products[productId].allowAdd == "False") {
                                return false;
                            }
                            else
                                return true;
                        }
                        vm.allowRemove = function (productId) {
                            if (vm.products[productId].allowRemove == "False") {
                                return false;
                            }
                            else
                                return true;
                        }
                        vm.showRemoveItem = function (productId) {
                            return (vm.showOrderEdits && vm.allowOrderEdits(productId))
                                || (vm.products[productId] && vm.products[productId].nextQuantity > 0 && !datacontext.cust.mycust.lockUser && vm.products[productId].outOfStock && vm.allowRemove(productId));
                        }

                        $scope.$watch(function () { return vm.categoryDC.productViewCategorys }, function (oldVal, newVal) {
                            if (newVal != undefined) {
                                setActiveCats();
                            }
                        });

                        vm.customerProductPreference = datacontext.cust.mycust.customerProductPreference;
                        needsToCheckout();
                        vm.orderProductSubstitutions = datacontext.cust.mycust.orderProductSubstitutions;

                    });


            })();

            return;
        };

        $scope.$watch(function () {
            return $(".product-grid-page").height();
        }, function onHeightChange(newValue, oldValue) {
            //the product id is needed only to check if the product render is complete
            var $el = $(".product-grid-page .shopping-grid-item:first");
            if ($el != undefined && $el != null) {
                if ($el.offset() != undefined) {
                    //product loading complete event
                    vm.scrollToPrevPosition();
                }
            }
        });

        function getPreOrderProds() {
            var onlyActive = true;
            $http.get('/api/ProductPreOrder/GetPreOrderProduct/' + onlyActive).then(
                function (response) {
                    vm.categoryDC.preOrderProds = response.data;
                }, function (err, status) {
                });
            $http.get('/api/ProductPreOrder/GetCustomerPreOrderProduct/').then(
                function (response) {
                    vm.categoryDC.customerPreOrderProds = response.data;
                }, function (err, status) {
                });

        };
        getPreOrderProds();

        vm.scrollToPrevPosition = function () {
            var position = common.scrollToPosition;
            if (position != null && position) {
                $('html, body').animate({
                    scrollTop: position
                }, 0);
            }
        }

        vm.updateDeliveryDate = function () {
            vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
            vm.CutoffDate = moment(vm.DeliveryDate).add(-1, 'days').toDate();
        }

        $scope.$on('updateDeliveryDate', function (event, msg) {
            vm.updateDeliveryDate();
        });

        vm.initializeModals = function () {
            vm.showOrderErrorModal = false;
            vm.showHouseModal = datacontext.cust.getShowOneTimePopupHouse();
            vm.showApartmentModal = datacontext.cust.getShowOneTimePopupApartment();
            vm.showHouseApartmentModal = vm.showHouseModal || vm.showApartmentModal;

            vm.showOneTimeModal = datacontext.cust.getShowOneTimePopup();

            if (authService.authentication.isAuth == false) {
                vm.showStandingOrderModal = true;
            }
            else {
                vm.showStandingOrderModal = false;
            }
            if (vm.isAuth) {
                vm.showAccountMessage = datacontext.cust.mycust.adminLockout;

                // If the customer is experiencing a delivery day lockout, then
                // that takes priority over the suspend delivery message.
                if (datacontext.cust.mycust.lockUser && !vm.showAccountMessage) {
                    vm.showDeliveryLockoutModal = true;
                }
                else if (datacontext.cust.mycust.userSuspended && !vm.showAccountMessage) {
                    vm.skipDeliveryModal = true;
                }
            }
            var showOneTime = datacontext.cust.getShowOneTimePopup();
            if ((authService.authentication.convertedUser) || (showOneTime)) {
                vm.showOneTimeModal = true;
            }
        }

        vm.getDeliveryDate = function () {
            if (datacontext.cust.mycust != null && datacontext.cust.mycust != undefined)
                return datacontext.cust.mycust.deliveryDayFull;
        }

        function checkMyCust() {
            MyCtrl($scope);
            function MyCtrl($scope) {
                setTimeout(function () {
                    $scope.$apply(function () {
                        if (datacontext.cust.mycust) {
                            vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
                            vm.CutoffDate = moment(vm.DeliveryDate).add(-1, 'days').toDate();
                        } else {
                            MyCtrl($scope);
                        }
                    });
                }, 200);
            }
        }

        vm.nextCategory = '';

        function gotoProductDetail(product) {
            if (product) {
                $state.go("^.detail", { id: product });
            }
        }

        function showCartMessage() {
            var show = false;

            if (!vm.isAuth && vm.showOrderEdits) {
                vm.cartMessage = 'Continue your sign-up process here';
                show = true;
            }
            else if (vm.isAuth) {
                vm.cartMessage = 'To see items in your cart click here';
                show = true;
            }

            return show;
        }

        vm.showRegionalPrices = function (product) {
            return false
        }

        // This function supports cook county sugar tax compliance
        vm.SugarTaxCompliant = function () { return false }

        vm.RefreshProductsRegion = function (newRegion) {
            datacontext.products.getProductPartialsForPriceCode(newRegion)
                .then(function () {
                    if (newRegion == datacontext.cust.mycust.price_schedule) {
                        datacontext.cust.mycust.regionSelected = true;
                        vm.showPricingModal = false;
                    }
                    datacontext.cust.mycust.price_schedule = newRegion;
                    datacontext.cust.mycust.regionSelected = true;
                    vm.showPricingModal = false;
                });
        }

        // Show bottle discounts if count > 0
        vm.showBottleDiscountLine = function (item) {
            return item && item.bottleDiscount > 0;
        }

        vm.showDiscountLine = function () {
            //var standing = vm.GetStandingDeliveryTotals();
            var next = vm.GetNextDeliveryTotals();
            return (next != null && next.discount != 0);
        }

        vm.showDeliveryChargeLine = function () {
            var next = vm.GetNextDeliveryTotals();
            return (next != null && next.deliveryCharge != 0);
        }

        vm.showMinProduceChargeLine = function () {
            var next = vm.GetNextDeliveryTotals();
            return (next != null && next.minimumProduceFee != 0);
        }

        vm.showDeliveryChargeLine = function () {
            var next = vm.GetNextDeliveryTotals();
            return (next != null && next.deliveryCharge != 0);
        }

        vm.showDeliveryCreditLine = function () {
            var next = vm.GetNextDeliveryTotals();
            return (next != null && next.deliveryChargeCredit != 0);
        }

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }

        vm.cartProductIds = function () {
            var ids = [];
            //filtering out produce items from regular cart view
            for (var i = 0; i < vm.productItems.length; i++) {
                if (!vm.produceItems.find(x => x.id === vm.productItems[i].id))
                {
                    ids.push(vm.productItems[i].id);

                }
            }
            return ids;
        }

        if (datacontext != null) {
            if (datacontext.cust.mycust != null) {
                if (datacontext.cust.mycust.userSuspended && datacontext.cust.mycust.lockUser == false) {
                    datacontext.cust.mycust.cartItemDisabledReason = "Disabled due to suspended delivery.";
                }
            }
        }

        var previousState = { from: undefined, fromParams: undefined };

        $rootScope.$on('$stateChangeSuccess', function (ev, to, toParams, from, fromParams) {
            previousState.from = from;
            previousState.fromParams = fromParams
        });

        vm.isIncompleteStartup = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.incompleteCustomerSignup;
        }

        vm.shoppingCartContinueShopping = function () {
            var isIncompleteStartup = vm.isIncompleteStartup();
            var categoryView = datacontext.cust.getLastcategory();
            var subViewName = datacontext.cust.getLastcategoryParam(categoryView);

            if (!isIncompleteStartup && categoryView) {
                $state.go('shopping.category', { productViewId: categoryView, subViewId: subViewName });
                $state.go(previousState.from.name, previousState.fromParams);
            } else if (isIncompleteStartup) {
                $state.go('sign-up.2.category', { productViewId: categoryView, subViewId: subViewName });
            } else {
                $state.go("shopping.categorynoparm")
            }
        }

        //------------------------------------------------------------------------
        // Product Collections Logic For New Start Customer Modal Pop-Up Flow Only
        //------------------------------------------------------------------------
        vm.productCollectionsEnabled = false;
        vm.productCollections = [];
        vm.previousBranch = 0;
        vm.selectedProductCollection = null;
        vm.collectionSelectionsValid = false;
        vm.showOneTimeUseDisclaimer = false;
        vm.showCartEditDisclaimer = false;

        $scope.$watch(function () {
            if (datacontext.cust.mycust) {
                return datacontext.cust.mycust.branch
            }
        }, function (newValue, oldValue, scope) {
            if (newValue && newValue > 0) {
                vm.getActiveNewStartCollectionsForBranch(newValue);
            }
        }, true);

        vm.getActiveNewStartCollectionsForBranch = function (branchNumber) {
            if (branchNumber && branchNumber > 0 && vm.previousBranch != branchNumber) {

                var enableUrl = "api/ProductCollection/ProductCollectionsEnabled";
                $http.get(enableUrl)
                    .success(function (data) {
                        vm.productCollectionsEnabled = data;

                        if (vm.productCollectionsEnabled === true) {
                            vm.previousBranch = branchNumber;
                            var url = "api/ProductCollection/GetActiveProductCollections/?branchNumber=" + branchNumber + "&newStartsOnly=true";

                            $http.get(url)
                                .success(function (data) {
                                    //If we need to add a carousel to see more then 3 this logic will need to be changed
                                    var allActiveResults = data;
                                    if (allActiveResults && allActiveResults.length > 3) {
                                        vm.productCollections = allActiveResults.slice(0, 3);
                                    } else {
                                        vm.productCollections = allActiveResults;
                                    }
                                    vm.showOneTimeUseDisclaimer = vm.productCollections.some(pc => pc.oneTimeUse == true);
                                    vm.showCartEditDisclaimer = vm.productCollections.some(pc => pc.discountValue && pc.discountValue > 0);
                                })
                                .error(function (data, status, headers, config) {
                                    vm.message = data;
                                });
                        }
                    });

            }
        }

        vm.ShowProductCollections = function () {
            this.ProcessOneTimeModal();
            vm.showProductCollectionsItemsModal = false;

            if (vm.productCollections && vm.productCollections.length > 0) {
                vm.showProductCollectionsModal = true;
            }
        }

        vm.CollectionsGoBack = function () {
            vm.selectedProductCollection = null;
            vm.showProductCollectionsItemsModal = false;
            vm.showProductCollectionsModal = true;
            vm.collectionSelectionsValid = false;
        }

        vm.ShowProductCollectionItems = function (productCollection) {
            if (productCollection) {
                vm.selectedProductCollection = productCollection;
                vm.showProductCollectionsModal = false;
                vm.showProductCollectionsItemsModal = true;

                //Set Quantity Satisfied Flag for UX elements and pre-select if group contains only one Product
                angular.forEach(productCollection.productCollectionGroup, function (group) {
                    //Track User selected products seperately to save looping later
                    group.selectedProducts = [];
                    if (group.productCollectionGroupItems.length === 1) {
                        group.productCollectionGroupItems[0].selected = true;
                        group.productCollectionGroupItems[0].quantity = 1;
                        group.minQtySatisfied = true;
                        group.selectedProducts.push(group.productCollectionGroupItems[0].productId);
                    } else {
                        group.minQtySatisfied = false;
                    }
                });

                //Run validation now in case every group in this collection has only one product option
                validateSelections();
            }
        }

        vm.ToggleSelectedCollectionItem = function (collectionGroupItem, collectionGroup) {
            if (collectionGroupItem && collectionGroupItem.selected) {
                //Do not allow users to un-select items if there is only one product option in the group
                if (collectionGroup.productCollectionGroupItems.length > 1) {
                    collectionGroupItem.selected = false;
                    collectionGroupItem.quantity = 0;
                    //Remove from the array of user-selected products
                    collectionGroup.selectedProducts = collectionGroup.selectedProducts.filter(e => e !== collectionGroupItem.productId);
                    validateSelections();
                }
            } else {
                if (!collectionGroup.maxAllowed || collectionGroup.selectedProducts.length < collectionGroup.maxAllowed) {
                    collectionGroupItem.selected = true;
                    collectionGroupItem.quantity = 1;
                    collectionGroup.selectedProducts.push(collectionGroupItem.productId);
                    validateSelections();
                }
            }
        }

        function validateSelections() {
            if (!vm.selectedProductCollection) { return; }

            var satisfiedGroups = 0;
            angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                group.minQtySatisfied = group.selectedProducts.length >= group.minRequired;
                if (group.minQtySatisfied) {
                    satisfiedGroups++;
                    group.userMessage = "Selection Complete";
                } else {
                    var delta = group.minRequired - group.selectedProducts.length;
                    group.userMessage = "Please select " + delta + " more option" + (delta === 1 ? "" : "s");
                }
            });

            //The user selections are valid when the min quantities of all groups have been satisfied
            vm.collectionSelectionsValid = satisfiedGroups === vm.selectedProductCollection.productCollectionGroup.length;
        }

        vm.ValidCollectionAddToCart = function () {
            //Used later for collection usage record that ties the customer ID and the collection ID together, which enables discounts if valid
            datacontext.cust.mycust.newStartCollectionId = vm.selectedProductCollection.id;

            //Need to commit the customer update right now so that cart item updates will account for the discount
            //This also saves the assignment of specific products to each CollectionGroupItem, required for discount math when multiple collections in play
            vm.selectedProductCollection.custId = datacontext.cust.mycust.id;
            vm.selectedProductCollection.newCustomerSignUp = true; //If this logic is re-used later fore recipes, this will have to be refactored
            datacontext.cust.updateSelectedProductCollection(datacontext.cust.mycust.id, vm.selectedProductCollection);

            //Make sure user selections are all added to the cart
            var newCartItems = [];
            angular.forEach(vm.selectedProductCollection.productCollectionGroup, function (group) {
                angular.forEach(group.selectedProducts, function (selectedProduct) {
                    var p = vm.products[selectedProduct];
                    if (p) {
                        p.standingQuantity = 1;
                        p.nextQuantity = 1;
                        p.changed = true;
                        newCartItems.push(p);
                    }
                });
            });

            vm.totalsRefreshing = true;
            try {
                datacontext.order.PostOrderDetailUpdate(newCartItems).then(function (result) {
                    vm.refreshGridItems();
                    vm.refreshOrderItems();
                    vm.totalsRefreshing = false;

                    //Hide the modal form
                    vm.showProductCollectionsItemsModal = false;
                    //Show the full cart so the user may continue the sign-up process
                    vm.checkoutButtonClicked();
                },
                    function () {
                        vm.totalsRefreshing = false;
                        //TODO - warning message?
                    });
            }
            catch (err) {
                vm.totalsRefreshing = false;
                //TODO - warning message?
            }

        }

        vm.AddAllRecipeProductsToCart = function (products) {
            for (let i = 0; i < products.length; i++) {
                var product = vm.products[products[i].productId];
                var quantity = products[i].productQty
                if (vm.allowOrderEdits(products[i].productId)) {
                    changeNextQuantity(product, quantity)
                }
            }
        }

        vm.IsRecipeAddToCartDisabled = function (products) {
            if (products && products.length > 0) {
                for (let i = 0; i < products.length; i++) {
                    if (products[i].productId != null && vm.allowOrderEdits(products[i].productId)) {
                        return false;
                    }
                }
            }
            return true;
        }
        //---------PRODUCE FUNCTIONS---------//
        vm.produceViewAvailable = false;
        vm.produceCategory = null;
        vm.produceEdit = false;
        vm.produceEditMessage = null;
        vm.hasProduceProds = false;
        vm.defaultVolume = '3 Units';


        //checks to see if the delivery date is 2 days out
        vm.setProduceAllow = function () {
            if (vm.isAuth) {
                if (datacontext.cust.mycust) {
                    //sets the TZ to central bc all branch cutoffs are in central
                    moment.tz.setDefault("America/Chicago");
                    // EPOCH
                    var cutoffTime = Date.parse(moment(datacontext.cust.mycust.branchCutoff).format());
                    //grabs the current time in the chicago timezone
                    var today = Date.parse(moment().format());
                    cutoffTime = cutoffTime - (vm.currentProduceBox.cutoffMinutes * 60 * 1000);
                    var dayOfWeek = datacontext.cust.mycust.deliveryDay;
                    if (dayOfWeek === 'MON') {
                        //need to move back cutoff by 2 days to thursday 
                        cutoffTime = cutoffTime - (2880 * 60 * 1000);
                    }

                    if (today <= cutoffTime) {
                        if (today >= cutoffTime - 900000) {
                            vm.produceEditMessage = "15 minute threshold warning. Produce must be submitted before 9:00 PM CST today.";
                        }
                        vm.produceEditMessage = "Produce orders must be placed by " + new Date(cutoffTime).toDateString() + " " +
                            new Date(cutoffTime).toLocaleTimeString().slice(0,4) + " PM CST";
                        vm.produceEdit = true;
                    }
                    else {
                        vm.produceEdit = false;
                        vm.produceEditMessage = "Ordering Disabled. Produce must be ordered by 9:00 PM two business days before your next delivery";
                    }

                }
            }
        };
        vm.showEditBoxes = false;
        vm.toggleEditBoxes = function () {
            vm.showEditBoxes = !vm.showEditBoxes;
        };
        vm.editingProduce = false;
        //copies all products from the customers cart, saves a dupe of those products for removal, and adds products to the edit window
        vm.editActiveBox = function () {
            vm.showEditBoxes = false;
            vm.toggleCurrentBox(true);
            vm.currentProduceBox.oldProduceBoxItem = angular.copy(vm.customerProduceContainer.produceProducts);
            vm.currentProduceBox.produceBoxItem = [];
            //utilizing the add function created is the easiest way to copy
            for (var i = 0; i < vm.customerProduceContainer.expandedProdList.length; i++) {
                var curItem = vm.customerProduceContainer.expandedProdList[i];
                vm.addToCurrentBox(curItem.productId);              
            }
            vm.editingProduce = true;
            vm.canModifyCurrentBox();

        };
        //the cart produce container is untouched until submit or delete is hit, so just nulling the edit box cancels edits
        vm.cancelProduceBoxEdit = function () {
            vm.showEditBoxes = true;
            vm.toggleCurrentBox();
            vm.loadDefaultProduceBox();
            vm.editingProduce = false;
            vm.canModifyCurrentBox();
        };
        //deleting the cart products by clearing the edit box and submitting an "empty" box for edit (which automatically deletes all old prods)
        vm.deleteProduceBox = function () {
            vm.currentProduceBox.produceBoxItem = [];
            vm.submitProductBox(true);

        };
        vm.canModifyCurrentBox = function () {
            vm.setProduceAllow();
            var boxItemQuant = 0;

            for (var i = 0; i < vm.currentProduceBox.produceBoxItem.length; i++) {
                boxItemQuant += vm.currentProduceBox.produceBoxItem[i].quantity;
            }
            vm.currentProduceBox.maxCapacity = Math.ceil(boxItemQuant / vm.currentProduceBox.capacity) * vm.currentProduceBox.capacity;
            if (boxItemQuant % vm.currentProduceBox.capacity !== 0) {
                vm.currentProduceBox.canSubmit = false;
            }
            else {
                vm.currentProduceBox.canSubmit = true;
                vm.toggleCurrentBox(true);
            }

        };
        vm.addToCurrentBox = function (product) {
            var newItem = { productNumber: product, quantity: 1 };
            vm.currentProduceBox.produceBoxItem.push(newItem);
            vm.canModifyCurrentBox();
        };
        vm.removeProduceFromBox = function (index) {
            vm.currentProduceBox.produceBoxItem.splice(index, 1);
            vm.canModifyCurrentBox();
        };
        vm.toggleButtonName = "Expand";

        vm.toggleCurrentBox = function (keepOpen) {
            var imagePanel = document.getElementById('image-panel-produce');
            var boxHolder = document.getElementById('produce-box-fixed');
            if (keepOpen) {
                imagePanel.style.display = 'flex';
                boxHolder.style.height = 'max-content';
                vm.toggleButtonName = "Hide";
            }
            else {

                if (imagePanel.style.display === 'none') {
                    imagePanel.style.display = 'flex';
                    boxHolder.style.height = 'max-content';
                    vm.toggleButtonName = "Hide";
                } else {
                    imagePanel.style.display = 'none';
                    boxHolder.style.height = 'auto';
                    vm.toggleButtonName = "Expand";


                }
            }
        };
        //using the repository.order for all products with flag produceProd separates the produce items.
        //All order item quantites are tracked in that repo
        vm.loadCustomerProduceProducts = function () {
            vm.customerProduceContainer.produceProducts = datacontext.order.getProduceItems();
            vm.customerProduceContainer.totalCost = 0;
            vm.customerProduceContainer.totalProds = 0;
            //expanded prod list is just there for UI experiences. When editing or creating, each item is treated as quantity 1 
            //but the quants are adjusted before pushing to the cart so all products are grouped by product number 
            vm.customerProduceContainer.expandedProdList = [];

            var prods = vm.customerProduceContainer.produceProducts;

            for (var i = 0; i < prods.length; i++) {
                var curProd = prods[i];
                if (curProd) {
                    vm.customerProduceContainer.totalProds += curProd.nextQuantity;
                    if (curProd.salePrice) {
                        vm.customerProduceContainer.totalCost += curProd.salePrice * curProd.nextQuantity;
                        curProd.itemCost = curProd.salePrice;
                    }
                    else {
                        vm.customerProduceContainer.totalCost += curProd.price * curProd.nextQuantity;
                        curProd.itemCost = curProd.price;

                    }
                    for (var j = 0; j < curProd.nextQuantity; j++) {
                        var expandedProd = angular.copy(curProd);
                        expandedProd.nextQuantity = 1;
                        vm.customerProduceContainer.expandedProdList.push(expandedProd);
                    }
                }
            }
        };
        //default box sets the capacity for everything 
        vm.loadDefaultProduceBox = function () {
            var url = 'api/Produce/GetDefaultProduceBox';
            $http.get(url).then(
                function (response) {
                    vm.currentProduceBox = response.data;
                    vm.currentProduceBox.canSubmit = false;
                    vm.incompleteBoxMessage = 'Produce products must be in multiples of ' + vm.currentProduceBox.capacity;

                    vm.currentProduceBox.maxCapacity = vm.currentProduceBox.capacity;
                    vm.setProduceAllow();

                }, function (err, status) {
                });

        };
        //submit to cart using exisitng cart edit quantity. When editing a box it will remove all old products from cart and then add fresh even if 
        //products are unchanged. If deleting, currentProduceBox.productBoxItem.length = 0 so there will be nothing added, only removal (cust still needs to checkout to save)
        vm.submitProductBox = function (editing) {
            //sets the TZ to central bc all branch cutoffs are in central
            moment.tz.setDefault("America/Chicago");
            // EPOCH
            var cutoffTime = Date.parse(moment(datacontext.cust.mycust.branchCutoff).format());
            //grabs the current time in the chicago timezone
            var today = Date.parse(moment().format());
            cutoffTime = cutoffTime - (vm.currentProduceBox.cutoffMinutes * 60 * 1000);
            var dayOfWeek = datacontext.cust.mycust.deliveryDay;
            if (dayOfWeek === 'MON') {
                //need to move back cutoff by 2 days to thursday 
                cutoffTime = cutoffTime - (2880 * 60 * 1000);
            }

            if (today <= cutoffTime) {
                //remove all old products from cart 
                if (editing) {
                    if (vm.currentProduceBox.oldProduceBoxItem) {
                        for (var i = 0; i < vm.currentProduceBox.oldProduceBoxItem.length; i++) {
                            var product = vm.products[vm.currentProduceBox.oldProduceBoxItem[i].id];
                            var quant = (vm.products[vm.currentProduceBox.oldProduceBoxItem[i].id].nextQuantity * -1);
                            changeNextQuantity(product, quant);
                        }
                    }
                }

                var buildOrderItemList = [];

                for (var i = 0; i < vm.currentProduceBox.produceBoxItem.length; i++) {
                    var boxItem = vm.currentProduceBox.produceBoxItem[i];
                    var buildingItem = {
                        ProductNumber: boxItem.productNumber,
                        Quantity: 1
                    };
                    if (buildOrderItemList.length > 0) {
                        var alreadyThere = buildOrderItemList.find(x => x.ProductNumber === buildingItem.ProductNumber);
                        if (alreadyThere) {
                            alreadyThere.Quantity++;
                        }
                        else {
                            buildOrderItemList.push(buildingItem);
                        }
                    }
                    else {
                        buildOrderItemList.push(buildingItem);
                    }
                }
                for (var i = 0; i < buildOrderItemList.length; i++) {
                    var product = vm.products[buildOrderItemList[i].ProductNumber];
                    var quant = buildOrderItemList[i].Quantity;
                    changeNextQuantity(product, quant);
                }
                $state.go('shopping.cart');
            }
            else {
                vm.showProduceOrderFail = true;
            }
        };


    }
})();
;
(function () {
    "use strict";
    var controllerId = "productCatalogDairyStoreController";

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "$filter"
            , "config"
            , "common"
            , "datacontext"
            , "authService"
            , productCatalogDairyStoreController]);

    function productCatalogDairyStoreController(
        $stateParams
        , $scope
        , $state
        , $timeout
        , $window
        , $filter
        , config
        , common
        , datacontext
        , authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        var keyCodes = config.keyCodes;
        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;

        vm.datacontext = datacontext;
        vm.selectedParentCategory = {};

        $scope.$state = $state;

        vm.appVersion = appVersion;

        $scope.$root.SwitchToListView = function (viewType) {
            datacontext.cust.mycust.listView = viewType;
        }

        $scope.$root.isListView = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.listView;
        }

        vm.changeCategoryView = function (category, subCategory) {

            if (category.id !== vm.selectedParentCategory.id) {
                vm.selectedParentCategory = category;
                datacontext.category.selectedParentCategory = category; 
                vm.changeState();
            }

            if (subCategory) {
                setTimeout(function () {
                    scrollToCategory(category.id, subCategory.id);
                }, 100);
            }
        }


        //vm.changeSubCategoryView = function (category) {
        //    vm.selectedSubCategory = category;
        //    vm.changeState();
        //}

        vm.changeState = function () {
            $state.go('dairy-stores.browsing', {
                category: vm.selectedParentCategory.navigationUrl,
                //subCategory: vm.selectedSubCategory.navigationUrl
            }, {
                reload: false,
                // notify: false
            });
            $scope.getSeoMetadata(vm.selectedParentCategory.navigationUrl, 7)

        }

        //vm.scrollToCategory = function (subCategory, offset) {
        //    offset = offset ? offset : 0;
        //    var $el = $('#subcategory_' + subCategory.id);
        //    var top = $el.offset().top - offset;
        //    $('html,body').animate({ scrollTop: top }, 1800);
        //}

        activate();
        function activate() {
            datacontext.products.getProductPartialsForLocalInitialization();

            if ($state.current.name === "dairy-stores.category")
            {
                var $container = $('.products-nav-container');
                var menuHeight = $('#sticky-menu').height();
                var navOffsetTop = $container.offset().top;
                var productNavHeight = $container.height();


                $(window).scroll(function () {
                    var scrollTop = $(window).scrollTop();

                    if (scrollTop > (navOffsetTop - menuHeight)) {
                        if (!$container.hasClass('fixed')) {
                            $('.products-nav-container').addClass('fixed');
                            $('.products-nav-container').css("top", menuHeight);
                            $('.subcat').removeClass('hide');
                            $('.subcat').height(productNavHeight);
                        }
                    }
                    else {
                        $('.products-nav-container.fixed').removeClass('fixed');
                        $('.subcat:not(.hide)').addClass('hide');
                    }
                });
            }

            vm.params = $state.params;

            datacontext.productcategory.getDairyStoreCategoryTree().then(function (result) {
                vm.categoryTree = result.data;
                datacontext.dairyStoreProducts = result.data.reduce(function(products, cat1) {
                    cat1.categories.reduce(function(products, cat2) {
                        cat2.products.reduce(function (products, product) {
                            products[product.productNumber] = product;
                            return products;
                        }, products)
                        return products;
                    }, products)
                    return products;
                }, {});

                datacontext.products.addDairyStoreProductDetails(datacontext.dairyStoreProducts)
                
                if ($state.current.name === "dairy-stores.product") {
                    vm.selectedParentCategory = vm.categoryTree[0];
                    datacontext.category.selectedParentCategory = vm.categoryTree[0]
                    return;
                }

                if (!vm.params.category && !vm.params.subCategory) {
                    
                    vm.changeCategoryView(vm.categoryTree[0]);
                }
                else {
                    vm.parentCategory = vm.categoryTree.filter(function (el) {
                        return el.navigationUrl === vm.params.category;
                    })[0];

                    vm.subCategory = vm.parentCategory.categories.filter(function (el) {
                        return el.navigationUrl === vm.params.subCategory;
                    })[0];

                    vm.changeCategoryView(vm.parentCategory, vm.subCategory);
                }

            });

        };

    }
})();;
(function () {
    "use strict";
    var controllerId = "productCatalogRetailController";

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , "$state"
            , "$timeout"
            , "$window"
            , "$filter"
            , "config"
            , "common"
            , "datacontext"
            , "authService"
            , productCatalogRetailController]);

    function productCatalogRetailController(
        $stateParams
        , $scope
        , $state
        , $timeout
        , $window
        , $filter
        , config
        , common
        , datacontext
        , authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        var keyCodes = config.keyCodes;
        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;

        vm.datacontext = datacontext;
        vm.selectedParentCategory = {};

        $scope.$state = $state;

        vm.appVersion = appVersion;

        $scope.$root.SwitchToListView = function (viewType) {
            datacontext.cust.mycust.listView = viewType;
        }

        $scope.$root.isListView = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.listView;
        }

        vm.changeCategoryView = function (category, subCategory) {

            if (category.id !== vm.selectedParentCategory.id) {
                vm.selectedParentCategory = category;
                datacontext.category.selectedParentCategory = category; 
                vm.changeState();
            }

            if (subCategory) {
                setTimeout(function () {
                    scrollToCategory(category.id, subCategory.id);
                }, 100);
            }
        }


        //vm.changeSubCategoryView = function (category) {
        //    vm.selectedSubCategory = category;
        //    vm.changeState();
        //}

        vm.changeState = function () {
            $state.go('retail.browsing', {
                category: vm.selectedParentCategory.navigationUrl,
                //subCategory: vm.selectedSubCategory.navigationUrl
            }, {
                reload: false,
                // notify: false
            });
            $scope.getSeoMetadata(vm.selectedParentCategory.navigationUrl, 7)

        }

        //vm.scrollToCategory = function (subCategory, offset) {
        //    offset = offset ? offset : 0;
        //    var $el = $('#subcategory_' + subCategory.id);
        //    var top = $el.offset().top - offset;
        //    $('html,body').animate({ scrollTop: top }, 1800);
        //}

        activate();
        function activate() {
            datacontext.products.getProductPartialsForLocalInitialization();

            if ($state.current.name === "retail.category")
            {
                var $container = $('.products-nav-container');
                var menuHeight = $('#sticky-menu').height();
                var navOffsetTop = $container.offset().top;
                var productNavHeight = $container.height();


                $(window).scroll(function () {
                    var scrollTop = $(window).scrollTop();

                    if (scrollTop > (navOffsetTop - menuHeight)) {
                        if (!$container.hasClass('fixed')) {
                            $('.products-nav-container').addClass('fixed');
                            $('.products-nav-container').css("top", menuHeight);
                            $('.subcat').removeClass('hide');
                            $('.subcat').height(productNavHeight);
                        }
                    }
                    else {
                        $('.products-nav-container.fixed').removeClass('fixed');
                        $('.subcat:not(.hide)').addClass('hide');
                    }
                });
            }

            vm.params = $state.params;

            datacontext.productcategory.getRetailCategoryTree().then(function (result) {
                vm.categoryTree = result.data;
                
                datacontext.retailProducts = result.data.reduce(function(products, cat1) {
                    cat1.categories.reduce(function(products, cat2) {
                        cat2.products.reduce(function (products, product) {
                            products[product.productNumber] = product;
                            return products;
                        }, products)
                        return products;
                    }, products)
                    return products;
                }, {});

                datacontext.products.addRetailProductDetails(datacontext.retailProducts)
                
                if ($state.current.name === "retail.product") {
                    vm.selectedParentCategory = vm.categoryTree[0];
                    datacontext.category.selectedParentCategory = vm.categoryTree[0]
                    return;
                }

                if (!vm.params.category && !vm.params.subCategory) {
                    vm.changeCategoryView(vm.categoryTree[0]);
                }
                else {
                    vm.parentCategory = vm.categoryTree.filter(function (el) {
                        return el.navigationUrl === vm.params.category;
                    })[0];

                    vm.subCategory = vm.parentCategory.categories.filter(function (el) {
                        return el.navigationUrl === vm.params.subCategory;
                    })[0];

                    vm.changeCategoryView(vm.parentCategory, vm.subCategory);
                }

            });

        };

    }
})();;
(function () {
    var controllerId = "productCollectionsController";

    angular.module("app-hd").controller(controllerId, ["$http", "$location", productCollectionsController]);

    function productCollectionsController($http, $location) {
        var vm = this;

        vm.collections = [];

        vm.getCollections = function () {
        };
    }

})();
;
(function () {
    var controllerId = 'productDetailController';

    angular.module('app-hd').controller(controllerId,
    ['$state', '$scope', '$http','$sce', '$stateParams','$anchorScroll', '$location', 'config', 'common', 'datacontext', 'ngAuthSettings', "authService",
        "unauthenticatedBranch", productDetail]);

    function productDetail($state, $scope, $http, $sce, $stateParams, $anchorScroll, $location, config, common, datacontext, ngAuthSettings, authService, unauthenticatedBranch) {
        var vm = this;
        vm.serverUrl = ngAuthSettings.apiServiceBaseUri;
        vm.picUrlBase = ngAuthSettings.baseUri;
        vm.ngAuthSettings = ngAuthSettings;
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;

        vm.IceCreamBagitem = $scope.$parent.vm.IceCreamBagitem;
        vm.RejectBagOption = $scope.$parent.vm.RejectBagOption;
        vm.showIceCreamBagModal = false;

        vm.allowAdd = $scope.$parent.vm.allowAdd;
        vm.allowRemove = $scope.$parent.vm.allowRemove;


        vm.showOrderEdits = $scope.$parent.vm.showOrderEdits;
        vm.allowOrderEdits = $scope.$parent.vm.allowOrderEdits;

        //vm.IceCreamBagOption = $scope.$parent.vm.IceCreamBagOption;
        vm.ProcessBagOption = $scope.$parent.vm.ProcessBagOption;

        vm.$state = $state;
        vm.getProductDetails = _getprodDetails;
        vm.activate = activate;

        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;
        vm.showProductReviewError = false;

        vm.productId = $stateParams.id;
        vm.products = datacontext.products.entityItems;
        vm.categoryDC = datacontext.category;
        vm.productsDC = datacontext.products;
        vm.product = datacontext.products.entityItems[vm.productId];
        vm.baseUrl = config.baseUrl;
        vm.isAuth = authService.authentication.isAuth;
        vm.productReviews = [];
        vm.productRecipes = [];
        vm.prodReviewsCurPage = 1;
        vm.allowShowMore = true;
        vm.canSubmitReview = false;
        vm.productImages = [];
        vm.showMultipleImages = false;
        vm.chosenImage =
        {
            id: 1000000000,
            productNumber: null,
            imageFileName: "no-image-default",
            imageSequence: 25

        };
        vm.showTabs = _showTabs;
        function _showTabs() {
            //992 is where the screen goes from 2 cols to stacked 
            return (window.innerWidth < 992)
        };
        window.onresize = vm.showTabs;

        vm.showRecipes = false;                              
        vm.showReviews = false;       
        vm.showDetails = true;

        vm.scrollToRecipes = function () {
            var old = $location.hash();
            $location.hash('product-recipe-box');
            $anchorScroll();
            //resets the url so it doesnt contain a hash extension
            $location.hash(old);

        }
        vm.toggleTab = function (tab) {
            if (tab === "recipes") {
                vm.showRecipes = true;
                vm.showReviews = false;
                vm.showDetails = false;
            }
            else if (tab === "details") {
                vm.showRecipes = false;
                vm.showReviews = false;
                vm.showDetails = true;
            }
            else if (tab === "reviews") {
                vm.showRecipes = false;
                vm.showReviews = true;
                vm.showDetails = false;
            }
            else {
                vm.showRecipes = false;
                vm.showReviews = false;
                vm.showDetails = true;
            }
            
        }

        vm.showMultipleImages = function () {
            //this will be true on first load. Therefore it will not re-factor the productimage list when an image is changed
            if (vm.chosenImage.id === 1000000000) {
                if (vm.product && vm.product.productImages && vm.product.productImages.length > 0) {
                    //set the chosen image equal to the the first sequence image
                    vm.chosenImage = vm.product.productImages[0];
                    //add all but the first to the sequence 
                    vm.allProductImages = vm.product.productImages.slice(0, vm.product.productImages.length);
                    vm.productImages = vm.product.productImages.slice(1, 6);
                    return true;
                }
                else {
                    //no extra images
                    return false;
                }
            }
            else {
                return true;
            }

        }

        vm.changeImage = function (newImage) {
            //dont need all this code bc the main list is fully filled and never changes
            vm.chosenImage = newImage;

        }
        vm.changeImageArrowRight = function (curImage) {
            if (curImage.imageSequence != vm.allProductImages.length) {
                if (vm.allProductImages.some(e => e.imageSequence === curImage.imageSequence + 1)) {
                    vm.chosenImage = vm.allProductImages.find(e => e.imageSequence === curImage.imageSequence + 1);
                }
            }
            else {
                vm.chosenImage = vm.allProductImages[0];
            }
        }
        vm.changeImageArrowLeft = function (curImage) {

            if (curImage.imageSequence != 1) {
                if (vm.allProductImages.some(e => e.imageSequence === curImage.imageSequence - 1)) {
                    vm.chosenImage = vm.allProductImages.find(e => e.imageSequence === curImage.imageSequence - 1);
                }
            }
            else {
                if (vm.allProductImages.some(e => e.imageSequence === vm.allProductImages.length)) {
                    vm.chosenImage = vm.allProductImages.find(e => e.imageSequence === vm.allProductImages.length);
                }

            }
        }
        vm.scrollImage = function (direction) {
            //will always be 7+ if can scroll == true 
            var length = vm.allProductImages.length;
            switch (direction) {
                case "leftArrow":
                    var frontVal = vm.productImages[0].imageSequence;
                    if (frontVal != 1) {
                        //add the image before into view and pop the last image
                        if (vm.allProductImages.some(e => e.imageSequence === frontVal - 1)) {
                            vm.productImages.unshift(vm.allProductImages.find(e => e.imageSequence === frontVal - 1));
                            vm.productImages.pop();
                        }
                    }
                    else {
                        //add the last image in the list into view and pop the last image 
                        if (vm.allProductImages.some(e => e.imageSequence === vm.allProductImages.length)) {
                            vm.productImages.unshift(vm.allProductImages.find(e => e.imageSequence === vm.allProductImages.length));
                            vm.productImages.pop();
                        }
                    }
                    break;
                case "rightArrow":
                    var endImgSeq = vm.productImages[vm.productImages.length - 1].imageSequence;
                    if (endImgSeq < length) {
                        //pop last image, add frontval-1 in back
                        if (vm.allProductImages.some(e => e.imageSequence === endImgSeq + 1)) {
                            vm.productImages.push(vm.allProductImages.find(e => e.imageSequence === endImgSeq + 1));
                            vm.productImages.shift();
                        }

                    }
                    else {
                        //remove first image in list, pop the first image sequence to list
                        if (vm.allProductImages.some(e => e.imageSequence === 1)) {
                            vm.productImages.push(vm.allProductImages.find(e => e.imageSequence === 1));
                            vm.productImages.shift();
                        }
                    }
                    break;
                default:

            }
        }
        vm.canScrollImages = function () {
            //if there are 7 images it is scrollable (1 main, 6 extras)
            if (vm.product.productImages.length > 5) {
                return true;
            }
            else
                return false;
        }
        vm.openMore = function (prodNo) {
            var curPage = vm.prodReviewsCurPage + 1;
            var url = "api/ProductReviews/GetApprovedProductReviews/" + prodNo + "/" + curPage;
            return $http.get(url)
                .success(function (data) {
                    if (data.length > 0) {
                        splitName(data);
                        vm.productReviews = vm.productReviews.concat(data);
                        vm.prodReviewsCurPage = curPage;
                        if (data.length < 6) {
                            vm.allowShowMore = false;
                        }
                    }
                    else {
                        vm.allowShowMore = false;
                 
                    }
                }).error(function () {
                    vm.allowShowMore = false;
                });
        }

        function _loadProductReviews(prodNo, curPage) {
            var url = "api/ProductReviews/GetApprovedProductReviews/" + prodNo + "/" + curPage;
            return $http.get(url)
                .success(function (data) {
                    splitName(data);
                    vm.productReviews = data;
                    _canSubmitReview(prodNo);
                    //if there is less than 6 but more than 0 
                    if (vm.productReviews.length < 6 && vm.productReviews.length > 0) {
                        vm.allowShowMore = false;
                    }
                    //there is 6, let them try and render more
                    if (vm.productReviews.length == 6) {
                        vm.allowShowMore = true;
                    }
                    //if it is 0 
                    if (vm.productReviews.length == 0) {
                        vm.allowShowMore = false;
                        vm.productReviews = null;
                    }

                })
                .error(function () {
                    vm.allowShowMore = false;
                    vm.productReviews = null;
                });

        }
        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (oldVal, newVal) {
                if (oldVal && (newVal === null || oldVal.branchNumber !== newVal.branchNumber )) {
                _loadProductRecipeDetails(vm.productId);
            }
        });
        function _loadProductRecipeDetails(prodNo) {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }

            var url = "api/recipes/getRecipesByProduct/" + prodNo + "/" + curBranch;
            return $http.get(url)
                .success(function (data) {                    
                    vm.productRecipes = data;
                })
                .error(function () {
                    vm.recipeError = true;
                    vm.productRecipes = [];
                });
        }

        function splitName(prodRev) {
            for (var i = 0; i < prodRev.length; i++)
            {
                var splitName = prodRev[i].customerName.split(",");
                prodRev[i].customerFirstName = splitName[1];
                prodRev[i].customerLastName = splitName[0][0];
            }
        }
        vm.prodReview;
        vm.cancelFailModal = function () {
            vm.showProductReviewError = false;
        }
        vm.submitReview = function (prodNo) {
            if (vm.prodReview.leaveAnon === undefined) {
                vm.prodReview.leaveAnon = false;
            }
            var url = "api/ProductReviews/SubmitAReview";
            var data = {
                productNumber: prodNo,
                rating: vm.prodReview.rating,
                comment: vm.prodReview.comment,
                leaveAnon: vm.prodReview.leaveAnon
            }

            $http.post(url, data).success(function (data) {
                document.getElementById("product-review-form").reset();
                toggleForm();
                vm.prodReview.leaveAnon = false;
                vm.showProductReviewError = false;

            }).error(function () {
                vm.showProductReviewError = true;
                vm.productReviewSubmitError = "There was an error submitting";
            });

        }
        function _canSubmitReview(prodNo) {
            var url = "api/ProductReviews/GetCanSubmitReview/" + prodNo;
            if (vm.isAuth) {
                return $http.get(url)
                    .success(function (data) {
                        vm.canSubmitReview = data;
                    })
                    .error(function () {
                        vm.canSubmitReview = false;
                    });
            }
            else {
                vm.canSubmitReview = false;
            }



        }
        vm.saveChange = $scope.$parent.vm.saveChange;
        vm.step = datacontext.cust.NewCustomerStep;

        vm.renderHtml = function () {
            return $sce.trustAsHtml(vm.getDescription());
        };
        vm.getnew = function () {
            if (angular.isDefined(vm.product.nutritionInformation))
                var x = vm.product.nutritionInformation['Nutrients'];
            return vm.product;
        };
        vm.getProd = function () {
            return vm.product;
        };
        vm.title = "product detail";
        vm.baseUrl = ngAuthSettings.apiServiceBaseUri.replace('delivery/', 'delivery?');

        vm.ogShareTitle = "";
        vm.getCategory = function (product) {
            if (product.brand == 'Oberweis') return product.categoryName;
        }
        vm.appVersion = appVersion;

        $scope.ogMetaData = {
            url:
                ngAuthSettings.apiServiceBaseUri
                + 'home-delivery/browsing/product/' + vm.productId,
            //ngAuthSettings.apiServiceBaseUri,
            type: 'website',
            title: 'Oberweis Dairy',
            description: 'bla vla',
            image:
                ngAuthSettings.apiServiceBaseUri
                + 'images/' + 'logo-banner.jpg' + vm.appVersion
        };

        vm.showRegionalPrices = function (product) {
            if (unauthenticatedBranch.state.selectedLocationBranch !== null) {
                return false;
            } else if ((!(datacontext.cust.mycust) || !(datacontext.cust.mycust.regionSelected)) && !vm.isAuth && !datacontext.isNewCustomer) {
                //we are now showing "Show Pricing" for all products...
                return true;
                //return (product['regionalPricing']);
            }
        }
        vm.goToRecipeDetails = function (recipeId) {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = -1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
                $state.go('browsing.recipes.recipe', {
                    id: recipeId
                });
            
        }
        vm.RefreshProductsRegion = function (newRegion) {
            datacontext.products.getProductPartialsForPriceCode(newRegion)
                .then(function () {
                    if (newRegion == datacontext.cust.mycust.price_schedule) {
                        datacontext.cust.mycust.regionSelected = true;
                        vm.showPricingModal = false;
                    }
                    datacontext.cust.mycust.price_schedule = newRegion;
                    datacontext.cust.mycust.regionSelected = true;
                    vm.showPricingModal = false;
                });
        }
        vm.postProductFeedback = function (productId, rating) {
            if (!vm.feedback || rating != vm.feedback.rating) {
                datacontext.cust.postProductFeedback(productId, rating).success(function () {
                    //vm.getProductFeedback(productId);
                });
            }
        }

        vm.feedback = {};

        vm.getProductFeedback = function (productId) {
            datacontext.cust.getProductFeedback(productId).then(function (feedback) {
                if (feedback != null) {
                    vm.feedback = feedback;
                }
            });
        }

        // This function supports cook county sugar tax compliance
        vm.SugarTaxCompliant = function () { return false }

        activate();


        function activate() {
            common.activateController([
                datacontext.primeProducts()
            ], controllerId)
                .then(function () {

                    vm.SugarTaxCompliant = function () {
                        if (datacontext.cust.mycust.sugarTaxInEffect) {
                            return true;
                        } else {
                            return false;
                        }
                    }

                    vm.product = _getprodDetails(vm.productId);


                   // vm.getProductFeedback(vm.productId);
                    _loadProductReviews(vm.productId, 1);
                    _loadProductRecipeDetails(vm.productId);

                    $scope.ogMetaData.url = ngAuthSettings.apiServiceBaseUri + 'browsing/product/' + vm.productId;
                    //ngAuthSettings.apiServiceBaseUri.replace('delivery/', 'delivery?') + 'browsing/product/' + vm.productId;

                    $scope.ogMetaData.title = vm.product.brand + vm.getCategory(vm.product) + (vm.product.title || vm.product.description);

                    $scope.ogMetaData.description = vm.product.description;
                    $scope.ogMetaData.image =
                        $scope.cdnBaseUrl
                        + "/assets/images/products/" + vm.productId + ".jpg" + "?v="+$scope.imageVersion;

                    $scope.getSeoMetadata(vm.productId, 3);

                    //common.$broadcast('setMetaData', $scope.ogMetaData);
                });

            $('html, body').animate({
                scrollTop: 0
            }, 0);
        };

        function _getprodDetails(id) {
            var dx = datacontext.products.entityItems[id];
            return datacontext.products.entityItems[id];
        }
    }
})();
;
(function () {
    var controllerId = 'productDetailDairyStoreController';

    angular.module('app-hd').controller(controllerId,
    ['$state', '$scope', '$sce', '$stateParams', 'config', 'common', 'datacontext', 'ngAuthSettings', "authService", productDairyStoreDetail]);

    function productDairyStoreDetail($state, $scope, $sce, $stateParams, config, common, datacontext, ngAuthSettings, authService) {

        var vm = this;
        vm.appVersion = appVersion;
        vm.productId = $stateParams.id;
        vm.product = null ;
        
        $scope.$watch(function () { return datacontext.dairyStoreProducts[vm.productId] }, function () {
            vm.product = datacontext.dairyStoreProducts[vm.productId];
            $scope.getSeoMetadata(vm.productId, 3);

        });
        
        vm.continueBrowsing = function() {
            $state.go('dairy-stores.browsing', {
                category: datacontext.category.selectedParentCategory.navigationUrl
            });
        }
        vm.routeToSpa = function () {
            $state.go("shopping.product", { id: vm.productId });
        };
        vm.routeToFindAStore = function () {
            $state.go("find-a-store");

        };
    }
})();;
(function () {
    var controllerId = 'productDetailRetailController';

    angular.module('app-hd').controller(controllerId,
    ['$state', '$scope', '$sce', '$stateParams', 'config', 'common', 'datacontext', 'ngAuthSettings', "authService", productDetail]);

    function productDetail($state, $scope, $sce, $stateParams, config, common, datacontext, ngAuthSettings, authService) {

        var vm = this;
        vm.appVersion = appVersion;
        vm.productId = $stateParams.id;
        vm.product = null ;
        
        $scope.$watch(function () { return datacontext.retailProducts[vm.productId] }, function () {
            vm.product = datacontext.retailProducts[vm.productId];
            $scope.getSeoMetadata(vm.productId, 3);

        });
        
        vm.continueBrowsing = function() {
            $state.go('retail.browsing', {
                category: datacontext.category.selectedParentCategory.navigationUrl
            });
        }
    }
})();;
(function () {
    var controllerId = 'productRequestController';

    angular.module('app-hd').controller(controllerId,
	['$scope', productRequestController]);


    function productRequestController($scope) {
        var vm = this;
        $scope.page = 1
        vm.requestType = undefined;

        vm.setRequestType = function(requestType){
            vm.requestType = requestType;

            if (vm.requestType === 'customer') {
                vm.productRequestTypeId = 1;
            } else {
                vm.productRequestTypeId = 2;
            }
        }
        
        function isRetail(){
            return vm.requestType === "retailer";
        }
        
        $('#product-request-form-step-1').validate({
            debug: true,
            errorClass: "recipe-form-invalid",
            focusInvalid: false,
            rules: {
                "name-step-1": {
                    required: true
                },
                "email-step-2": {
                    required: true,
                    email: true
                }
            },
            messages: {
                "name-step-1": {
                    required: "Name is required"
                },
                "email-step-2": {
                    required: "Email is required"
                }
            },
            submitHandler: function(from) {
                $scope.page = 2
            }
        })

        $("#product-request-form").validate({
            errorClass: "recipe-form-invalid",
            focusInvalid: false,
            rules: {
                StoreName: {
                    required: true,
                    maxlength: 100 
                },
                StoreAddress: {
                    required: {
                        depends: function() {
                           return !isRetail();
                        }
                    },
                    maxlength: 50
                },
                StoreCity: {
                    required: true,
                    maxlength: 50
                },
                StoreState: {
                    required: true,
                    maxlength: 10
                }
            },
            messages: {
                StoreName: {
                    required: "Store name is required"
                },
                StoreAddress: {
                    required: "Store address is required"
                },
                StoreCity: {
                    required: "Store city is required"
                },
                StoreState: {
                    required: "Store state is required"
                }
            },
            invalidHandler: function(form, validator) {
                if (!validator.numberOfInvalids())
                    return;
                $('html, body').animate({
                    scrollTop: $(validator.errorList[0].element).offset().top - 200 
                }, 500);
            }
        })
    }
})();;
(function () {
    "use strict";
    var controllerId = "progressBarController";

    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , "$state"
            , "datacontext"
            , "authService"
            , progressBar]);

    function progressBar(
         $stateParams
        , $scope
        , $state
        , datacontext
        , authService) {

        var vm = this;
        vm.isActive = _isActive;
        vm.isDisabled = _isDisabled;
        vm.getCssClass = _getCssClass;
        vm.continueShoppingNewCust = _continueShoppingNewCust;
        //vm.showStandingOrderModal = true;

        if (authService.authentication.isAuth == false) {
            vm.showStandingOrderModal = true;
        }
        else {
            vm.showStandingOrderModal = false;
        }

        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal) {
                vm.mycust = datacontext.cust.mycust;
            }
        });

        vm.activeStep = "ng-hide";

        function _isActive(step) {
            var isActive = $state.$current.name.split(".")[1] == step;
            if (isActive) {
                vm.activeStep = "progress-step-" + step;
            }

            return isActive;
        }

        function _continueShoppingNewCust() {
            vm.saveStepChanges();

            var categoryView = datacontext.cust.getLastcategory();
            var subViewName = datacontext.cust.getLastcategoryParam(categoryView);

            $state.go('sign-up.2.category', { productViewId: categoryView, subViewId: subViewName });
        }

        function _isDisabled(step) {

            if (!step || !datacontext.cust.mycust || datacontext.cust.mycust.isPosting) {
                return true;
            }
            if (!datacontext.cust.mycust.maxStep) {
                datacontext.cust.mycust.maxStep = 2;
            }
            if (datacontext.cust.mycust.startupStep > datacontext.cust.mycust.maxStep) {
                datacontext.cust.mycust.maxStep = datacontext.cust.mycust.startupStep;
            }

            return datacontext.cust.mycust.maxStep < step && step < 8;

        }

        function _getCssClass(step) {
            if (vm.isActive(step)) {
                return "active";
            }
            else if (vm.isDisabled(step)) {
                return "inactive";
            }
        }
        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }

        vm.showProgressBar = function () {
            return $state.$current.name.split(".").length > 1
                    && $state.$current.name.split(".")[1] != 8
                    && $state.$current.name.split(".")[1] != 1;
        }

        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        }
    }
})();;
(function () {
    var controllerId = 'promoCodeController';

    angular.module('app-hd').controller(controllerId,
        ['$rootScope', '$scope', '$cookies', '$http', '$stateParams', '$state', 'config', 'common', 'datacontext', "authService", promoCodeController]);

    function promoCodeController($rootScope, $scope, $cookies, $http, $stateParams, $state, config, common, datacontext, authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        var AuthInfo = authService.authentication;

        vm.datacontext = datacontext;

        vm.orderContext = datacontext.order;
        vm.title = 'box';
        vm.collection = [];

        vm.salesPerson = $rootScope.salesPerson;

        $scope.$watch(function () { return $rootScope.salesPerson; }, function () {
            vm.salesPerson = $rootScope.salesPerson;
        });

        vm.checkingPromo = false;
        vm.showSalesPersonModal = false;
        vm.promoCode = "";
        vm.message = "";
        vm.currentCoupons = [];
        vm.Message = "";

        vm.errrorMsg = "";
        vm.lastCode = "";

        vm.delete = function (item) {
            var vm = this;
            var url = AuthInfo.isAuth ? "api/order/delCouponsAuth?couponId=" + item.couponCode
                : "api/order/delCouponsNoAuth?couponId=" + item.couponCode + "&id=" + vm.datacontext.cust.mycust.id;

            vm.message = "";

            return $http.get(url)
                .success(function (data) {
                    vm.getCoupons();
                    vm.datacontext.order.PostOrderDetailUpdate();
                })
                .error(function (data, status, headers, config) {
                });
        };

        vm.deletePromo = function (item) {
            var vm = this;
            var url = "api/order/delCouponsAuth" + "?couponId=" + item.couponCode;

            if (!AuthInfo.isAuth) {
                if (vm.datacontext.cust.mycust.id == null) {
                    return;
                }
                url = "api/order/delCouponsNoAuth" + "?id=" + vm.datacontext.cust.mycust.id + '&couponId=' + item;

                vm.message = "";

                return $http.get(url)
                    .success(function (data) {
                        var promo = {
                            name: '',
                            promo_Code: '',
                            description: '',
                            allowCoolerFree: '',
                            allowCoolerWeeklyDrip: ''
                        };
                        vm.datacontext.cust.mycust.promoCode = promo;

                        vm.datacontext.order.PostOrderDetailUpdate().then(vm.removeFreeCooler);
                    })
                    .error(function (data, status, headers, config) {
                        vm.message = data;
                    });
            }
        };

        vm.submitSalesPerson = function () {
            var vm = this;

            vm.showSalesPersonModal = false;

            if ($cookies.get("salesId")) {
                vm.checkPromo();
            }            
        }

        vm.removeFreeCooler = function () {
            if (vm.datacontext.cust.mycust.porchBoxItems != null) {
                vm.datacontext.order.PostOrderDetailUpdate({
                    productId: vm.datacontext.cust.mycust.porchBoxItems.discountProductNumber,
                    standingQuantity: 0,
                    nextQuantity: 0
                });
            }
        }
        vm.addFreeCooler = function () {
            var vm = this;

            if (vm.datacontext.cust.mycust.porchBoxItems != null) {
                var freePorchBox = vm.datacontext.cust.mycust.porchBox == 'FREE';

                if (freePorchBox) {

                    var prod = [];

                    prod.push(
                        {
                            productId: vm.datacontext.cust.mycust.porchBoxItems.productNumber,
                            standingQuantity: 0,
                            nextQuantity: 1
                        });
                    prod.push(
                        {
                            productId: vm.datacontext.cust.mycust.porchBoxItems.discountProductNumber,
                            standingQuantity: 0,
                            nextQuantity: 1
                        });
                    vm.datacontext.order.PostOrderDetailUpdate(prod);
                }
            }
        }

        vm.getCoupons = function () {
            var vm = this;
            var url = "api/order/getCouponsAuth";

            if (!AuthInfo.isAuth) {
                if (vm.datacontext.cust.mycust.id == null) return;
                //if (vm.promoCode == null) return;
                url = "api/order/getCouponsNoAuth" + "?id=" + vm.datacontext.cust.mycust.id;
            }

            vm.message = "";

            return $http.get(url)
                .success(function (data) {
                    vm.currentCoupons = data;
                })
                .error(function (data, status, headers, config) {
                    vm.message = data;
                });
        }

        vm.checkPromo = function () {
            var vm = this;
            if (vm.checkingPromo) {
                console.log("uh, oh, returning.");
                return;
            }
            vm.checkingPromo = true;

            vm.datacontext.promotion.applyPromotion(vm.promoCode)
                .then(function (promo) {
                    if (promo != null) {
                        vm.datacontext.cust.mycust.promoCode = promo;
                        if (promo.allowCoolerFree) {
                            vm.addFreeCooler();
                        }
                    }
                    vm.getCoupons();

                    vm.promoCode = '';
                    vm.checkingPromo = false;
                    vm.datacontext.order.PostOrderDetailUpdate();
                }, function (data, status, headers, config) {
                    if (data === 'RequireSalesID') {
                        vm.salesPerson.invalid = true;
                        vm.showSalesPersonModal = true;
                    }
                    else {
                        vm.message = data;
                    }
                    vm.checkingPromo = false;
                });
        };

        vm.update = function () {
            if (vm.promoCode != vm.lastCode) vm.message = "";
        };

        activate();

        function activate() {
            vm.datacontext = datacontext;

            common.activateController([
                vm.datacontext.primeProducts()
            ], controllerId)
                .then(function () {
                    if (vm.datacontext.cust.promoCode.length > 0) {
                        vm.promoCode = vm.datacontext.cust.promoCode;
                        vm.checkPromo();
                        vm.datacontext.cust.mycust.promoCodeTxt = undefined;
                    }
                    else if (vm.datacontext.cust.mycust.promotionCode && vm.datacontext.cust.mycust.promotionCode != undefined) {
                        vm.promoCode = vm.datacontext.cust.mycust.promotionCode;
                        vm.checkPromo();
                        vm.datacontext.cust.mycust.promoCodeTxt = undefined;
                    }
                    else {
                        if (vm.datacontext.cust.mycust.promoCodeTxt) {
                            vm.promoCode = vm.datacontext.cust.mycust.promoCodeTxt;
                            vm.checkPromo();
                            vm.datacontext.cust.mycust.promoCodeTxt = undefined;
                        }
                    }

                    vm.hasData = true;
                    vm.getCoupons();
                });
            return;
        }
        //TODO: this may be removed but needs to be tested
        vm.parseBoolean = function (string) {
            var bool;
            bool = (function () {
                switch (false) {
                    case string.toLowerCase() !== 'true':
                        return true;
                    case string.toLowerCase() !== 'false':
                        return false;
                }
            })();
            if (typeof bool === "boolean") {
                return bool;
            }
            return void 0;
        }
    }
})();;
(function () {
    var controllerId = 'recipeCatalogController';

    angular.module('app-hd').controller(controllerId, ['$scope', '$http', '$state', '$filter', 'common', 'config', 'unauthenticatedBranch', 'datacontext', recipeCatalogController]);

    app.filter('startFrom', function () {
        return function (input, start) {
            start = +start; //parse to int
            return input.slice(start);
        }
    });


    function recipeCatalogController($scope, $http, $state, $filter, common, config, unauthenticatedBranch, datacontext) {
        var vm = this;

        vm.$state = $state;
        vm.recipes = [];
        vm.featuredRecipes = [];
        vm.recipeCategories = [];
        vm.ALL_CATEGORY_ID = 0;
        vm.subcategoryLink = ['all', 'dairy', 'breakfast', 'snacks', 'dinner', 'dessert', 'beverages'];
        vm.currentBranch = 1;
        vm.currentPage = 0;
        vm.recipesPerPage = 15;
        vm.perPageOptions = [15, 25, 50, 100];

        vm.navUrl = 'recipes-';
        $scope.getSeoMetadata(vm.navUrl + vm.subcategoryLink[0], 7);

        vm.getBranch = function () {
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = 1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
            vm.currentBranch = curBranch;
        }

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (oldVal, newVal) {
            if (oldVal && oldVal.branchNumber !== newVal.branchNumber) {
                vm.getAllRecipes(vm.ALL_CATEGORY_ID);
                vm.setCategory(vm.ALL_CATEGORY_ID);
                vm.getAllFeaturedRecipes();
            }
        });
        vm.getAllRecipes = function (catId) {
            vm.getBranch();
            var uri = "/api/recipes/getRecipes/" + catId + "/" + vm.currentBranch;

            $http.get(uri).then(
                function (result) {
                    vm.recipes = result.data;
                    vm.totalPages = Math.ceil(vm.recipes.length / vm.recipesPerPage);
                    vm.currentPage = 0;
                    $scope.getSeoMetadata(vm.navUrl + vm.subcategoryLink[catId], 7);
                    return true;
                },
                function (error) {
                    return false;
                    vm.errorMessage = "Internal server error.";
                }
            );
        };
        vm.getRecipeData = function () {
            return $filter('filter')(vm.recipes, vm.recipeQuery)
        };
        vm.numberOfPages = function () {
            return Math.ceil(vm.getRecipeData().length / vm.recipesPerPage);
        };
        vm.getAllFeaturedRecipes = function () {
            vm.getBranch();
            var uri = "/api/recipes/getAllRecipeFeatured/" + vm.currentBranch;

            $http.get(uri).then(
                function (result) {
                    vm.featuredRecipes = result.data;
                    return true;
                },
                function (error) {
                    return false;
                    vm.errorMessage = "Internal server error.";
                }
            );
        };

        vm.getAllRecipeCategories = function () {
            var uri = "/api/recipes/getAllRecipeCategories";

            $http.get(uri).then(
                function (result) {
                    vm.recipeCategories = result.data;
                    return true;
                },
                function (error) {
                    return false;
                    vm.errorMessage = "Internal server error.";
                }
            );
        };
        vm.setCategory = function (id) {
            vm.selectedCategoryId = id;
            vm.getAllRecipes(vm.selectedCategoryId );
        };

        (function activate() {
            vm.selectedCategoryId = vm.ALL_CATEGORY_ID;
            vm.getAllRecipes(vm.selectedCategoryId);
            vm.getAllFeaturedRecipes();
            vm.getAllRecipeCategories();
        })();


    }
})();
;
(function() {
    var controllerId = "recipeController";

    angular.module("app-hd").controller(controllerId, ["$http", "$location", recipeController]);

    function recipeController($http, $location) {
        var vm = this;

        vm.ALL_CATEGORY_ID = 0;
        vm.recipes = [];
        vm.errorMessage = "";

        vm.getRecipes = function() {
            var uri = "/api/recipes/search/" + vm.selectedCategoryId
            
            $http.get(uri).then(
                function(result) {
                    vm.recipes = result.data;
                },
                function(error) {
                    vm.errorMessage = "Internal server error.";
                }
            );
        };

        vm.setCategory = function(categoryId) {
            $location.search("category", categoryId)
            vm.selectedCategoryId = categoryId;
            vm.getRecipes()
        };
        
        vm.recipeFullUrl = function(recipeFriendlyUrl) {
            return "/recipe/" + recipeFriendlyUrl + "?category=" + vm.selectedCategoryId;
        };

        (function() {
            var category = vm.ALL_CATEGORY_ID
            
            if ($location.search().category) {
                const parsed = parseInt($location.search().category);
                if (!isNaN(parsed)) {
                    category = parsed;
                }
            }
                
            vm.setCategory(category);
        })();
    }
})();
;
(function () {
    var controllerId = 'recipeDetailController';

    angular.module('app-hd').controller(controllerId, ['$scope', '$state', '$http', "$stateParams", "datacontext","unauthenticatedBranch", recipeDetailController]);


    function recipeDetailController($scope, $state, $http, $stateParams, datacontext, unauthenticatedBranch) {
        var vm = this;

        vm.recipeId = $stateParams.id;
        _getRecipeDetails(vm.recipeId);
        vm.goToProduct = _goToProduct;

        $scope.$watch(function () { return unauthenticatedBranch.state.selectedLocationBranch }, function (oldVal, newVal) {
            if (oldVal && oldVal.branchNumber !== newVal.branchNumber) {
                if (!isAuthForRecipe()) {
                    $state.go('browsing.recipes');
                }

            }
        });
        function isAuthForRecipe() {
            var branches = vm.recipe.branchRecipeDetail;
            var selectedBranchLocation = unauthenticatedBranch.state.selectedLocationBranch;
            var curBranch = -1;
            if (datacontext.cust.mycust !== null && datacontext.cust.mycust.branch > 0) {
                curBranch = datacontext.cust.mycust.branch;
            } else if (selectedBranchLocation !== null) {
                curBranch = selectedBranchLocation.branchNumber;
            }
            if (curBranch > 0) {
                for (i = 0; i < branches.length; i++) {
                    if (branches[i].branchId == curBranch) {
                        if (branches[i].showOnWeb === true) {
                            return true;
                        }
                    }
                }
                return false;
            }
        }

        function _getRecipeDetails(id) {

            var uri = "/api/recipes/getRecipeDetails/" + vm.recipeId;

            $http.get(uri).then(
                function (result) {
                    vm.recipe = result.data;
                    if (!isAuthForRecipe()) {
                        $state.go('browsing.recipes');
                    }
                    vm.recipe.recipeUrl = "https://www.oberweis.com/home-delivery/browsing/recipe/" + vm.recipe.id;
                    vm.recipe.recipeThumbnailUrl = $scope.CDNImageBaseURL + "/assets/images/recipe/thumbnail/" + vm.recipe.headerImage;
                    vm.recipe.recipeProductId = (vm.recipe.recipeIngredient.map(a => a.productId)).filter(x => x !== null);
                    document.getElementById('recipe-heading').style.setProperty('background-color', vm.recipe.headerColor);
                    document.getElementById('recipe-heading').style.setProperty('color', vm.recipe.headerTextColor);
                    $scope.getSeoMetadata(vm.recipe.id,10);
                },
                function (error) {
                    vm.errorMessage = "Internal server error.";
                }
            );

        }
        function _goToProduct(id) {
            if (id) {
                if ($state.current.name === "shopping.recipes.recipe") {
                    $state.go("shopping.product", { id: id });

                }
                else
                $state.go("browsing.product", { id: id });
            }
        }





    }



})();
;
(function () {
    var controllerId = 'salesPersonController';

    angular.module('app-hd').controller(controllerId,
        ['$scope', '$rootScope', 'datacontext', salesPersonController]);

    function salesPersonController($scope, $rootScope, datacontext) {
        var vm = this;
        vm.datacontext = datacontext;
        
        vm.salesPerson = $rootScope.salesPerson;

        vm.placeholder = "Sales Person ID";

        $scope.$watch(function () { return $rootScope.salesPerson; }, function () {
            vm.salesPerson = $rootScope.salesPerson;
        });

        vm.getSalesPerson = function () {
            var vm = this;
            vm.datacontext.cust.getSalesPerson(vm.salesPerson.tempId).then(function (data) {
                $rootScope.salesPerson = data;
            }, function (err) {
                console.log(err);
            });
        }

        vm.init = function (options) {
            var vm = this;

            if (options.required) {
                vm.required = options.required;
            } else {
                vm.placeholder = vm.placeholder + " (Optional)";
            }
        }

        vm.getSalesPerson();

    }
})();;
(function () {
    var controllerId = 'scheduledDeliveryOfferController';
    angular.module("app-hd").controller(controllerId,
        ["$scope", "datacontext", scheduledDeliveryOfferController]);

    // Shared across all controller instances.
    var originalSlidingDiscount = undefined;
    var originalDeliveryCredit = undefined;

    function scheduledDeliveryOfferController($scope, datacontext) {
        /* This controller *Optimistic* updates the delivery charge and totals directly on the UI customer state.
            When the next PostOrderDetailUpdate runs, the response will update it too.
         */
        
        if (datacontext.cust.mycust.scheduledDeliveryOffer) {
            $scope.selectedOffer = datacontext.cust.mycust.scheduledDeliveryOffer;
        } else {
            $scope.selectedOffer = "ondemand";
        }
        
        function getTotals() {
            return datacontext.order.GetNextDeliveryTotals();
        }

        if (originalSlidingDiscount === undefined) {
            originalSlidingDiscount = datacontext.cust.mycust.slidingDeliveryDiscountTarget;
        }
        
        if (originalDeliveryCredit === undefined) {
            originalDeliveryCredit = getTotals().deliveryChargeCredit;
        }

        function setOriginalDeliveryCredit() {
            var totals = getTotals();

            // Remove the current credit.
            totals.total -= totals.deliveryChargeCredit;
            // Add the original credit.
            totals.total += originalDeliveryCredit;

            totals.deliveryChargeCredit = originalDeliveryCredit;
        }
        
        function removeDeliveryCredit() {
            var totals = getTotals();
            
            totals.total -= totals.deliveryChargeCredit;
            totals.deliveryChargeCredit = 0;
        }
        
        function addDeliveryChargeCredit() {
            var totals = getTotals();
            datacontext.cust.mycust.slidingDeliveryDiscountTarget = 0;

            // The customer could have a partial or full credit already, it needs to be removed.
            totals.total -= totals.deliveryChargeCredit;

            // Add full delivery amount credit.
            var credit = -totals.deliveryCharge;
            totals.deliveryChargeCredit = credit;
            totals.total += credit;
        }

        $scope.onOfferChange = function() {
            var totals = getTotals();
            
            // datacontext.cust.mycust.scheduledDeliveryOffer is used in the PostGetDetailUpdate and order checkout
            var mycust = datacontext.cust.mycust;
            if ($scope.selectedOffer === "ondemand") {
                mycust.onDemandCustomer = true;
                // used when posting order commit and update
                datacontext.cust.mycust.scheduledDeliveryOffer = undefined;
                datacontext.cust.mycust.slidingDeliveryDiscountTarget = originalSlidingDiscount;
                
                if (originalSlidingDiscount > 0 && totals.subtotal >= originalSlidingDiscount) {
                    addDeliveryChargeCredit();
                } else if (originalSlidingDiscount > 0) {
                    removeDeliveryCredit();
                } else {
                    setOriginalDeliveryCredit();
                }
            } else {
                datacontext.cust.mycust.onDemandCustomer = false;
                datacontext.cust.mycust.scheduledDeliveryOffer = $scope.selectedOffer;
                
                if ($scope.selectedOffer === "bi-weekly") {
                    datacontext.cust.mycust.slidingDeliveryDiscountTarget = 25;
                } else if ($scope.selectedOffer === "weekly") {
                    datacontext.cust.mycust.slidingDeliveryDiscountTarget = 0;
                    addDeliveryChargeCredit();
                }
            }
            
            if (datacontext.cust.mycust.slidingDeliveryDiscountTarget > 0) {
                if (totals.subtotal >= datacontext.cust.mycust.slidingDeliveryDiscountTarget) {
                    addDeliveryChargeCredit();
                } else {
                    removeDeliveryCredit();
                }
            }
        };
    }
})();
;
(function () {
    var controllerId = 'shoppingNavigationController';

    angular.module('app-hd').controller(controllerId,
    [

             "$scope"
            , "$state"
            , "config"
            , "common"
            , "datacontext"
            , "authService", shoppingNavigationController]);

    function shoppingNavigationController(
         $scope
        , $state
        , config
        , common
        , datacontext
        , authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(controllerId);
        var $q = common.$q;
        var vm = this;
        vm.showLogoutIncompleteCheckoutWarning = false;

        vm.closeLogoutIncompleteCheckoutWarning = function () {
            vm.showLogoutIncompleteCheckoutWarning = false;
        }

        vm.getCssClass = function (link) {
            if ($state.current.name === link) {
                return 'active-menu-link';
            }
        }

        function getReferralProgram () {
            if (datacontext.cust.mycust)
                return datacontext.cust.mycust.referralProgram;
        }

        vm.hasReferralCampaign = function () {
            return getReferralProgram() && getReferralProgram().campaign
        }

        vm.hasSentReferral = function () {
            return getReferralProgram() && getReferralProgram().hasSentReferral
        };

        vm.hasReceivedReferral = function () {
            return getReferralProgram() && getReferralProgram().hasReceivedReferral
        };

        vm.showGreyBar = function () {
            //var showBar = ($state.current.name != 'sign-in') && !vm.isNewCustomer() && !vm.isIncompleteStartup();
            var showBar = vm.isAuthenticated() && !vm.isNewCustomer() && !vm.isIncompleteStartup();
            if (showBar) {
                $('#bodyContainer').addClass('grey-bar')
            }
            else {
                $('#bodyContainer').removeClass('grey-bar')
            }

            return showBar;
        }

        vm.showHelpLink = function () {
            return $state.current.url && $state.current.url.indexOf('/product/') >= 0;
        }
        vm.showContinueNewCust = function () {
            return (vm.notInMarket() && vm.isNewCustomer());
        }
        vm.continueShoppingNewCust = function () {
            var categoryView = datacontext.cust.getLastcategory();
            var subViewName = datacontext.cust.getLastcategoryParam(categoryView);

            $state.go('sign-up.2.category', { productViewId: categoryView, subViewId: subViewName });
        }

        vm.notInMarket = function () {
            return $state.current.url && $state.current.url.indexOf('category') < 0;
        }
        vm.isAuthenticated = function () {
            return authService.authentication.isAuth;
        }

        vm.showCart = function () {
            return vm.isAuthenticated() || datacontext.isNewCustomer;
        }

        vm.showMyAccountLink = function () {
            return (vm.isAuthenticated());
        }

        vm.showShoppingLink = function () {
            return (($state.current.url) && ($state.current.url.indexOf('account') >= 0));
        }

        vm.hideFromCustomer = function () {
            return vm.isAuthenticated() || datacontext.isNewCustomer;
        }

        vm.isNewCustomer = function () {
            return datacontext.isNewCustomer;
        }
        vm.isIncompleteStartup = function () {
            return datacontext.cust && datacontext.cust.mycust && datacontext.cust.mycust.incompleteCustomerSignup;
        }
        //1-3-2023: allowing all customers to leave delivery feedback. If we ever disable this, replace 'true' with the commented out line 
        vm.allowDeliveryFeedback = function () {
            if (datacontext.cust.mycust) return true;// datacontext.cust.mycust.allowDeliveryFeedback;
        }

        vm.defaultSubscriptionExists = function () {
            if (datacontext.cust.mycust && datacontext.subscription.defaultSubscriptionOfferId != 0)
                return true;
            else
                return false;
        }


        // CCF3 - Remove this check once the mobile tutorial is ready!!!
        window.mobileAndTabletcheck = function () {
            var check = false;
            (function (a) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true; })(navigator.userAgent || navigator.vendor || window.opera);
            return check;
        };

        vm.showTutorialVideo = function () {
            var showTutorial = false;
            if (window.mobileAndTabletcheck()) {
                showTutorial = false;
            }
            else {
                showTutorial = vm.isAuthenticated();
            }
            return showTutorial;
        }
        vm.logOut = function (force) {
            if (!force) {
                datacontext.order.editsMadeAfterLastCheckout().then(function () {
                    var editsMadeAfterCheckout = datacontext.cust.mycust.editsMadeAfterLastCheckout;
                    
                    if (editsMadeAfterCheckout) {
                        vm.showLogoutIncompleteCheckoutWarning = true;
                    }
                    else {
                        vm.closeLogoutIncompleteCheckoutWarning();
                        vm.showLogoutIncompleteCheckoutWarning = false;
                        datacontext.resetAllData();
                        authService.logOut();
                        $scope.showPWlookup = false;
                        $state.go('sign-in');

                    }
                });
            }
            else {
                vm.closeLogoutIncompleteCheckoutWarning();
                vm.showLogoutIncompleteCheckoutWarning = false;
                datacontext.resetAllData();
                authService.logOut();
                $scope.showPWlookup = false;
                $state.go('sign-in');

            }

        }

        vm.changeState = function (targetview, targetSubview, targetState) {
            // targetState category/detail/cart

            if (!(targetState) || targetState.length == 0) targetState = 'category';

            var currentState = $state.current.name.toLowerCase();

            if (targetState.length > 0 && currentState.indexOf(targetState) < 0) {
                // not viewing requested state needs to route
                var prefix = '';
                var newParms = {
                    productViewId: targetview, subViewId: targetSubview
                };

                newParms = getViewParms(newParms);

                if (targetState.indexOf('.') < 0) {
                    var statePrts = currentState.split('.');
                    var prefix = '';
                    for (var inx = 1; inx < statePrts.length; inx++) {
                        prefix += '^.';
                    }
                    if (prefix.length == 0) prefix += '.';
                }

                $state.go(prefix + targetState, newParms, {
                    reload: false,
                    inherit: false,
                    notify: true
                }).then(function () {
                    if (targetState.indexOf('category') >= 0)
                        changecategoryView(targetview, targetSubview);
                    else {
                        changecategoryView(targetview, targetSubview, true);
                    }
                });
            } else {
                if (targetState.indexOf('category') < 0)
                    changecategoryView(targetview, targetSubview, true);
                else
                    changecategoryView(targetview, targetSubview);
            }
        }

        function goBack() {
            history.back();
            scope.$apply();
        }

        function getSubViewId(productViewId) {
            var ret = datacontext.cust.getLastcategoryParam(productViewId);
            if (ret == undefined || ret.length == 0)
                if (productViewId == 'products') {
                    return 'dairy';
                }
            return ret;
        }

        function getPreviousOrDefaultView() {
            var ret = datacontext.cust.getLastcategory();
            return (ret) && (ret.length > 0) ? ret : config.defaultCategory;
        }


        vm.continueShopping = function () {
            var productViewId = getPreviousOrDefaultView();
            changecategoryView(productViewId, '')
        }

        function getViewParms(toParams) {
            var ret = {
                productViewId: (toParams.productViewId && toParams.productViewId.length > 0)
                    ? toParams.productViewId : getPreviousOrDefaultView()
            };

            ret.subViewId = (toParams.subViewId && (toParams.subViewId.length > 0))
                ? toParams.subViewId
                : getSubViewId(ret.productViewId);
            return ret;
        }
        vm.ChangecategoryView = changecategoryView;
        function changecategoryView(categoryView, subViewName, doNotPerformGo) {
            categoryView = (categoryView) && (categoryView.length > 0) ? categoryView.toLowerCase() : config.defaultCategory;
            //if()
            //   subViewName = (subViewName) && (subViewName.length > 0) ? subViewName.toLowerCase() : '';

            var newParms = getViewParms({ productViewId: categoryView, subViewId: subViewName });
            if (categoryView != datacontext.category.productViewName) {
                vm.productViewId = newParms.productViewId;
                vm.subcategoryid = newParms.subViewId;
                datacontext.category.setProductViewName(vm.productViewId);
            }
            if (vm.productViewId == 'products') {
                if (vm.subcategoryid && (vm.subcategoryid.length > 0)) {
                    datacontext.category.selectcategory(vm.subcategoryid);
                }
            }
            datacontext.cust.putLastcategoryParam(categoryView, subViewName);
            datacontext.cust.putLastcategory(categoryView);

            if (!doNotPerformGo) {
                // this is necessary so that the category is set and ready to display when it returns to the
                // categroy view
                $state.go('browsing.category', newParms, {
                    reload: false,
                    inherit: false,
                    notify: true
                });
            }
        }

        vm.ChangeSubCategoryView = function (elem) {
            var subViewName = elem.cat2.name;
            var categoryView = $state.params.productViewId || '';

            datacontext.category.selectcategory(subViewName);
            datacontext.cust.putLastcategoryParam(categoryView, subViewName);
            $state.go('^.category', { productViewId: categoryView, subViewId: subViewName }, {
                reload: false,
                inherit: false,
                notify: true
            });
        }

        activate();

        function activate() {
            vm.isAuth = authService.authentication.isAuth;
            if (vm.isAuth) {
                common.activateController([
                    datacontext.primeProducts(),
                    datacontext.subscription.getDefaultSubscriptionOfferId()
                ], controllerId)
                .then(function () {
                });

                return;
            }
        };
    }
})();
;
(function () {
    var controllerId = 'specialMessageController';
    angular.module("app-hd").controller(controllerId,
        [ "$scope"
            , "datacontext"
            , "common"
            , specialMessage]);

    function specialMessage(
         $scope
        , datacontext
        , common) {

        var vm = this;

        vm.showSpecialMessage = false;
        vm.closeSpecialMessage = _closeSpecialMessage;

        function _closeSpecialMessage() {
            vm.showSpecialMessage = false;
        }

        activate();

        function activate() {
            //get messages
            var branches = [1, 7, 8, 9, 10, 11, 12];
            var days = [3, 4];
            datacontext.primeCustomer().then(function () {
                var dd = moment(datacontext.cust.mycust.nextDeliveryDate);
                vm.showSpecialMessage = false; // branches.includes(datacontext.cust.mycust.branch) && days.includes(dd.day());
            });
        }

        function getMessages() { 
            var defer = $q.defer();

            datacontext.store.getStores().then(
                function (response) {

                    defer.resolve();
                }
                , function (data, status) {
                    console.error('getMessages() error', status, data);
                    defer.reject();
                }
            );

            return defer.promise
        }
    }
})();;
(function () {
    var controllerId = 'spinnerController';
    angular.module('app-hd').controller(controllerId,
        ['$rootScope', 'common', 'config', spinnerController]);

    function spinnerController($rootScope, common, config) {
        var vm = this;

        var events = config.events;
        vm.busyMessage = 'Please wait ...';
        vm.isBusy = true;
        vm.spinnerOptions = {
            radius: 40,
            lines: 7,
            length: 0,
            width: 30,
            speed: 1.7,
            corners: 1.0,
            trail: 100,
            color: '#ec1f30'
        };

        $rootScope.$on(events.controllerActivateSuccess,
            function (event, data) {
                if (common.cntlCount <= 1) {
                    toggleSpinner(false);
                } else {
                    common.cntlCount--;
                }
            }
        );

        $rootScope.$on('$viewContentLoaded', function (event, data) {
            if (common.cntlCount <= 1) {
                var x = 0;
                // toggleSpinner(false);
            } else {
                common.cntlCount--;
            }
        }
        );

        $rootScope.$on(events.spinnerToggle,
            function (event, data) {
                toggleSpinner(data.show);
            }
        );


        activate();

        function activate() {
            common.activateController([], controllerId);
            toggleSpinner(true);
        }

        function toggleSpinner(on) {
            vm.isBusy = on;
        }

    }
})();;
(function () {
    var controllerId = 'storeController';
    angular.module('app-hd').controller(controllerId,
        ['$scope', '$rootScope', '$q', '$http', '$location', '$state', '$window', '$anchorScroll', 'common', 'config', 'uiGmapGoogleMapApi', 'uiGmapIsReady', storeController]);

    function storeController($scope, $rootScope, $q, $http, $location, $state, $window, $anchorScroll, common, config, uiGmapGoogleMapApi, uiGmapIsReady) {
        var vm = this;

        //vm.request = {
        //    address: "",
        //    oberweisStores: true,
        //    groceryStores: false
        //}
        vm.setQueryParam = function () {
            vm.request = {
                address: $location.search().address,
                oberweisStores: ($location.search().oberweisStores === "true" || $location.search().oberweisStores === undefined),
                groceryStores: ($location.search().groceryStores === "true")
            }
        }

        vm.setQueryParam();

        $scope.$watch(function () { return $location.search() }, function () {
            vm.setQueryParam();
            vm.refreshGeoLocation();
        });

        vm.position = { coords: { latitude: 41.79818400000001, longitude: -88.348431 } };
        vm.map = {
            center: { latitude: vm.position.coords.latitude, longitude: vm.position.coords.longitude }
            , zoom: 11
            , options: { scrollwheel: false }
        };

        vm.distanceOptions = [5, 10, 20, 50, 100];
        vm.distanceSelected = 20;
        vm.mobileBrakepoint = 680;
        vm.showMap = true;
        vm.stores = { oberweis: {}, loaded: false };

        vm.canGeolocate = canGeolocate;
        vm.findStores = findStores;
        vm.gotoGeolocation = gotoGeolocation;
        vm.gotoAddress = gotoAddress;
        vm.gotoMarker = gotoMarker;

        vm.windowOptions = {
            pixelOffset: {
                height: -30,
                width: 0
            }
        };
        uiGmapGoogleMapApi.then(function (maps) {
            //var request = $window.sessionStorage.getItem("findStoreRequest");
            //if (request) {
            //    vm.request = JSON.parse(request);
            //    $window.sessionStorage.removeItem("findStoreRequest");
            vm.refreshGeoLocation();
        });

        vm.refreshGeoLocation = function () {
            if (vm.request && vm.request.address) {
                gotoAddress();
            } else {
                if (canGeolocate()) {
                    gotoGeolocation();
                }
            }
        }

        vm.googleDirections = function () {
            var url = "http://maps.google.com/?q=" + vm.currentStore.address + ',' + vm.currentStore.city + ',' + vm.currentStore.state + ',' + vm.currentStore.zipCode;
            window.location.href = url;
        }
        vm.store = {};

        vm.markerEvents = {
            click: function (gMarker, eventName, store) {
                if ($(window).width() > vm.mobileBrakepoint) {
                    //$anchorScroll.yOffset = $('#find-a-store-list').position().top;
                    //$location.hash(store.id);
                    $anchorScroll();
                }
                gotoMarker(store);
            }
        };

        function gotoGeolocation() {
            geolocate().then(function (position) {

                //$location.search("address", "");

                vm.request = {
                    address: "",
                    oberweisStores: vm.request.oberweisStores,
                    groceryStores: vm.request.groceryStores
                };

                centerMap(position);

                findStores(position);
            }, function () {
                centerMap(vm.position);
                findStores(vm.position);
            });
        }

        function centerMap(position) {
            vm.map.center.latitude = position.coords.latitude;
            vm.map.center.longitude = position.coords.longitude;
        }

        function canGeolocate() {
            return ("geolocation" in navigator);
        }

        function gotoAddress() {

            $location.search("address", vm.request.address);
            $location.search("oberweisStores", vm.request.oberweisStores.toString());
            $location.search("groceryStores", vm.request.groceryStores.toString());

            if (vm.request.address) {
                findLocation(vm.request.address).then(function (position) {
                    centerMap(position);
                    findStores(position);
                }, function (reason) {
                    alert(reason);
                });
            }
            else {
                vm.gotoGeolocation();
            }
        }
        vm.storeId = 0;

        vm.setCurrentStoreLocation = function () {

            var store = $scope.oberweisStores.filter(function (item) {
                return item.location === vm.storeId;
            })[0];

            vm.showMap = true;

            store.show = false;

            vm.store = vm.currentStore = store;

            vm.centerToCurrentStore();

            //vm.store.icon = '/images/map-icon-store.png';
            vm.store.options = { labelClass: 'marker_labels', labelAnchor: '30 65', labelContent: vm.store.location};

            //var title = store.name + " in " + store.city + ", " + store.state;
            var title = store.name + " locations near " + store.city + ", " + store.state;

            $scope.setStoreName(title);

        }

        vm.centerToCurrentStore = function () {
            vm.map.center.latitude = vm.currentStore.coordinates.latitude;
            vm.map.center.longitude = vm.currentStore.coordinates.longitude;
        }

        function gotoMarker(store) {
            vm.showMap = true;
            $("html, body").animate({ scrollTop: $("#map-container").offset().top - 120 }, 500);

            if (vm.store) {
                vm.store.show = false;
            }
      
            store.show = true;
            if (store.isOberweis) {
                vm.store = store;
            }
          
        }

        $scope.oberweisStores = [];

        function findStores(position) {
            var data = {
                latitude: position.coords.latitude,
                longitude: position.coords.longitude,
                searchOberweis: vm.request.oberweisStores,
                distance: 100000
            };

            $http.post('api/StoreFinder', data).success(
                function (response) {
                    vm.stores.oberweis = response.oberweis;

                    angular.forEach(vm.stores.oberweis, function (store, key) {
                        store.id = 'oberweis.' + key;
                        store.isOberweis = true;
                        store.icon = $scope.CDNImageBaseURL + '/website/images/map-icon-store.png';
                        store.closeClick = function () {
                            store.show = false;
                        };
                    });

                    vm.stores.loaded = true;

                    $scope.oberweisStores = vm.stores.oberweis;
                    vm.setCurrentStoreLocation();

                });
        }

        function geolocate() {
            var d = $q.defer();
            navigator.geolocation.getCurrentPosition(d.resolve, d.reject);
            return d.promise;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "storedPaymentController";
    angular.module("app-hd").controller(controllerId, ['$http', '$q', '$location', '$state', "$scope", "$sce", "$window", "config", "common", "datacontext", storedPaymentController]);

    function storedPaymentController($http, $q, $location, $state, $scope, $sce, $window, config, common, datacontext) {
        //
        //	new customer deliveryDate controller
        //

        var vm = this;
        vm.checkedValue = false;
        vm.paymentIframe = {};

        //vm.setPaymentType = setPaymentType;
        //vm.setPaymentMethod = setPaymentType;
        //function continueButtonClicked(noValidate) {
        //    if (common.validateForm("#checkingForm") && vm.validateChecking()) {
        //        enrollPaymentType();
        //    }
        //}



        //vm.LookupBankName = _LookupBankName;
        vm.isPaymentTypeActive = isPaymentTypeActive;

        vm.paymentMethod = { paymentType: '' };
        vm.expireYearOptions = [];
        vm.enroll_Message = "";

        vm.showPhoneNumber = true;

        //vm.getYearRange = function () {
        //    var expireYearOptions = [];

        //    var dt = new Date();

        //    for (var i = 0; i < 12; i++) {
        //        expireYearOptions.push(i + dt.getFullYear());
        //    }
        //    return expireYearOptions;
        //}


        //function setPaymentType() {
        //    if (!(vm.paymentMethod.paymentMethod === 'Credit Card' && vm.enroll_success)) {
        //        vm.editCreditCard();
        //    }
        //    datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod;
        //}

        function isPaymentTypeActive(paymentType) {
            return vm.paymentMethod.paymentMethod === paymentType;
        }

        var initialPaymentdata = {
            billCode: "11",
            bankName: '',
            paymentMethod: "Checking",
            creditCard: '',
            expireMonth: null,
            expireYear: null,
            accountNumber: '',
            routingNumber: '',
            zip: ''
        };

        //function enrollPaymentType() {
        //    //
        //    //	performed after the information is entered into the text box
        //    //
        //    vm.enroll_Message = "";
        //    vm.paymentMethod.billCode = (vm.paymentMethod.PaymentMethod == "Checking") ? "11" : "10";
        //    var defer = $q.defer();

        //    datacontext.cust.mycust.paymentType = vm.paymentMethod.paymentMethod;
        //    datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod;


        //    if (vm.paymentMethod.paymentMethod == 'Checking') {
        //        datacontext.cust.mycust.bankName = vm.paymentMethod.bankName;
        //        datacontext.cust.mycust.accountNumber = vm.paymentMethod.accountNumber;
        //        datacontext.cust.mycust.routingNumber = vm.paymentMethod.routingNumber;
        //        datacontext.cust.mycust.creditCard = ''
        //        datacontext.cust.mycust.expireMonth = '';
        //        datacontext.cust.mycust.expireYear = ''; datacontext.cust.mycust.accountNumber = vm.paymentMethod.accountNumber;
        //        datacontext.cust.mycust.routingNumber = vm.paymentMethod.routingNumber;
        //        datacontext.cust.mycust.zip = '';
        //        datacontext.cust.mycust.paymentOrderIdString = null;
        //        datacontext.cust.mycust.payerId = null;

        //        datacontext.cust.mycust.completedPaymentInfo = true;

        //        vm.navigateToNext();

        //        return;
        //    } else {
        //        datacontext.cust.mycust.bankName = '';
        //        datacontext.cust.mycust.accountNumber = '';
        //        datacontext.cust.mycust.routingNumber = '';

        //        datacontext.cust.mycust.expireMonth = vm.paymentMethod.expireMonth;
        //        datacontext.cust.mycust.expireYear = vm.paymentMethod.expireYear;
        //        datacontext.cust.mycust.zip = vm.paymentMethod.zipCode;
        //    }

        //    vm.paymentMethod.customerNumber = datacontext.cust.mycust.customerNumber;
        //};


        //vm.validateChecking = function () {
        //    if (vm.paymentMethod.paymentMethod === "Checking") {
        //        if (!vm.paymentMethod.bankName) {
        //            vm.enroll_success = false;
        //            vm.enroll_Message = "Invalid Routing Number.";
        //            return false;
        //        }
        //    }
        //    return true;
        //}

        vm.resetErrorMessage = function () {
            vm.enroll_Message = "";
        };

        //function _LookupBankName() {
        //    if (('' + vm.paymentMethod.routingNumber).length >= 8) {
        //        return $http.get("api/customers/getBankName?rounteNum=" + vm.paymentMethod.routingNumber)
        //            .success(querySucceeded);
        //    }

        //    function querySucceeded(data) {
        //        vm.resetErrorMessage();
        //        vm.paymentMethod.bankName = data;
        //    }
        //}
        $window.submitPaymentSuccess = function (data) {
            var urlParams = new URLSearchParams(window.location.search);

            urlParams.set('order_id', data.uID);
            urlParams.set('response_code', data.code);//data.code
            urlParams.set('response_code_text', data.message);
            urlParams.set('phoneNumber', vm.customer.phone);
            
            window.location.search = urlParams;
        }

        function verifyPaymentData() {
            //console.log($state.params)
            if (($state.params.response_code) && ($state.params.response_code.length > 0)) {

                datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod = 'Credit Card';

                if (($state.params.response_code == 1 || $state.params.response_code == "000")) {

                    //datacontext.cust.getPaymentData($state.params.order_id, true).then(function (result) {
                    //    var starword = '************' + result.span;

                    //    datacontext.cust.mycust.maskedCreditCard = starword;
                    //    datacontext.cust.mycust.creditCard = starword;
                    //    datacontext.cust.mycust.last4CreditCard = result.span;
                    //    datacontext.cust.mycust.payerId = result.payer_identifier;
                    //    datacontext.cust.mycust.paymentOrderIdString = result.order_id;
                    //    datacontext.cust.mycust.expireMonth = result.expire_month;
                    //    datacontext.cust.mycust.expireYear = result.expire_year;
                    //    vm.customer.creditCard = starword;
                    //    datacontext.cust.mycust.accountNumber = '';
                    //    datacontext.cust.mycust.routingNumber = '';
                    //    datacontext.cust.mycust.zip = result.billing_zip_code;

                    //    vm.enroll_Message = "Payment Type Approved";
                    //    vm.enroll_success = true;

                    //    datacontext.cust.mycust.completedPaymentInfo = true;
                    //    vm.navigateToNext();
                    //}, function () {
                    //    //error
                    //    vm.clearQueryStringParameters();
                    //    vm.creditCardErrorMessage = config.paymentServiceErrorMessage;
                    //    vm.enroll_success = false;
                    //})
                }
                else {
                    vm.creditCardErrorMessage = $state.params.response_code_text;
                    vm.editCreditCard();
                }
            }
        }

        activate();

        function activate() {
            //
            //	this code will run only once throughout the sign up of a new customer
            //


            datacontext.primeCustomer().then(function () {

                vm.customer = datacontext.cust.mycust;

                vm.editCreditCard = function () {
                    vm.enroll_success = false;
                    vm.showPhoneNumber = false;

                    common.$broadcast(config.events.spinnerToggle, { show: true });

                    var returnUrl = '/payment?phoneNumber=' + vm.customer.phone;

                    datacontext.cust.getAuthenticationUrl(returnUrl, vm.customer.customerNumber, true).then(function (result) {
                        vm.paymentIframeUrl = $sce.trustAsResourceUrl(result.iFrameUrl);
                        common.includePaymentScripts();
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    }, function () {
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                        vm.enroll_Message = config.paymentServiceErrorMessage;
                    });
                };

                //verifyPaymentData();
                ////common.validateCustomerNumber(vm.customer.customerNumber);

                //if (datacontext.cust.mycust.accountNumber != null && datacontext.cust.mycust.routingNumber != null) {
                //    if (datacontext.cust.mycust.accountNumber > 0 && datacontext.cust.mycust.routingNumber > 0) {
                //        vm.checkedValue = true;
                //    }
                //}

                ////$('#CreditCardIFrame').attr("src", vm.paymentIframe.url);

                //if ((datacontext.cust.mycust) && (datacontext.cust.mycust.paymentMethod)) {

                //    initialPaymentdata = {
                //        billCode: (datacontext.cust.mycust.paymentMethod == "Checking") ? "11" : "10",
                //        bankName: datacontext.cust.mycust.bankName,
                //        paymentMethod: datacontext.cust.mycust.paymentMethod,
                //        creditCard: datacontext.cust.mycust.creditCard,
                //        expireMonth: datacontext.cust.mycust.expireMonth,
                //        expireYear: datacontext.cust.mycust.expireYear,
                //        accountNumber: datacontext.cust.mycust.accountNumber,
                //        routingNumber: datacontext.cust.mycust.routingNumber,
                //        zip: datacontext.cust.mycust.zip,
                //    }
                //}

                //angular.copy(initialPaymentdata, vm.paymentMethod);



                //vm.enroll_success = (((datacontext.cust.mycust)
                //    && (datacontext.cust.mycust.bankName) && datacontext.cust.mycust.bankName.length > 0)
                //    && datacontext.cust.mycust.accountNumber.length > 0) ||
                //    ((datacontext.cust.mycust) && datacontext.cust.mycust.payerId && datacontext.cust.mycust.payerId.length > 0) ? true : false;


                //if (vm.paymentMethod.paymentMethod == "Checking") {
                //    vm.LookupBankName();
                //}
                //else {
                //    if (!vm.enroll_success) {
                //        vm.editCreditCard();
                //    }
                //}


                //var dt = new Date();
                //for (var i = 0; i < 12; i++) {
                //    vm.expireYearOptions.push(i + dt.getFullYear());
                //}
            });
        }

        //vm.showMainMenu = function () {
        //    var fullsite = "" + window.location;
        //    if (fullsite.indexOf('/sign-up') > 0) return false;
        //    else return true;
        //}
    }
})();;
(function () {
    var controllerId = 'storeLocatorController';
    angular.module("app-hd").controller(controllerId,
        ["$stateParams"
            , "$scope"
            , '$http'
            , "$state"
            , "$cookies"
            , "$filter"
            , "$location"
            , "$window"
            , "datacontext"
            , "authService"
            , "common"
            , storeLocator]);

    function storeLocator(
         $stateParams
        , $scope
        , $http
        , $state
        , $cookies
        , $filter
        , $location
        , $window
        , datacontext
        , authService
        , common) {

        var vm = this;
        var $q = common.$q;

        vm.storelocationchanged = _storelocationchanged;
        vm.showFeedbackModal = _showFeedbackModal;
        vm.storebrandchange = _storebrandchange;
        vm.showModal = false;
        //vm.iframeUrl = 'https://locationrater.com/tp/gJAqba';
        vm.iframeUrl = 'https://www.locationrater.com/survey/dGhhdC1idXJnZXItam9pbnQtYmxvb21pbmd0b24taWxsaW5vaXMtdXMtZWRmOWVm';

        vm.showIFrame = true;

        vm.stores = {
            oberweis: {}, states: {}, loaded: false };

        
        
        vm.storesForDDL = {};
        //for branded fee=dback. Need a DDL for states when the brand is changes 
        vm.statesForDDL = {};

        function _resetdefaults() {
            vm.dairyStore = "";
            _resetStores();
            _resetStates();
        }

        function initializeFormValidation() {
            $("#storeLocatorForm").validate({
                errorClass: 'customErrorClass'
            });
        }

        function _storelocationchanged() {
            _resetStates();
            _resetStores();
            datacontext.store.setSelectedStore(vm.dairyStore);
        }
        vm.submitLocation = _submitLocation;
        function _submitLocation() {
            var store = datacontext.store.getSelectedStore();
            if (vm.dairyBrand == "That Burger Joint") {
                window.location = store.tbjFeedbackUrl;
            }
            else if (vm.dairyBrand == "Woodgrain Pizzeria") {
               window.location = store.wgFeedbackUrl;
            }
            else {
                window.location = store.feedbackUrl;
            }

        }
        function _resetStores() {
            if (vm.dairyBrand == "That Burger Joint") {
                vm.storesForDDL = $filter('filter')(vm.stores.oberweis, { state: vm.dairyState, tbj: true });
            }
            else if (vm.dairyBrand == "Woodgrain Pizzeria") {
                vm.storesForDDL = $filter('filter')(vm.stores.oberweis, { state: vm.dairyState, woodgrain: true });
            }
            else {
                vm.storesForDDL = $filter('filter')(vm.stores.oberweis, { state: vm.dairyState });
            }
        }
        function _resetStates() {
            if (vm.dairyBrand == "Oberweis") {
                vm.statesForDDL = vm.stores.states;
            }
            if (vm.dairyBrand == "That Burger Joint") {
                vm.statesForDDL = vm.stores.tbjStates;

            }
            if (vm.dairyBrand == "Woodgrain Pizzeria") {
                vm.statesForDDL = vm.stores.woodgrainStates;
            }

        
        }
        function _storebrandchange() {
            _resetStates();
            _resetStores();
        }
        //-----------------------------
        activate();

        function activate() {
            vm.showModal = ($location.search()).feedback != null;

            getStores().then(
                function () {
                    _resetdefaults();
                });
        }

        function getStores() { 
            var defer = $q.defer();

            datacontext.store.getStores().then(
                function (response) {
                    var data = response.data;
                    vm.stores.oberweis = data;
                    vm.stores.tbj = [];
                    vm.stores.woodgrain = [];
                    vm.stores.states = [];
                    vm.stores.woodgrainStates = [];
                    vm.stores.tbjStates = [];
                    vm.stores.brands = ["Oberweis", "That Burger Joint", "Woodgrain Pizzeria"];
                    angular.forEach(data, function (value, key) {                       
                        if (-1 === vm.stores.states.indexOf(value.state)) {
                                vm.stores.states.push(value.state);
                        }
                        if (value.tbj) {
                            vm.stores.tbj.push(value);
                            if (-1 === vm.stores.tbjStates.indexOf(value.state)) {
                                vm.stores.tbjStates.push(value.state);
                            }
                            if (value.woodgrain) {
                                vm.stores.woodgrain.push(value);
                                if (-1 === vm.stores.woodgrainStates.indexOf(value.state)) {
                                    vm.stores.woodgrainStates.push(value.state);
                                }
                            }
                        }
                    });

                    vm.dairyState = vm.stores.states[0];
                    vm.dairyBrand = vm.stores.brands[0];
                    vm.stores.loaded = true;
                    defer.resolve();
                }
                , function (data, status) {
                    console.error('get stores Repos error', status, data);
                    defer.reject();
                }
            );

            return defer.promise
        }

        function _showFeedbackModal() {
            if (vm.showModal) {
                //var store = datacontext.store.getSelectedStore();
                $window.open(($location.search()).feedback, '_blank');
            }
            vm.showModal = false;
            //return vm.showModal;
        }

    }
})();;
(function () {
    "use strict";
    var controllerId = "suspendController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$state", "$http", "$filter", "config", "common", "datacontext", "authService", suspendController]);

    function suspendController($scope,$state, $http, $filter, config, common, datacontext,authService) {
        var vm = this;
        vm.result_success = false;
        vm.result_Message = "";
        vm.mycustLockout = true;
        vm.DeliveryDate = "00/00/00";
        vm.confirmed = false;
        vm.skipOriginal = null;
        vm.skip_change = skip_change;
        vm.close = close;
        vm.cancel = cancel;
        vm.submitSuspendRequest = submitSuspendRequest;
        vm.notSuspendedOption = {};
        vm.allowUserToSuspend = false;
        vm.showSuspendModal = false;
        vm.cartItemDisabledReason = '';
        vm.test = $scope.userSuspended;
        vm.dirty = false;
        vm.unskipDelivery = unskipDelivery;


        // unskip a delivery
        function unskipDelivery() {
            if (!vm.mycustLockout) {
                vm.skip = 0.0;
                submitSuspendRequest();
            }
            vm.showSuspendModal = true;
            vm.showMoreOptions
            return;
        }

        vm.showSuspendLink = function () { return false; };

        vm.showUnSuspendLink = function () { return false; };

        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal) {
                vm.showSuspendLink = function () {
                    return datacontext.cust.mycust && !datacontext.cust.mycust.userSuspended && !datacontext.cust.mycust.adminLockout;
                };

                vm.showUnSuspendLink = function () {
                    return datacontext.cust.mycust && datacontext.cust.mycust.userSuspended && !datacontext.cust.mycust.adminLockout;
                };
            }
        });

        // skip a delivery
        function submitSuspendRequest() {

            common.$broadcast(config.events.spinnerToggle, { show: true });

            var str = vm.skip.toString().split(".");

            vm.numberOfDeliveriesToSuspend = datacontext.cust.mycust.numberOfDeliveriesToSuspend = parseInt(str[0]);
            vm.deliveriesBeforeSuspension = datacontext.cust.mycust.deliveriesBeforeSuspension = parseInt(str[1] ? str[1] : "0");

            return datacontext.order.updateSuspension().then(function (response) {

                var dd = vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
                var fd = datacontext.cust.mycust.futureDeliveryDate;

                vm.result_success = true;

                if (vm.skip == 0) {
                    vm.result_Message = "Your delivery will no longer be suspended. An email confirmation has been sent to you.";
                }
                else if (vm.skip > 0) {

                    var message = (vm.numberOfDeliveriesToSuspend == 1) ? "delivery" : vm.numberOfDeliveriesToSuspend + " deliveries";
                    if (vm.deliveriesBeforeSuspension > 0) {
                        vm.result_Message = "Your next delivery will be made and then your next " + message + " will be suspended. Your home delivery will automatically resume " + fd + ". An email confirmation has been sent to you.";
                    }
                    else {
                        vm.result_Message = "Your next " + message + " will be suspended. Your home delivery will automatically resume " + dd + ". An email confirmation has been sent to you.";
                    }
                }

                common.$broadcast(config.events.spinnerToggle, { show: false });
                vm.confirmed = true;

            }, function (data) {
                common.$broadcast(config.events.spinnerToggle, { show: false });
                vm.result_success = false;
                vm.result_Message = "error Message: " + data;
            });
        };

        function cancel() {
            //this is being done to reset in case they change a check box, cancel and reload the modal
            getSuspendInfo();
            close();
        }

        function close() {
            vm.result_Message = '';
            vm.confirmed = false;
            vm.showSuspendModal = false;
            vm.dirty = false;
        }

        function getSuspendInfo() {
            return $http.get("api/order/GetSkipDeliveries").then(
                function (response) {
                    vm.numberOfDeliveriesToSuspend = datacontext.cust.mycust.numberOfDeliveriesToSuspend = response.data.skip;
                    vm.deliveriesBeforeSuspension = datacontext.cust.mycust.deliveriesBeforeSuspension = response.data.make.toString();
                    vm.skip = parseFloat(vm.numberOfDeliveriesToSuspend + '.' + vm.deliveriesBeforeSuspension);
                    vm.skipOriginal = vm.skip;
                }, function (data, status, headers, config) {
                    vm.result_success = false;
                    vm.result_Message = "Can not obtain account information, please try later or contact customer service.";
                });
        }

        function skip_change() {
            vm.dirty = vm.skipOriginal != vm.skip;
        }

        function activateError(errorMessage) {
            if (!errorMessage) {
                errorMessage = "Can not obtain account information, please try later or contact customer service.";
            }
            authService.logOut();
            $state.go("sign-in-error", { error: errorMessage });
        }

        activate();
        function activate() {
            common.activateController([
                datacontext.primeCustomer()
            ], controllerId)
                .then(function () {
                    return getSuspendInfo();
                },
                function (error) {
                    if (error.message === "Reinstate Error") {
                        activateError("There was an error restarting your service. Please contact customer service at 866-623-7934 or create a new account");
                    } else {
                        activateError();
                    }
                })
                .then(function () {
                    vm.mycustLockout = datacontext.cust.mycust.lockUser;
                    vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
                }, function () { activateError(); });
        }
    }
})();
;
var controllerId = "referralController";

(function () {
    "use strict";
    angular.module("app-hd").controller(controllerId, ["$state", "$stateParams", "$scope", "datacontext", "authService",
        "$http", "common", "config", referralController]);

    function referralController($state, $stateParams, $scope, datacontext, authService, $http, common, config) {
        $scope.tabs = [
            {
                name: "send",
                title: "Send Referrals",
                canShow: function () {
                    return getCampaignId() > 0;
                }
            },
            {
                name: "pending",
                title: "Pending Referrals",
                canShow: function() {
                    return $scope.sentReferrals.pending.length > 0
                }
            },
            {
                name: "rewards",
                title: "Received Rewards",
                canShow: function() {
                    return $scope.sentReferrals.completed.length > 0 || $scope.rewardsAsReceiver.length > 0
                }
            },
        ];

        $scope.submitReferralState = {
            submitClicked: false,
            loading: false,
            error: false,
            errorMessage: ""
        }

        $scope.sentReferrals = {
            pending: [],
            completed: []
        }

        $scope.rewardsAsReceiver = [];

        $scope.referralProgram = null;

        $scope.resendingReferral = false;
        $scope.resentReferralMessage = null;
        $scope.referralBannerFileName = "refer_friend_header.png"
        $scope.resendReferral = function(referralId) {
            $scope.resendingReferral = true;
            $scope.resentReferralMessage = null;
            $http.get("/api/referral/resend/" + referralId)
                .then(function(){
                    $scope.resendingReferral = false;
                    $scope.resentReferralMessage = "The referral has been successfully resent"
                    $('#referral-resent-modal').modal('toggle')
                }, function(error) {
                    $scope.resendingReferral = false;
                    if (error && error.data && error.data.message) {
                        $scope.resentReferralMessage = error.data.message;
                    } else {
                        $scope.resentReferralMessage = "Error resending, please try again later or contact customer service";
                    }
                    $('#referral-resent-modal').modal('toggle')
                });
        };

        ;(function activate(){
            common.$broadcast(config.events.spinnerToggle, { show: true });

            common.activateController([
                datacontext.primeCustomer(),
                $http.get("/api/referral/referrals").then(function(response) {
                    var sentReferrals = response.data.sentReferrals;
                    var rewardsAsReceiver = response.data.rewardsAsReceiver;

                    $scope.rewardsAsReceiver = rewardsAsReceiver;

                    $scope.sentReferrals.pending = [];
                    $scope.sentReferrals.completed = [];
                    sentReferrals.forEach(referral => {
                        if (referral.isCompleted) {
                            $scope.sentReferrals.completed.push(referral);
                        } else {
                            $scope.sentReferrals.pending.push(referral);
                        }
                    });
                })
            ], controllerId)
                .then(function () {
                    $scope.referralProgram = datacontext.cust.mycust.referralProgram;
                    
                    if (getCampaignId() > 0) {
                        $scope.referralBannerFileName = $scope.referralProgram.campaign.sendBannerFileName;
                        
                        if ($scope.referralProgram.campaign.allowReusableCode === true) {
                            $http.get("/api/referral/reusable-link/" + getCampaignId()).then(function(response) {
                                $scope.reusableLink = response.data.link;
                            })
                        }
                    }
                    
                    if (!$state.params.tabName || $state.current.name === "shopping.referral") {
                        if ($scope.tabs[0].canShow()) {
                            $state.go('shopping.referral.tab', { tabName : $scope.tabs[0].name });
                        } else if ($scope.tabs[2].canShow()) {
                            $state.go('shopping.referral.tab', { tabName : $scope.tabs[2].name });
                        } else if ($scope.tabs[1].canShow()) {
                            $state.go('shopping.referral.tab', { tabName : $scope.tabs[1].name });
                        }
                    }
                });
        })();

        function getCampaignId() {
            if (!$scope.referralProgram)
                return 0;

            if (!$scope.referralProgram.campaign)
                return 0;

            return $scope.referralProgram.campaign.campaignId;
        }

        $scope.referral = {
            message: "Hello! I am loving the convenience of having farm fresh groceries delivered right to my door through Oberweis’ Home Delivery Service and I know you’ll love it too! Click on the link below to sign up!",
            senderName: "",
            receiverEmail: ""
        };

        $scope.submitReferral = function(referralForm, referral) {
            $scope.submitReferralState.submitClicked = true;
            referral.campaignId = getCampaignId();

            if (referralForm.$invalid)
                return;

            $scope.submitReferralState.loading = true;

            $http.post("/api/referral/send", referral)
                .then(function (referral) {
                    $scope.sentReferrals.pending.push(referral.data);
                    $scope.recentReferralSent = $scope.referral.receiverEmail;
                    $('#referral-sent-modal').modal('toggle')

                    $scope.submitReferralState.loading = false;
                    $scope.submitReferralState.error= false;
                    $scope.submitReferralState.errorMessage = "";
                    $scope.referral.receiverName = "";
                    $scope.referral.receiverEmail = "";
                    referralForm.$setPristine();

                }, function(errorResponse) {
                    $scope.submitReferralState.loading = false;
                    $scope.submitReferralState.error = true;
                    if (errorResponse.data && errorResponse.data.message) {
                        $scope.submitReferralState.errorMessage = errorResponse.data.message;
                    } else {
                        $scope.submitReferralState.errorMessage = "Error sending referral, please try again later."
                    }
                });
        };
    }
})();
;
var controllerId = "referralRedeemController";

(function () {
    "use strict";
    angular.module("app-hd").controller(controllerId, ["$state", "$stateParams", "$scope", "datacontext", "authService",
        "$http", "common", "config", referralController]);


    function referralController($state, $stateParams, $scope, datacontext, authService, $http, common, config) {
        var ctrl = this;

        ctrl.referralProgram = { rewardsAvailable: 0 };
        ctrl.signUpReward = 0;
        ctrl.redeemLoading = false;
        ctrl.getRewardRedeemableAmount = _getRedeemableAmount;
        ctrl.getRedeemedAmount = _getRedeemedAmount;
        ctrl.getRemainingSignupRewards = _getRemainingSignUpRewards;
        ctrl.redeemReward = _redeemReward;
        ctrl.redeemErrorMessage = "";

        // The amount rewards can be applied to
        function _getRewardCanBeAppliedToAmount()
        {
            var totals = datacontext.order.GetNextDeliveryTotals();
            if (!totals)
                return 0;

            return Math.max(totals.subtotal + totals.discount + totals.referralReward, 0);
        }

        function _getRedeemableAmount() {
            return Math.min(ctrl.referralProgram.rewardsAvailable, _getRewardCanBeAppliedToAmount())
        }

        function _getRemainingSignUpRewards()
        {
            var totals = datacontext.order.GetNextDeliveryTotals();
            if (!totals)
                return 0;

            return Math.max(ctrl.signUpReward + totals.referralReward, 0);
        }

        function _getRedeemedAmount() {
            var totals = datacontext.order.GetNextDeliveryTotals();
            if (!totals)
                return 0;

            return totals.referralReward;
        }

        // Redeems the redeemable amount
        function _redeemReward() {
            var amount = _getRedeemableAmount();
            var deliveryDate = datacontext.cust.mycust.nextDeliveryDate;
            ctrl.redeemLoading = true;
            $http.post("/api/referral/redeem", { amount, deliveryDate }).then(function() {
                return datacontext.order.PostOrderDetailUpdate([]);
            }).then(function () {
                ctrl.redeemLoading = false;
                ctrl.redeemErrorMessage = "";
                ctrl.referralProgram = datacontext.cust.mycust.referralProgram;
            }, function (error) {
                if (error.data && error.data.message) {
                    ctrl.redeemErrorMessage = error.data.message
                } else {
                    ctrl.redeemErrorMessage = "An error occurred while redeeming your referral rewards.";
                }
                ctrl.redeemLoading = false;
            });
        }

        (function activate(){
            common.$broadcast(config.events.spinnerToggle, { show: true });

            common.activateController([
                datacontext.primeCustomer().then(function () {
                    var mycust = datacontext.cust.mycust;
                    if (mycust.referralProgram) {
                        ctrl.referralProgram = datacontext.cust.mycust.referralProgram;
                    }
                    if (mycust.signUpReward > 0) {
                        ctrl.signUpReward = mycust.signUpReward;
                    }
                })
            ], controllerId)
        })();
    }
})();
;
(function () {
    "use strict";
    var controllerId = "availabilityController";
    angular.module("app-hd").controller(controllerId, ["$rootScope", "$scope", "$q", "$state", "$stateParams", '$window', "$cookies", "config", "common", "datacontext", "authService", "uiGmapGoogleMapApi", availabilityController]);

    function availabilityController($rootScope, $scope, $q, $state, $stateParams, $window, $cookies, config, common, datacontext, authService, uiGmapGoogleMapApi) {
        //	new customer sign up controller
        var vm = this;
        var setCookie = $scope.$parent.setCookie;
        var getCookie = $scope.$parent.getCookie;
        var PROMO_ADDRESS_COOKIE = "promo_address"

        vm.isApartment = false;
        vm.isPromoPage = false;
        vm.notForSalesRep;
        vm.salesPersonIdRequired;
        vm.referralCode;
        vm.promoPixelCodes = {
            'NEWHOME1': { promoCode: 'NEWHOME1', pixel: '4e38a240-048d-013b-56b8-0cc47a8ffaac' },
            'NEWHOMETX': { promoCode: 'NEWHOMETX', pixel: 'd222ab30-048c-013b-56b8-0cc47a8ffaac' }
        };


        vm.salesPerson = $rootScope.salesPerson;

        vm.init = function (options) {
            vm.isPromoPage = options.isPromoPage;
            vm.notForSalesRep = options.notForSalesRep;
            vm.salesPersonIdRequired = options.onlyForSalesRep;
        }

        $scope.$watch(function () { return $rootScope.salesPerson; }, function () {
            vm.salesPerson = $rootScope.salesPerson;
        });

        vm.formStates = {
            apartmentQuestions: 1,
            incomplete: 2,
            startform: 3,
            nodelivery: 4,
            alreadyHave: 5,
            success: 6,
            error: 7,
            multi: 8,
            welcomeBack: 9
        };

        vm.address = {
            address1: null,
            address2: null,
            emailAddress: null,
            zip: null
        };

        vm.parent = $scope.$parent;

        vm.baseUrl = config.baseUrl;
        vm.submit = _submit;
        vm.submitNoDelivery = _submitNoDelivery;
        vm.names = [];
        vm.confirmName = _confirmName;
        vm.selectedName = '';
        //vm.processAddress = _processAddress;
        //vm.testAddress = _testAddress;

        vm.customerDC = datacontext.cust;
        vm.addressResponse = [];
        vm.markers = [];
        $scope.selectedMarker = null;
        vm.selectedMarkerId = null;
        vm.markerEvents = {
            click: function (gMarker, eventName, marker) {
                vm.selectedMarkerId = marker.id;
            }
        };

        $scope.$watch(function () { return vm.selectedMarkerId }, function (newVal, oldVal) {
            if (newVal != oldVal) {
                $scope.selectedMarker = vm.markers[vm.selectedMarkerId];
            }
        });

        vm.position = { coords: { latitude: 41.79818400000001, longitude: -88.348431 } };
        vm.map = {
            center: { latitude: vm.position.coords.latitude, longitude: vm.position.coords.longitude }
            , zoom: 11
            , options: { scrollwheel: true }
            //, options: { scrollwheel: true, mapTypeId: 'satellite' }
        };

        uiGmapGoogleMapApi.then(function (maps) {
            //

        });

        vm.selectAddress = _selectAddress;

        vm.availability_status = vm.formStates.startform;
        vm.showAptQuestionsModal = false;

        function OpenAPTQuestions() {
            vm.availability_status = vm.formStates.apartmentQuestions;
        };

        // this section is for the apt questions

        vm.state = '';
        $scope.answers = vm.customerDC.aptQuestions;

        $scope.areAllAptQuestionsDone = function () {
            var haveAnswers = true;
            angular.forEach($scope.answers, function (answer) {
                if (answer === null) {
                    return haveAnswers = false;
                }
            });
            return haveAnswers;
        };

        $scope.AreAnswersAcceptable = function () {
            // this checks to see if the apt question are all answered properly
            var correctAnswers = ["No"
                , "Yes"
                , "Yes"
                , "Yes"
                , "No"
                , "Yes"];
            var valid = true;
            angular.forEach($scope.answers, function (answer, key) {
                if (answer !== correctAnswers[key]) {
                    valid = false;
                }
            });
            return valid;
        };

        $scope.items = []; //items;

        $scope.disableApartmentChange = function () {
            if ((vm.state == 'allow') || (vm.state == 'deny')) return true;
            return false;
        }

        $scope.ok = function () {
            if (!$scope.areAllAptQuestionsDone()) return vm.state = "incomplete";
            if (vm.state == 'deny') {
                vm.state = '';
                vm.availability_status = vm.formStates.startform;
                return vm.state;
            }
            vm.state = $scope.AreAnswersAcceptable() ? 'allow' : 'deny';
            $scope.continue();
            return vm.state;
        };

        $scope.continue = function () {
            vm.state = $scope.AreAnswersAcceptable() ? 'allow' : 'deny';
            if (vm.state != 'allow') {
                vm.submit();
            }
            else {
                _submit();
                if (vm.formStates.startform == 3) {
                    //CCF
                    $scope.answers = [""
                        , ""
                        , ""
                        , ""
                        , ""
                        , ""];

                }
                vm.availability_status = vm.formStates.startform;
            }
        };

        $scope.cancel = function () {
            vm.availability_status = vm.formStates.startform;
        };
        // end of the section for apt questions

        vm.isLoaded = false;

        function _submitNoDelivery() {
            vm.customerDC.InsSignupNoDelivery();

            vm.request = {
                address: vm.address.zip,
                oberweisStores: true,
                groceryStores: false
            }

            gotoFindStore(vm.request);
        }

        function gotoFindStore(request) {
            $window.sessionStorage.setItem("findStoreRequest", JSON.stringify(request));
            $window.location = "/search/find-a-store";
        }

        vm.customerDC.setShowOneTimePopup(false);

        function _submit(novalidate, formId) {
            if (formId === undefined) {
                formId = "#homeDeliveryLookUp"
            }
            authService.logOut();
            if (novalidate || (common.validateForm(formId) && !vm.invalidSalesPerson)) {

                //if (location.href.indexOf("promo") > 0 && $state.current.name.indexOf("sign-up") < 0) {
                if (vm.isPromoPage === true) {

                    var url = "/home-delivery/sign-up?"

                    // GOOGLE ANALYTICS (Force page send for the sign-up process)
                    ga('set', 'page', url);
                    ga('send', 'pageview');

                    setCookie(PROMO_ADDRESS_COOKIE, JSON.stringify({
                        address1: vm.address.address1,
                        address2: vm.address.address2,
                        zip: vm.address.zip,
                        emailAddress: vm.address.emailAddress,
                        referralCode: vm.referralCode
                    }));

                    if (vm.promo) {
                        url += "&promo=" + vm.promo;
                    }
                    if (vm.acct) {
                        url += "&acct=" + vm.acct;
                    }
                    if (vm.salesPerson.id) {
                        url += "&sid=" + vm.salesPerson.id;
                    }
                    $window.location = url;

                    return;
                }
                if ($state.current.name === "") {
                    var param = {
                        address1: vm.address.address1,
                        zip: vm.address.zip,
                        emailAddress: vm.address.emailAddress,
                    }
                    var url = "/home-delivery/sign-up?";
                    url = url + "address1=" + param.address1 + "&";
                    if (vm.address.address2) {
                        url = url + "address2=" + param.address2 + "&";
                    }
                    if (vm.promo) {
                        url = url + "promo=" + param.promo + "&";
                    }
                    if (vm.acct) {
                        url = url + "acct=" + param.acct + "&";
                    }
                    url = url + "zip=" + param.zip + "&" + "emailAddress=" + param.emailAddress
                    $window.location = url;
                }
                if ($state.current.name.indexOf("sign-up") < 0) {
                    var param = {
                        address1: vm.address.address1,
                        zip: vm.address.zip,
                        emailAddress: vm.address.emailAddress,
                    }
                    url = url + "address1=" + param.address1 + "&";
                    if (vm.address.address2) {
                        param.address2 = vm.address.address2;
                    }

                    if (vm.promo) {
                        param.promo = vm.promo;
                    }

                    if (vm.acct) {
                        param.acct = vm.acct;
                    }
                   $state.go("sign-up.1", param);

                    return;
                }

                if ((vm.address.address2) && (vm.address.address2.length > 0) && (vm.state != 'allow')) {
                    vm.isApartment = true;
                    OpenAPTQuestions();
                    return;
                }
                if (vm.availability_status == vm.formStates.apartmentQuestions) {
                    vm.customerDC.setShowOneTimePopupApartment(true);
                    vm.customerDC.setShowOneTimePopupHouse(false);
                }
                else {
                    vm.customerDC.setShowOneTimePopupApartment(false);
                    vm.customerDC.setShowOneTimePopupHouse(true);
                }

                datacontext.isNewCustomer = true;

                if (vm.acct) {
                    common.$broadcast(config.events.spinnerToggle, { show: true });

                    datacontext.cust.getNameList(vm.acct)
                        .then(function (names) {
                            vm.names = names;
                            vm.availability_status = vm.formStates.welcomeBack;
                        }, function (error) {
                            console.log(error);
                        }).then(function () {
                            common.$broadcast(config.events.spinnerToggle, { show: false });
                        });

                } else {
                    _testAddress();
                }
            }
        }

        function _confirmName() {
            if (vm.selectedName) {
                //make call to service to check name
                datacontext.cust.confirmCustomerName(vm.acct, vm.selectedName)
                    .then(function (data) {

                        if (data) {
                            datacontext.cust.mycust.customerNumber = vm.acct;
                            datacontext.cust.mycust.isReturning = true;
                            datacontext.isReturning = true;
                        }
                    }, function (error) {
                        console.log(error);
                    })
                    .then(function () {
                        _testAddress();
                    }, function (error) {
                        console.log(error);
                    });
            }
        }

        function _testAddress() {
            datacontext.cust.mycust.address1 = vm.address.address1;
            datacontext.cust.mycust.address2 = vm.address.address2;
            datacontext.cust.mycust.eMail = vm.address.emailAddress;
            datacontext.cust.mycust.zip = vm.address.zip;
            datacontext.cust.mycust.isCurator = vm.isCurator;
            datacontext.cust.mycust.referralCode = vm.referralCode;

            common.$broadcast(config.events.spinnerToggle, { show: true });

            datacontext.cust.TestMyCustomerAddress()
                .then(function (resolve) {
                    datacontext.primeCustomerPromise = $q.defer();
                    _processAddress(resolve);

                }, function (error) {
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });
        }

        function _selectAddress() {

            if (vm.selectedMarkerId == -1) {
                alert("Please contact customer service.");
                return;
            }

            //send selected address to server
            datacontext.cust.ProcessAddress(vm.addressResponse[vm.selectedMarkerId]).then(function (resolve) {
                _processAddress(resolve);
            }, function (error) {
                console.log(error);
            });
        }

        function _processAddress(resolve) {
            common.$broadcast(config.events.spinnerToggle, { show: true });
            var noError = false;
            if (resolve.message == 'noService') {
                console.log("Do not deliver to address.");
                vm.availability_status = vm.formStates.nodelivery;
                //vm.message = "This address is invalid.";
            } else if (resolve.message === "currentCustomer") {
                console.log("Address belongs to current customer.");
                vm.availability_status = vm.formStates.alreadyHave;
                vm.parent.vm.isAlreadyHave = true;
            } else if (resolve.message === "badAddress") {
                console.log("This is not a valid address.");
                vm.message = "This address is invalid.";
            } else if (resolve.message === "multi") {
                vm.availability_status = vm.formStates.multi;
                vm.addressResponse = resolve.addressResponse;

                $.each(vm.addressResponse, function (i, a) {
                    vm.markers.push({
                        id: i
                        , coordinates: { latitude: a.address.latitude, longitude: a.address.longitude }
                        , addressResponse: a
                        , options: { labelClass: 'map-marker-label', labelAnchor: '-12 40', labelContent: i + 1 }
                    });
                });
            } else {
                noError = true;
            }
            if (noError) {
                datacontext.cust.mycust.eMail = vm.address.emailAddress;
                datacontext.cust.putItemsLoaded("custId", datacontext.cust.mycust.id);
                datacontext.category.productViewName = null;
                datacontext.category.isLoaded = false;
                datacontext.primeProducts(true);
                datacontext.cust.mycust.isCurator = vm.isCurator;

                $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
                    if (oldVal) {
                        vm.customer = datacontext.cust.mycust;
                        if (vm.salesPerson.id) {
                            vm.customer.salesPersonId = vm.salesPerson.id;
                        }
                    }
                });

                datacontext.promotion.applyPromotion(vm.promo).then(
                    function (promo) {
                        if (promo != null) {
                            datacontext.cust.mycust.promoCode = promo;
                            datacontext.cust.mycust.hasDeliveryDiscount = promo.hasDeliveryDiscount;
                            datacontext.cust.mycust.hasDollarsOffDiscount = promo.hasDollarsOffDiscount;
                            datacontext.cust.mycust.hasFirstTasteDiscount = promo.hasFirstTasteDiscount;
                            datacontext.cust.mycust.hasGraduatedDiscount = promo.hasGraduatedDiscount;

                            datacontext.cust.mycust.slidingDeliveryDiscountTarget = promo.slidingDeliveryDiscountTarget;
                            datacontext.cust.mycust.slidingDollarsOffDiscountTarget = promo.slidingDollarsOffDiscountTarget;
                            datacontext.cust.mycust.slidingGraduatedDiscountTarget = promo.slidingGraduatedDiscountTarget;
                            datacontext.cust.mycust.dollarOffAmountFormatted = promo.dollarOffAmountFormatted;

                            datacontext.hideOneTimeDeliveryDiscountModal = true;
                        }
                    },
                    function (error) {
                        //console.log(error);
                    }).then(function () {
                        vm.startShopping();
                        datacontext.primeCustomerPromise.resolve(resolve);
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    }, function (error) {
                        //console.log(error);
                    });
                //vm.availability_status = vm.formStates.success;
            } else {
                common.$broadcast(config.events.spinnerToggle, { show: false });
            }

        }

        vm.centerMap = function () {
            var marker = vm.markers[vm.selectedMarkerId];
            vm.map.center.latitude = marker.coordinates.latitude;
            vm.map.center.longitude = marker.coordinates.longitude;
            vm.map.zoom = 18;
        }

        vm.startShopping = function () {
            vm.parent.vm.ChangeTo("2");
        }

        function resetCustomer() {
            datacontext.cust.reset();
            datacontext.order.ResetOrderItems();
            datacontext.primeCustomerPromise = undefined;
        }
        function insertPromoPixel(uuid) {
            var s = document.createElement("script");
            s.type = "text/javascript";
            s.src = "https://tag.simpli.fi/sifitag/" + uuid;
            document.getElementsByTagName('head')[0].appendChild(s);
        }

        activate();
        function activate() {
            vm.products = datacontext.products.entityItems;
            resetCustomer();
            //datacontext.isNewCustomer = true;
            datacontext.cust.NewCustomerInProcess = true;
            common.activateController([], controllerId).then(function (data) {
                
                if ($state.params.curator === 'true') {
                    vm.isCurator = true;
                }

                var promoAddressCookie = getCookie(PROMO_ADDRESS_COOKIE)
                var promoAddressCookieData = {};
                if (promoAddressCookie) {
                    promoAddressCookieData = JSON.parse(promoAddressCookie);
                }

                if (($state.params.address1) && ($state.params.address1.length > 0)) {
                    vm.address.address1 = $state.params.address1;
                } else if (promoAddressCookieData.address1 && promoAddressCookieData.address1.length > 0) {
                    vm.address.address1 = promoAddressCookieData.address1;
                }

                if (($state.params.address2) && ($state.params.address2.length > 0)) {
                    vm.address.address2 = $state.params.address2;
                } else if (promoAddressCookieData.address2 && promoAddressCookieData.address2.length > 0) {
                    vm.address.address2 = promoAddressCookieData.address2;
                }

                if (($state.params.zip) && ($state.params.zip.length > 0)) {
                    vm.address.zip = $state.params.zip;
                } else if (promoAddressCookieData.zip && promoAddressCookieData.zip.length > 0) {
                    vm.address.zip = promoAddressCookieData.zip;
                }

                if (($state.params.emailAddress) && ($state.params.emailAddress.length > 0)) {
                    vm.address.emailAddress = $state.params.emailAddress;
                } else if (promoAddressCookieData.emailAddress && promoAddressCookieData.emailAddress.length > 0) {
                    vm.address.emailAddress = promoAddressCookieData.emailAddress;
                }

                if (promoAddressCookieData.referralCode && promoAddressCookieData.referralCode.length > 0) {
                    vm.referralCode = promoAddressCookieData.referralCode;
                }

                // The cookie should only be used one time.
                setCookie(PROMO_ADDRESS_COOKIE, "{}");

                if (($state.params.promo) && ($state.params.promo.length > 0)) {
                    vm.promo = $state.params.promo;
                    if (vm.promo && vm.promoPixelCodes[vm.promo]) {
                        insertPromoPixel(vm.promoPixelCodes[vm.promo].pixel);
                    }
                }
                if (($state.params.acct) && ($state.params.acct.length > 0)) {
                    vm.acct = $state.params.acct;
                }
                if (($state.params.referralCode) && ($state.params.referralCode.length > 0)) {
                    vm.referralCode = $state.params.referralCode;
                }

                if (vm.address.address1 && vm.address.zip && vm.address.emailAddress) {
                    _submit(true);
                }
            });

        }
    }
})();
;
(function () {
    "use strict";
    var controllerId = "signupBaseController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$state", "$cookies", "authService", "config", "common", "datacontext", "googleAnalytics", signupBaseController]);

    function signupBaseController($scope, $state, $cookies, authService, config, common, datacontext, googleAnalytics) {
        //
        //	new customer signup controller
        //
        var $q = common.$q;
        var vm = this;
        vm.isAlreadyHave = false;
        vm.intstep = 1;

        $scope.isSales = true;
        $scope.getSeoMetadata('sign-up', 7);

        vm.salesId = $cookies.get("salesId");
        if ($state.params.salesId && ($state.params.salesId.length > 0)) {
            vm.salesId = "" + ($state.params.salesId) ? $state.params.salesId : "";
            var expireDate = new Date();
            expireDate.setDate(expireDate.getDate() + 14);
            $cookies.put("salesId", vm.salesId, { 'expires': expireDate });
        }

        if (vm.salesId) {
            datacontext.cust.salesPersonId = vm.salesId;
            var salesIdprts = datacontext.cust.salesPersonId.split('=');
            if (salesIdprts.length > 1) {
                datacontext.cust.salesPersonId = salesIdprts[1];
            }
        }

        if (!datacontext.cust.salesAdding) {
            vm.salesAdding = datacontext.cust.salesAdding = ($state.current.name.toLowerCase().indexOf('sales') >= 0);
        }
        vm.isActiveStep = _isActiveStep;
        $scope.isActiveStep = _isActiveStep;
        vm.ChangeTo = changeTo;
        vm.NavigateToNext = navigateToNext;
        vm.resetApp = resetApp;

        vm.ChangeToThenBack = ChangeToThenBack;

        function ChangeToThenBack(demandStep, rtrnStep, subStep) {
            subStep = subStep ? subStep : "";
            datacontext.cust.mycust.startupStep = "" + demandStep;
            datacontext.cust.rtrn = rtrnStep;
            $state.go("^." + datacontext.cust.mycust.startupStep + subStep);
        };

        function changeTo(destinationStep, params) {
            //

            datacontext.cust.mycust.startupStep = "" + destinationStep;
            datacontext.cust.mycust.int_custStep = parseInt(destinationStep);

            // this bases the next url on how deep the current url is.
            var prts = $state.current.name.split('.');
            var nurl = prts[0] + ".";
            //  for (var inx = 1; inx < prts.length; inx++) nurl += "^.";

            nurl += datacontext.cust.mycust.startupStep;

            if (nurl != null) {
                if (nurl.indexOf('sign-up.') !== -1) {

                    // GOOGLE ANALYTICS (Force page send for the sign-up process)
                    var url = $state.$current.url.sourcePath;

                    if (url == "/home-delivery/sign-up") {
                        if (destinationStep == "2") {
                            url = url + '/shopping/category/products/dairy';
                        }
                    }

                    ga('set', 'page', url);
                    ga('send', 'pageview');
                }
            }


            if (datacontext.cust.mycust.startupStep == 2) {
                if ($state.current.name.indexOf("sales") >= 0) {
                    nurl = "sign-up.2";
                }
                nurl += "." + "category";
                vm.intstep = datacontext.cust.mycust.int_custStep;
                $state.go(nurl, { productViewId: 'products' });
                return;
            }

            vm.intstep = datacontext.cust.mycust.int_custStep;

            datacontext.cust.updateStepNumber();

            $state.go(nurl, params);
        };

        function navigateToNext(event_name, event_data) {

            if (event_name && event_data) {
                googleAnalytics.push(event_name, event_data);
            }
            var nextstep = parseInt($state.$current.name.split(".")[1]) + 1;
            if (datacontext.cust.rtrn) {
                nextstep = parseInt(datacontext.cust.rtrn);
                datacontext.cust.rtrn = "";
            }
            changeTo(nextstep);
        };
        function resetApp() {
            datacontext.reset();

            datacontext.saveAppDataState();
            vm.intstep = 1;
            datacontext.cust.putItemsLoaded("custId", null);

            var prts = $state.current.name.split('.');
            var nurl = "";
            for (var inx = 1; inx < prts.length; inx++) nurl += "^.";
            return;
        };

        activate();
        function activate() {
            if (($state.params.promo) && ($state.params.promo.length > 0)) {
                datacontext.cust.promoCode = $state.params.promo;
            }

            if (($state.params.acct) && ($state.params.acct.length > 0)) {
                datacontext.cust.customerNumber = $state.params.acct;
                datacontext.cust.isReturning = true;
            }

            if ($state.$current.name.split(".").length == 1) {
                //$state.go('sign-up.1');
                $state.go($state.$current.name + '.1');
            }
            onDestroy();
            //
            //	this code will run only once throughout the sign up of a new customer
            //
            if (authService.authentication.isAuth) {

                if (datacontext.cust.mycust != null && !datacontext.cust.mycust.incompleteCustomerSignup) {
                    authService.logOut();
                    datacontext.isNewCustomer = true;
                }

                //if ((datacontext.cust.mycust == null) && ($state.$current.name != 'sign-up')) {
                //    $state.go('sign-up.1');
                //    return false;
                //}

                if (datacontext.cust.mycust) {
                    if ((datacontext.cust.mycust) && (!datacontext.cust.mycust.nextDeliveryDate && datacontext.cust.mycust.order && datacontext.cust.mycust.order[0]))
                        datacontext.cust.mycust.nextDeliveryDate = datacontext.cust.mycust.order[0].deliveryDate;

                    if (!datacontext.cust.mycust.EOW)
                        datacontext.cust.mycust.EOW = 0;

                    vm.intstep = datacontext.cust.mycust.int_custStep;
                    if ((datacontext.cust.mycust.startupStep) && ($state.$current.name.split(".")[1] !== datacontext.cust.mycust.startupStep))
                        vm.ChangeTo(datacontext.cust.mycust.startupStep);
                }
            }
        }

        function onDestroy() {
            //
            //  this should fire when we leave the new customer process
            //
            //$scope.$on('$destroy', function () {
            //    datacontext.isNewCustomer = false;
            //});
        }

        function _isActiveStep(step) {
            return $state.$current.name.split(".")[1] == step;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "contactInfoController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$rootScope", "$state", "common", "datacontext", "authService", contactInfoController]);

    function contactInfoController($scope, $rootScope, $state, common, datacontext, authService) {
        var vm = this;
        vm.datacontext = datacontext;

        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;

        vm.isAuth = authService.authentication.isAuth;
        vm.continueButtonClicked = _continueButtonClicked;
        vm.passwordError = [];
        vm.userError = [];
        vm.errorMessage = "";
        vm.customerSourceTypes = [];

        vm.salesPersonPlaceholder = "Sales Person ID";
        if (!$rootScope.salesPersonAdding) {
            vm.salesPersonPlaceholder += " (Optional)";
        }
        vm.salesPersonOptions = { required: false };

        vm.salesPerson = $rootScope.salesPerson;

        $scope.$watch(function () { return $rootScope.salesPerson; }, function () {
            vm.salesPerson = $rootScope.salesPerson;
        });

        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        }

        vm.isUserAccountCreated = function () {
            return (datacontext.cust
                && datacontext.cust.mycust
                && datacontext.cust.mycust.aspNetUserId
                && (datacontext.cust.mycust.aspNetUserId != null
                || datacontext.cust.mycust.aspNetUserId != undefined));
        }

        function _continueButtonClicked() {
            if (common.validateForm("#signUpCreateAccount")) {

                if (!vm.isUserAccountCreated()) {

                    var registration = {
                        CustomerId: vm.customer.id,
                        Email: vm.customer.eMail,
                        Phone: vm.customer.phone,
                        userName: vm.customer.userName,
                        isSalesPerson: vm.customerDC.mycust.isSalesAdding,
                        password: vm.customer.password,
                        confirmPassword: vm.customer.password,
                        newPassword: vm.customer.password,
                        salesPersonId: vm.salesPerson.id,
                        customerSourceId: vm.customer.customerSourceId

                    };
                    datacontext.cust.mycust.salesPersonId = vm.salesPerson.id;
                    datacontext.cust.mycust.customerSourceId = vm.customer.customerSourceId;

                    //create user here
                    authService.saveRegistration(registration)
                        .then(function (response) {
                            //$scope.loginData.userName = $scope.registration.userName;
                            //$scope.loginData.password = $scope.registration.password;
                            datacontext.cust.mycust.aspNetUserId = response.userId;
                            datacontext.cust.mycust.incompleteCustomerSignup = true;
                            $scope.savedSuccessfully = true;
                            vm.customer.savedSuccessfully = true;
                            //$scope.Message = "User has been registered successfully, you will be logged in and redirected to the Market place page in 2 seconds.";
                            //$timeout($scope.redirectUserToLogin, 2000);

                            //if user is created preceed with customer
                            insSignupNoComplete();
                        },
                            function (error) {
                                vm.errorMessage = common.handleError(error);
                            },
                            function (other) {
                            });
                }
                else {
                    insSignupNoComplete();
                }
            }
        };
        vm.clearValidationMessages = function () {
            vm.errorMessage = "";
        }

        function insSignupNoComplete() {
            datacontext.cust.InsSignupNoComplete()
                .then(function () {
                    var event_name = 'signup_step_5_complete';
                    var event_data = {
                        customerId: datacontext.cust.mycust.id,
                        email: datacontext.cust.mycust.eMail,
                        state: datacontext.cust.mycust.state,
                        zip: datacontext.cust.mycust.zip,
                        nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                        porchBox: datacontext.cust.mycust.porchBox,
                        firstName: datacontext.cust.mycust.firstName,
                        lastName: datacontext.cust.mycust.lastName,
                        promoCode: datacontext.cust.mycust.promoCode


                    };
                    vm.navigateToNext(event_name, event_data);
                });
        }

        activate();

        function activate() {
            if (datacontext.isNewCustomer) {
                if ((datacontext.cust.mycust == null) && ($state.$current.name.indexOf('sign-up.1') < 0)) {
                    $state.go('sign-up.1', null, { reload: true });
                    return;
                }
            }
            common.activateController([], controllerId)
                .then(function () {
                    datacontext.customer_source.primeCustomerSourceTypes().then(function () {
                        vm.customerSourceTypes = datacontext.customer_source.entityItems;
                    });

                    datacontext.primeCustomer().then(function () {
                        vm.customer = datacontext.cust.mycust;

                        common.validateCustomerNumber(vm.customer.customerNumber);
                        if (vm.customer) {
                            vm.customer.customerNotificaitonPreferences = {
                                deliveryReminders: true,
                                smsDeliveryReminders: true,
                                postDeliveryNotifications: true,
                                smsDeliveryNotifications: true,
                                smsMarketingMessages:true
                            };
                        }

                        vm.salesAdding = datacontext.cust.mycust.isSalesAdding;
                        vm.customerDC = datacontext.cust;

                        if (vm.customer.stdAddress != null) {
                            vm.customer.addressLine1 = vm.customer.stdAddress.standardizedStreet;
                            vm.customer.city = vm.customer.stdAddress.standardizedCity;
                            vm.customer.state = vm.customer.stdAddress.standardizedState;
                            vm.customer.zipCode = vm.customer.stdAddress.standardizedZipCode;
                            vm.customer.county = vm.customer.stdAddress.county;
                            //vm.customer.porchBoxItems = vm.customer.stdAddress.route.porchBoxItems;
                        }

                    });

                });
        }

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "deliveryDateController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$filter", "common", "datacontext", deliveryDateController]);

    function deliveryDateController($scope, $filter, common, datacontext) {
        var vm = this;

        var showMoreDatesTxt = 'Show More Dates...';
        var firstPossibleDate;

        vm.DeliveryTime = {};

        vm.possibleDates = [];

        vm.DeliveryDate = {};
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;
        vm.continueButtonClicked = continueButtonClicked;

        function continueButtonClicked() {
            var event_name = 'signup_step_3_complete';
            var eventData = {
                customerId: datacontext.cust.mycust.id,
                email: datacontext.cust.mycust.eMail,
                state: datacontext.cust.mycust.state,
                zip: datacontext.cust.mycust.zip,
                nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate
            };
            vm.navigateToNext(event_name, eventData);
        }

        $scope.dateOptionSelected = dateOptionSelected;


        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        }

        function dateOptionSelected(selectedDate) {
            /* This function relies on moment being set to the local time.  
               If you select 7/14/2023 00:00:00 and you're Eastern Time Zone, 
               it converts to Central Time Zone, the time will become 7/13/2023 23:00:00.
             */
            moment.tz.setDefault();
            
            vm.DeliveryDate.text = selectedDate;
            vm.DeliveryDate.value = new Date(selectedDate);
            var offsetMoment = moment(vm.DeliveryDate.text);

            datacontext.cust.mycust.nextDeliveryDate = offsetMoment.format('YYYY-MM-DDTHH:mm');
            if (vm.DeliveryDate == showMoreDatesTxt) {
                var howManyMore = vm.possibleDates.length - 1 + 4;
                loadDates(howManyMore);
                vm.DeliveryDate = firstPossibleDate;
            }
            datacontext.order.updateDeliveryDate();
        }

        function loadDates(numberOfDatesToLoad) {

            vm.possibleDates = common.possibleDates(numberOfDatesToLoad, datacontext.cust.mycust.nextDeliveryDate, datacontext.cust.mycust.deliveryDay, datacontext.cust.mycust.EOW);
            if (firstPossibleDate == null) {
                firstPossibleDate = datacontext.cust.mycust.nextDeliveryDate;
            }
            //don't show showMoreDatesTxt until otherwise told to do so...
            //vm.possibleDates.push({ value: showMoreDatesTxt, text: showMoreDatesTxt });
        }

        activate();

        function activate() {

            datacontext.primeCustomer().then(function () {

                vm.EOW = datacontext.cust.mycust.EOW;
                vm.customer = datacontext.cust.mycust;

                common.validateCustomerNumber(vm.customer.customerNumber);

                if (datacontext.isNewCustomer) {
                    if ((datacontext.cust.mycust == null) && ($state.$current.name.indexOf('sign-up.1') < 0)) {
                        $state.go('sign-up.1', null, { reload: true });
                        return;
                    }
                }
                common.activateController([], controllerId)
                    .then(function () {
                        loadDates(8);
                        //Fraud Prevention: do not allow new customers to select tommorrow as their first delivery
                        //removing this check once $110 limit for first order is live
                        //if (datacontext.isNewCustomer) {
                        //    if (vm.possibleDates[0].Date == moment().add(1, 'days').Date) {
                        //        vm.possibleDates.shift();
                        //    }
                        //}

                        var offsetMoment = moment(vm.possibleDates[0].text);
                        //datacontext.cust.mycust.nextDeliveryDate = offsetMoment.format('YYYY-MM-DDTHH:mm');

                        setCurrentDate(datacontext.cust.mycust.nextDeliveryDate);
                        vm.DeliveryTime = datacontext.cust.mycust.deliveryTime;
                    });
            });
        }

        function setCurrentDate(targetDate) {
            var targetMoment = moment(targetDate);
            targetMoment = moment(targetMoment.format('L'));

            vm.DeliveryDate = vm.possibleDates[0];
            vm.possibleDates.forEach(function (possDate) {
                var possDateMoment = moment(possDate.text);

                if (possDateMoment.isSame(targetMoment))
                    vm.DeliveryDate = possDate;
            });
        }


        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "lookUpAccountController";
    angular.module("app-hd").controller(controllerId, ["$timeout", "$stateParams", "$http", "$cookies", "$q", "$scope", "$state", "$location", "$window", "config", "common", "datacontext", "authService", lookUpAccountController]);

    function lookUpAccountController($timeout, $stateParams, $http, $cookies, $q, $scope, $state, $location, $window, config, common, datacontext, authService) {
        //
        //	new customer signup controller
        //

        var vm = this;
        vm.baseUrl = config.baseUrl;
        vm.title = "New Customer Setup";
        vm.canSubmit = true;
        vm.customerDC = datacontext.cust.mycust;
        vm.cust = datacontext.cust;
        vm.baseUrl = config.baseUrl;
        $scope.savedSuccessfully = false;
        $scope.Message = "";
        $scope.userNameMessage = '';
        $scope.authentication = authService.authentication;
        vm.userLookupError = false;
        vm.nameInUseError = false;
        vm.accountIdError = false;
        vm.emailNotFoundError = false;
        vm.customerFound = false;
        vm.userFound = false;

        vm.resetUser = false;


        $scope.$watch(function () { return datacontext.cust.mycust }, function (oldVal, newVal) {
            if (oldVal) {
            }
        });


        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        }

        vm.clearErrors = function () {
            //oRequestAnimationFrame.userLookupError = false;
            vm.nameInUseError = false;
            vm.accountIdError = false;
        }
        $scope.doesUserNameExist = function () {
            vm.cust.doesUserNameExist($scope.registration.userName)
                .then(function (response) {
                    if (response.data == true) {
                        $scope.registration.passwordChangeMessage = "Username is not unique, please use another.";
                    } else
                        $scope.registration.passwordChangeMessage = '';
                }, function (response) {
                    $scope.Message = "We did not find your account."; // + errors.join(" ");
                });
        };

        $scope.validateUserId = function () {
            vm.cust.lookupCustomer()
                .then(function (response) {
                    if (vm.cust.mycust.id !== null) {
                        $scope.Message = "";
                        $state.go("^." + "9");
                    } else {
                        $scope.Message = "We did not find your account."; // + errors.join(" ");
                    }
                    ;
                }, function (response) {
                    $scope.Message = "We did not find your account."; // + errors.join(" ");
                });
        };
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;

        $scope.lookUpCustomer = function () {
            if (common.validateForm("#contactInfo")) {
                datacontext.cust.mycust.lastName = vm.customerDC.lastName;
                datacontext.cust.mycust.phone = vm.customerDC.phone;
                datacontext.cust.mycust.zipCode = vm.customerDC.zipCode;
                vm.cust.lookupCustomer()
                    .then(function (response) {
                        //self.setShowOneTimePopup(true);
                        if (response.aspNetUserId == null) {
                            goToCustomerFound();
                        } else {
                            goToUserFound(response.userName);
                        };
                        return;
                    },
                        function (error) {
                            vm.emailNotFoundError = false;

                            if (error.data && error.data.message) {
                                if (error.data.message == "NoOrder") {
                                    vm.orderLookupError = true
                                }
                                else if (error.data.message == "IncompleteStart") {
                                    vm.IncompleteStartError = true;
                                }
                                else {
                                    vm.emailNotFoundError = true;
                                }
                            }
                            else {
                                vm.userLookupError = true;
                            }
                        }
                )
            }
        };

        $scope.lookUpCustomerByEmail = function () {
            if (common.validateForm('#emailLookup')) {
                $scope.Message = "";
                datacontext.cust.mycust.email = vm.customerDC.email;
                vm.cust.lookupCustomerByEmail()
                    .then(function (response) {
                        console.log(response)
                        //self.setShowOneTimePopup(true);
                        if (response.aspNetUserId == null) {
                            goToCustomerFound()
                        } else {
                            goToUserFound(response.userName);
                        };
                        return;
                    },
                        function (response) {
                            if (response.data && response.data.message) {
                                if (response.data.message == "NoOrder") { 
                                vm.orderLookupError = true
                                }
                                else if (response.data.message == "IncompleteStart") {
                                    vm.IncompleteStartError = true;
                                }
                                else {
                                    vm.emailNotFoundError = true;
                                }
                            }
                            else {
                                vm.emailNotFoundError = true;
                            }
                        }
                )
            }
        };

        function goToCustomerFound() {
            vm.emailNotFoundError = false;
            vm.userLookupError = false;
            vm.customerFound = true;
        }
        function goToUserFound(userName) {
            vm.customerDC.userName = datacontext.cust.mycust.userName = userName;
            vm.emailNotFoundError = false;
            vm.userLookupError = false;
            vm.userFound = true;
        }
        $scope.signUp = function () {
            if (common.validateForm("#registerAccount") && $scope.validatePassword()) {
                $scope.registration.customerId = datacontext.cust.mycust.Id;
                $scope.registration.customerNumber = datacontext.cust.mycust.customerNumber;
                $scope.registration.NewPassword = $scope.registration.confirmPassword;
                $scope.registration.resetUser = vm.resetUser;
                datacontext.cust.as400Refresh = true;

                $scope.registration.passwordChangeMessage = '';

                authService.saveRegistration($scope.registration)
                    .then(function (response) {
                        $scope.loginData.userName = $scope.registration.userName;
                        $scope.loginData.password = $scope.registration.password;
                        vm.enroll_success = $scope.savedSuccessfully = true;
                        $scope.Message = "Your account has been registered successfully. You will be redirected to the log in page in 2 seconds.";
                        $timeout(function () { $state.go('sign-in', null); }, 2000);
                    }, function (error) {
                        $scope.registration.passwordChangeMessage = common.handleError(error);
                    });
            }
        };


        $scope.clearValidationMessages = function () {
            $scope.Message = "";
        }

        $scope.resetUser = function () {
            if (common.validateForm("#registerAccount") && $scope.validatePassword()) {
                $scope.registration.customerId = vm.customer.id;
                $scope.registration.userId = vm.customer.aspNetUserId;
                $scope.registration.customerNumber = vm.customer.customerNumber;
                $scope.registration.NewPassword = $scope.registration.confirmPassword;
                $scope.registration.resetUser = vm.resetUser;
                $scope.registration.passwordResetToken = $location.search().token;

                authService.resetUser($scope.registration)
                    .then(function (response) {
                        $scope.loginData.userName = $scope.registration.userName;
                        $scope.loginData.password = $scope.registration.password;
                        vm.enroll_success = $scope.savedSuccessfully = true;
                        //$scope.Message = "User has been registered successfully, you will be logged in and redirected to the Market place page in 2 seconds.";
                        //$timeout($scope.redirectUserToLogin, 2000);
                        $scope.Message = "Your account has been registered successfully. You will be redirected to the log in page in 2 seconds.";
                        $timeout(function () { $state.go('sign-in', null); }, 2000);
                    }, function (error) {
                        $scope.Message = common.handleError(error);
                    });
            }
        };

        $scope.validatePassword = function () {
            //
            //  this is used by the password section to control the color of the result Message
            //
            var error = '';
            if ($scope.registration.password !== '' && $scope.registration.confirmPassword !== '')
                error = "Password and confirmation password do not match.";
            if ($scope.registration.password != $scope.registration.confirmPassword) {
                $scope.registration.passwordChangeMessage = error;
            } else {
                if ($scope.registration.passwordChangeMessage == error) {
                    $scope.registration.passwordChangeMessage = "";
                }
            }

            if ($scope.registration.passwordChangeMessage) {
                return false;
            }
            return true;
        };


        $scope.registration = {
            userName: "",
            password: "",
            confirmPassword: "",
            customerId: "",
            securityAnswer: "",
            securityQuestion: ""
        };

        $scope.loginData = {
            userName: "testuser",
            password: "testuser",
            useRefreshTokens: false
        };

        $scope.Message = "";

        $scope.login = function () {
            datacontext.resetAllData();

            authService.login($scope.loginData)
                .then(function () {
                    common.dc.cust.NewCustomerStep = '0';
                    common.dc.cust.setShowOneTimePopup(true);
                    //$state.go('sign-in', null);
                    //return;
                    $window.location = '/';
                },
                function (err) {
                    $scope.Message = "err.error_description";
                });
        };

        // Calls the login function
        $scope.redirectUserToLogin = function () {
            $scope.login();
        };


        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }

        activate();
        function activate() {
            //
            //
            //
            //datacontext.reset();
            vm.isLoaded = false;
            datacontext.isNewCustomer = false;
            datacontext.cust.mycust = datacontext.cust.getEmptyCust();
            datacontext.cust.mycust.startupStep = 1;
            datacontext.cust.mycust.int_custStep = 1;
            vm.customer = datacontext.cust.mycust;

            var cidParam = $location.search().cid;

            if (cidParam) {
                common.activateController([datacontext.cust.lookupCustomerById(cidParam)], controllerId)
               .then(function (data) {

                   vm.customer = angular.copy(datacontext.cust.mycust);
                   if (datacontext.cust.mycust.id !== null) {
                       $scope.registration.customerId = datacontext.cust.mycust.id;
                       datacontext.isNewCustomer = false;
                       datacontext.isReturning = false;

                       //$scope.registration.customerId = datacontext.cust.mycust.id;
                       // this is where a cust id can be used to create a uid use the convention =>  /LookUpAccount//1?cid=217
                       vm.resetUser = true;
                       $scope.Message = "";
                       //$state.go("^." + "9");
                   } else {
                       $scope.Message = "We did not find your account."; // + errors.join(" ");
                   }
               });
            } else {
                common.activateController([], controllerId)
               .then(function (data) {
                   if (authService.authentication.isAuth) {
                       //$state.go("^." + "2");
                   }
               });
            }
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "paymentController_signup";
    angular.module("app-hd").controller(controllerId, ['$http', '$q', '$location', '$state', "$scope", "$sce", "$window", "config", "common", "datacontext", paymentController_signup]);

    function paymentController_signup($http, $q, $location, $state, $scope, $sce, $window, config, common, datacontext) {
        //
        //	new customer deliveryDate controller
        //

        var vm = this;
        vm.checkedValue = false;
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;
        vm.ChangeToThenBack = $scope.$parent.vm.ChangeToThenBack;
        vm.paymentIframe = {};

        vm.continueButtonClicked = continueButtonClicked;
        vm.setPaymentType = setPaymentType;

        vm.salesAdding = false;
        //vm.setPaymentMethod = setPaymentType;
        function continueButtonClicked(noValidate) {
            if (common.validateForm("#checkingForm") && vm.validateChecking()) {
                enrollPaymentType();
            }
        }

        vm.lookupPaymentMethod = function () {

            vm.lookupNotFound = false;

            if (common.validateForm("#lookupForm")) {
                return $http.get("api/payments/LookupPaymentMethod/" + vm.lookup.phone + '/' + vm.lookup.creditCard)
                    .then(function (result) {
                        var data = result.data;

                        if (data) {
                            //vm.enroll_success = true;

                            datacontext.cust.mycust.paymentMethod = "Credit Card";
                            datacontext.cust.mycust.creditCard = data.creditCard;
                            datacontext.cust.mycust.expireMonth = data.expireMonth;
                            datacontext.cust.mycust.expireYear = data.expireYear;
                            datacontext.cust.mycust.payerId = data.payerId;

                            initialPaymentdata = {
                                billCode: "10",
                                paymentMethod: datacontext.cust.mycust.paymentMethod,
                                creditCard: datacontext.cust.mycust.creditCard,
                                expireMonth: datacontext.cust.mycust.expireMonth,
                                expireYear: datacontext.cust.mycust.expireYear,
                                accountNumber: datacontext.cust.mycust.accountNumber,
                                routingNumber: datacontext.cust.mycust.routingNumber,
                                zip: datacontext.cust.mycust.zip,
                            };

                            angular.copy(initialPaymentdata, vm.paymentMethod);
                            vm.customer = datacontext.cust.mycust;
                            vm.paymentIframeUrl = "";
                            //calling FB Pixel 
                            var event_name = 'signup_step_6_complete';
                            var event_data = {
                                customerId: datacontext.cust.mycust.id,
                                email: datacontext.cust.mycust.eMail,
                                state: datacontext.cust.mycust.state,
                                zip: datacontext.cust.mycust.zip,
                                nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                                porchBox: datacontext.cust.mycust.porchBox,
                                firstName: datacontext.cust.mycust.firstName,
                                lastName: datacontext.cust.mycust.lastName,
                                promoCode: datacontext.cust.mycust.promoCode


                            };
                            fbq('track', 'AddPaymentInfo', {
                                city: datacontext.cust.mycust.city,
                                state: datacontext.cust.mycust.state,
                                zip: datacontext.cust.mycust.zipCode,
                                phone: datacontext.cust.mycust.phone,
                                email: datacontext.cust.mycust.eMail
                            });

                            vm.navigateToNext(event_name, event_data);
                        }
                        else {
                            vm.lookupNotFound = true;
                        }

                    },
                        function (err) {
                            console.log(err);
                        });
            }
        };


        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        };


        vm.LookupBankName = _LookupBankName;
        vm.isPaymentTypeActive = isPaymentTypeActive;

        vm.continueButtonClicked = continueButtonClicked;
        vm.paymentMethod = { paymentType: '' };
        vm.expireYearOptions = [];
        vm.enroll_Message = "";

        vm.getYearRange = function () {
            var expireYearOptions = [];

            var dt = new Date();

            for (var i = 0; i < 12; i++) {
                expireYearOptions.push(i + dt.getFullYear());
            }
            return expireYearOptions;
        }


        function setPaymentType() {
            if (!(vm.paymentMethod.paymentMethod === 'Credit Card' && vm.enroll_success)) {
                vm.editCreditCard();
            }
            datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod;
        }

        function isPaymentTypeActive(paymentType) {
            return vm.paymentMethod.paymentMethod === paymentType;
        }

        var initialPaymentdata = {
            billCode: "11",
            bankName: '',
            paymentMethod: "Checking",
            creditCard: '',
            expireMonth: null,
            expireYear: null,
            accountNumber: '',
            routingNumber: '',
            zip: ''
        };

        function enrollPaymentType() {
            //
            //	performed after the information is entered into the text box
            //
            vm.enroll_Message = "";
            vm.paymentMethod.billCode = (vm.paymentMethod.PaymentMethod == "Checking") ? "11" : "10";
            var defer = $q.defer();

            datacontext.cust.mycust.paymentType = vm.paymentMethod.paymentMethod;
            datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod;


            if (vm.paymentMethod.paymentMethod == 'Checking') {
                datacontext.cust.mycust.bankName = vm.paymentMethod.bankName;
                datacontext.cust.mycust.accountNumber = vm.paymentMethod.accountNumber;
                datacontext.cust.mycust.routingNumber = vm.paymentMethod.routingNumber;
                datacontext.cust.mycust.creditCard = ''
                datacontext.cust.mycust.expireMonth = '';
                datacontext.cust.mycust.expireYear = ''; datacontext.cust.mycust.accountNumber = vm.paymentMethod.accountNumber;
                datacontext.cust.mycust.routingNumber = vm.paymentMethod.routingNumber;
                datacontext.cust.mycust.zip = '';
                datacontext.cust.mycust.paymentOrderIdString = null;
                datacontext.cust.mycust.payerId = null;

                datacontext.cust.mycust.completedPaymentInfo = true;
                var event_name = 'signup_step_6_complete';
                var event_data = {
                    customerId: datacontext.cust.mycust.id,
                    email: datacontext.cust.mycust.eMail,
                    state: datacontext.cust.mycust.state,
                    zip: datacontext.cust.mycust.zip,
                    nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                    porchBox: datacontext.cust.mycust.porchBox,
                    firstName: datacontext.cust.mycust.firstName,
                    lastName: datacontext.cust.mycust.lastName,
                    promoCode: datacontext.cust.mycust.promoCode


                };

                vm.navigateToNext(event_name, event_data);

                return;
            } else {
                datacontext.cust.mycust.bankName = '';
                datacontext.cust.mycust.accountNumber = '';
                datacontext.cust.mycust.routingNumber = '';

                datacontext.cust.mycust.expireMonth = vm.paymentMethod.expireMonth;
                datacontext.cust.mycust.expireYear = vm.paymentMethod.expireYear;
                datacontext.cust.mycust.zip = vm.paymentMethod.zipCode;
            }

            vm.paymentMethod.customerNumber = datacontext.cust.mycust.customerNumber;
        };


        vm.validateChecking = function () {
            if (vm.paymentMethod.paymentMethod === "Checking") {
                if (!vm.paymentMethod.bankName) {
                    vm.enroll_success = false;
                    vm.enroll_Message = "Invalid Routing Number.";
                    return false;
                }
            }
            return true;
        }

        vm.resetErrorMessage = function () {
            vm.enroll_Message = "";
        }

        function _LookupBankName() {
            if (('' + vm.paymentMethod.routingNumber).length >= 8) {
                return $http.get("api/customers/getBankName?rounteNum=" + vm.paymentMethod.routingNumber)
                    .success(querySucceeded);
            }

            function querySucceeded(data) {
                vm.resetErrorMessage();
                vm.paymentMethod.bankName = data;
            }
        };


        $window.submitPaymentSuccess = function (data) {
            vm.completePayment(data.uID);
        }

        function verifyPaymentData() {
            //console.log($state.params)
            if (($state.params.response_code) && ($state.params.response_code.length > 0)) {

                datacontext.cust.mycust.paymentMethod = vm.paymentMethod.paymentMethod = 'Credit Card';

                if (($state.params.response_code == 1 && $state.params.response_code_text.toLowerCase() == "success")) {
                    vm.completePayment($state.params.order_id);
                }
                else {
                    vm.creditCardErrorMessage = $state.params.response_code_text;
                    vm.editCreditCard();
                }
            }
        }

        vm.completePayment = function (orderId) {
            datacontext.cust.getPaymentData(orderId, true).then(function (result) {
                var starword = '************' + result.span;

                datacontext.cust.mycust.maskedCreditCard = starword;
                datacontext.cust.mycust.creditCard = starword;
                datacontext.cust.mycust.last4CreditCard = result.span;
                datacontext.cust.mycust.payerId = result.payer_identifier;
                datacontext.cust.mycust.paymentOrderIdString = result.order_id;
                datacontext.cust.mycust.expireMonth = result.expire_month;
                datacontext.cust.mycust.expireYear = result.expire_year;
                vm.customer.creditCard = starword;
                datacontext.cust.mycust.accountNumber = '';
                datacontext.cust.mycust.routingNumber = '';
                datacontext.cust.mycust.zip = result.billing_zip_code;

                vm.enroll_Message = "Payment Type Approved";
                vm.enroll_success = true;

                datacontext.cust.mycust.completedPaymentInfo = true;
                var event_name = 'signup_step_6_complete';
                var event_data = {
                    customerId: datacontext.cust.mycust.id,
                    email: datacontext.cust.mycust.eMail,
                    state: datacontext.cust.mycust.state,
                    zip: datacontext.cust.mycust.zip,
                    nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                    porchBox: datacontext.cust.mycust.porchBox,
                    firstName: datacontext.cust.mycust.firstName,
                    lastName: datacontext.cust.mycust.lastName,
                    promoCode: datacontext.cust.mycust.promoCode
                };
                vm.navigateToNext(event_name, event_data);
            }, function () {
                //error
                vm.clearQueryStringParameters();
                vm.creditCardErrorMessage = config.paymentServiceErrorMessage;
                vm.enroll_success = false;
            })
        }


        vm.clearQueryStringParameters = function () {
            $state.go('sign-up.6', {
                tab: $state.params.tab,
                order_id: null,
                response_code: null,
                secondary_response_code: null,
                response_code_text: null
            }, {
                notify: false,
                location: 'replace'
            });
        }

        vm.editCreditCard = function () {
            vm.enroll_success = false;

            var returnUrl = '/home-delivery/sign-up/shopping-checkout-payment-info';

            datacontext.cust.getAuthenticationUrl(returnUrl, datacontext.cust.mycust.customerNumber, true).then(function (result) {
                vm.paymentIframeUrl = $sce.trustAsResourceUrl(result.iFrameUrl);
                common.includePaymentScripts();
            }, function () {
                vm.enroll_Message = config.paymentServiceErrorMessage;
            });
        }

        activate();

        function activate() {
            //
            //	this code will run only once throughout the sign up of a new customer
            //

            common.activateController([], controllerId)
                .then(function () {

                    datacontext.primeCustomer().then(function () {

                        vm.customer = datacontext.cust.mycust;
                        vm.salesAdding = datacontext.cust.mycust.isSalesAdding;

                        verifyPaymentData();
                        //common.validateCustomerNumber(vm.customer.customerNumber);

                        if (datacontext.cust.mycust.accountNumber != null && datacontext.cust.mycust.routingNumber != null) {
                            if (datacontext.cust.mycust.accountNumber > 0 && datacontext.cust.mycust.routingNumber > 0) {
                                vm.checkedValue = true;
                            }
                        }

                        //$('#CreditCardIFrame').attr("src", vm.paymentIframe.url);

                        if ((datacontext.cust.mycust) && (datacontext.cust.mycust.paymentMethod)) {

                            initialPaymentdata = {
                                billCode: (datacontext.cust.mycust.paymentMethod == "Checking") ? "11" : "10",
                                bankName: datacontext.cust.mycust.bankName,
                                paymentMethod: datacontext.cust.mycust.paymentMethod,
                                creditCard: datacontext.cust.mycust.creditCard,
                                expireMonth: datacontext.cust.mycust.expireMonth,
                                expireYear: datacontext.cust.mycust.expireYear,
                                accountNumber: datacontext.cust.mycust.accountNumber,
                                routingNumber: datacontext.cust.mycust.routingNumber,
                                zip: datacontext.cust.mycust.zip,
                            }
                        }

                        angular.copy(initialPaymentdata, vm.paymentMethod);



                        vm.enroll_success = (((datacontext.cust.mycust)
                            && (datacontext.cust.mycust.bankName) && datacontext.cust.mycust.bankName.length > 0)
                            && datacontext.cust.mycust.accountNumber.length > 0) ||
                            ((datacontext.cust.mycust) && datacontext.cust.mycust.payerId && datacontext.cust.mycust.payerId.length > 0) ? true : false;


                        if (vm.paymentMethod.paymentMethod == "Checking") {
                            vm.LookupBankName();
                        }
                        else {
                            if (!vm.enroll_success) {
                                vm.editCreditCard();
                            }
                        }


                        var dt = new Date();
                        for (var i = 0; i < 12; i++) {
                            vm.expireYearOptions.push(i + dt.getFullYear());
                        }
                    });
                });
        }

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }
    }
})();;
(function () {
    "use strict";
    var controllerId = "placeOrderController";
    angular.module("app-hd").controller(controllerId,
        ["$http", "$q", "$scope", "$state", "$location", "config", "common", "datacontext", placeOrderController]);

    function placeOrderController($http, $q, $scope, $state, $location, config, common, datacontext) {
        //
        //	new customer controller
        //

        var vm = this;
        vm.datacontext = datacontext;
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;
        vm.ChangeToThenBack = $scope.$parent.vm.ChangeToThenBack;
        vm.ChangeTo = $scope.$parent.vm.ChangeTo;
        vm.getDollars = common.getDollars;
        vm.getCents = common.getCents;
        vm.customer = datacontext.cust.mycust;
        vm.isPosting = isPosting;
        vm.isBusy = false;
        vm.GetNextDeliveryTotals = _getNextDeliveryTotals;
        vm.GetStandingDeliveryTotals = _getStandingDeliveryTotals;
        vm.products = datacontext.products.entityData;
        vm.getCustDeliveryDateEOW = _getCustDeliveryDateEOW;
        vm.getCustDeliveryDateNonEOW = _getCustDeliveryDateNonEOW;

        // This flow needs only the temporary customer number and the amount to pay
        vm.OneTimePayment = {
            customerNumber: 0,
            amountToPay: null,
        };

        vm.placeOrder = function () {
            vm.posttoServer();
        };

        vm.nextDelivery = function (item) {
            return item && item.nextQuantity && item.nextQuantity > 0;
        };

        vm.standingDelivery = function (item) {
            return item && item.standingQuantity && item.standingQuantity > 0;
        };

        vm.showDiscountLine = function () {
            var standing = vm.GetStandingDeliveryTotals();
            var next = vm.GetNextDeliveryTotals();

            return (standing != null && standing.discount != 0) || (next != null && next.discount != 0);
            //return (next != null && next.discount != 0);
        };

        vm.showOrderAdjustmentModal = false;

        var isPosting = false;
        vm.posttoServer = function () {

            vm.datacontext.lastTotal = vm.GetNextDeliveryTotals().total;

            common.preventBrowserBack();
            if (isPosting) return;
            isPosting = true;

            datacontext.cust.mycust.isPosting = true;

            vm.errorMessage = '';
            vm.isBusy = true;

            common.$broadcast(config.events.spinnerToggle, { show: true });

            vm.verifypromise = $http.post("api/customers/CreateNewCustomer", vm.customer)
                .success(checkOrderAdjustment)
                .error(badCreate)
                .finally(function () {
                    vm.isBusy = false;
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });

            function checkOrderAdjustment(result) {
                var products = result.adjustedDetails;
                vm.newCustomerNumber = result.newCustomerNumber;

                if (products && products.length > 0) {

                    vm.adjustedItems = products;

                    products.forEach(function (item) {
                        var product = datacontext.products.entityItems[item.productNumber];
                        product.nextQuantity = item.newQuantity;

                        product.outOfStock = true;
                    });
                    vm.showOrderAdjustmentModal = true;
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                }
                else {
                    vm.showOrderAdjustmentModal = false;
                    postSucceeded(vm.newCustomerNumber);
                }
            }

            vm.closeOrderAdjustmentModal = function () {
                vm.showOrderAdjustmentModal = false;
                postSucceeded(vm.newCustomerNumber);
            };

            function postSucceeded(newCustomerNumber) {
                // this is where a sales person will be routed back to the start
                if (datacontext.cust.mycust.isSalesAdding) {
                    //datacontext.reset();

                    datacontext.resetAllData();
                    datacontext.cust.mycust.IncompleteCustomerSignup = false;
                    datacontext.isNewCustomer = false;
                    datacontext.isReturning = false;
                    var url = 'home-delivery/sign-up/shopping-checkout-place-order';
                    ga('set', 'page', url);
                    ga('send', 'pageview');
                    //$state.go('^.1', { salesAdding: true });
                    $state.go('sales');
                    return;
                } else {
                    datacontext.cust.mycust.IncompleteCustomerSignup = false;
                    datacontext.isNewCustomer = false;
                    datacontext.isReturning = false;

                    if (datacontext.cust.mycust.isCurator) {
                        datacontext.cust.mycust.customerNumber = newCustomerNumber;
                        vm.ChangeTo('101', { completed: true });
                    }
                    else {
                        var event_name = 'signup_step_7_complete';
                        var event_data = {
                            customerId: datacontext.cust.mycust.id,
                            email: datacontext.cust.mycust.eMail,
                            state: datacontext.cust.mycust.state,
                            zip: datacontext.cust.mycust.zip,
                            nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                            porchBox: datacontext.cust.mycust.porchBox
                        };
                        vm.navigateToNext(event_name, event_data);
                    }
                }
            }
            function badCreate(data, status, headers, config) {
                isPosting = false;
                datacontext.cust.mycust.isPosting = false;

                if (data && data.message == 'cutoff') {
                    var dt = common.getServerDateTime();

                    var cutoff = new Date(datacontext.cust.mycust.branchCutoff);
                    var nextDeliveryDate = new Date(datacontext.cust.mycust.nextDeliveryDate);

                    while (cutoff < dt) {
                        cutoff.setDate(cutoff.getDate() + 7);
                        datacontext.cust.mycust.branchCutoff = cutoff;
                        nextDeliveryDate.setDate(nextDeliveryDate.getDate() + 7)
                        datacontext.cust.mycust.nextDeliveryDate = nextDeliveryDate;
                        datacontext.cust.mycust.serviceStartDate = nextDeliveryDate;
                    }
                    alert("It is too late to submit an order for delivery tomorrow. Please select a future delivery date.");
                    $state.go('^.3');
                }
                else if (data && data.message == 'payment-error') {
                    alert("There was an error submitting your payment information. Please try again.");
                    $state.go('^.6');
                }
                else {
                    datacontext.cust.mycust.IncompleteCustomerSignup = false;
                    datacontext.isNewCustomer = false;
                    datacontext.isReturning = false;
                    $state.go('^.error');
                    common.preventBrowserBack();
                    vm.errorMessage = 'There was an error creating your order. Please contact our Customer Service Department or try again later.';
                }
            }

        };

        //vm.posttoServer = function () {

        //    common.preventBrowserBack();
        //    if (isPosting) return;
        //    isPosting = true;

        //    datacontext.cust.mycust.isPosting = true;

        //    vm.errorMessage = '';
        //    vm.isBusy = true;

        //    common.$broadcast(config.events.spinnerToggle, { show: true });

        //    // Create new Customer First before taking payment
        //    $http.post("api/customers/CreateNewCustomer", vm.customer)
        //        .success(function (response) {
        //            //Customer was created
        //            checkOrderAdjustment(response);
        //            common.$broadcast(config.events.spinnerToggle, { show: false });


        //            //// Customers must now pre-pay their first order
        //            //vm.datacontext.lastTotal = vm.GetNextDeliveryTotals().total;
        //            //vm.OneTimePayment.amountToPay = vm.datacontext.lastTotal;
        //            //vm.OneTimePayment.customerNumber = datacontext.cust.mycust.customerNumber;
        //            //vm.OneTimePayment.customerId = datacontext.cust.getCustId();

        //            //$http.post("api/payments/PostFirstPaymentNewCustomer", vm.OneTimePayment)
        //            //    .success(function (response) {
        //            //        //Payment Succeeded
        //            //        //The amount will post the new Customer account during the CreateNewCustomer API call
        //            //        vm.customer.SignUpPaymentHistoryId = response.transactionHistoryId;
        //            //    })
        //            //    .error(function (data, status, headers, config) {
        //            //        //Payment Failed
        //            //        vm.OneTimePayment = {};
        //            //        badCreate(data, status, headers, config);
        //            //    }).finally(function () {
        //            //        $scope.oneTimePaymentSubmitted = false;
        //            //        common.$broadcast(config.events.spinnerToggle, { show: false });
        //            //    });


        //        //    //Ensure the account balance shows this first payment
        //        //    $q.all([
        //        //        vm.customerDC.getAccountBalanceSummary(true),
        //        //        datacontext.cust.getPaymentSummary(true).then(function () {
        //        //            $scope.getPaymentHistory();
        //        //        })
        //        //    ])
        //        })
        //        .error(badCreate)
        //        .finally(function () {
        //            vm.isBusy = false;
        //            common.$broadcast(config.events.spinnerToggle, { show: false });
        //        });








        //    function checkOrderAdjustment(result) {
        //        var products = result.adjustedDetails;
        //        vm.newCustomerNumber = result.newCustomerNumber;

        //        if (products && products.length > 0) {

        //            vm.adjustedItems = products;

        //            products.forEach(function (item) {
        //                var product = datacontext.products.entityItems[item.productNumber];
        //                product.nextQuantity = item.newQuantity;

        //                product.outOfStock = true;
        //            });
        //            vm.showOrderAdjustmentModal = true;
        //            common.$broadcast(config.events.spinnerToggle, { show: false });
        //        }
        //        else {
        //            vm.showOrderAdjustmentModal = false;
        //            postSucceeded(vm.newCustomerNumber);
        //        }
        //    };

        //    vm.closeOrderAdjustmentModal = function () {
        //        vm.showOrderAdjustmentModal = false;
        //        postSucceeded(vm.newCustomerNumber);
        //    };

        //    function postSucceeded(newCustomerNumber) {
        //        // this is where a sales person will be routed back to the start
        //        if (datacontext.cust.mycust.isSalesAdding) {
        //            //datacontext.reset();

        //            datacontext.resetAllData();
        //            datacontext.cust.mycust.IncompleteCustomerSignup = false;
        //            datacontext.isNewCustomer = false;
        //            datacontext.isReturning = false;
        //            var url = 'home-delivery/sign-up/shopping-checkout-place-order';
        //            ga('set', 'page', url);
        //            ga('send', 'pageview');
        //            //$state.go('^.1', { salesAdding: true });
        //            $state.go('sales');
        //            return;
        //        } else {
        //            datacontext.cust.mycust.IncompleteCustomerSignup = false;
        //            datacontext.isNewCustomer = false;
        //            datacontext.isReturning = false;

        //            if (datacontext.cust.mycust.isCurator) {
        //                datacontext.cust.mycust.customerNumber = newCustomerNumber;
        //                vm.ChangeTo('101', { completed: true });
        //            }
        //            else {
        //                vm.navigateToNext();
        //            }
        //        }
        //    };

        //    function badCreate(data, status, headers, config) {
        //        isPosting = false;
        //        datacontext.cust.mycust.isPosting = false;

        //        if (data && data.message == 'cutoff') {
        //            var dt = common.getServerDateTime();

        //            var cutoff = new Date(datacontext.cust.mycust.branchCutoff);
        //            var nextDeliveryDate = new Date(datacontext.cust.mycust.nextDeliveryDate);

        //            while (cutoff < dt) {
        //                cutoff.setDate(cutoff.getDate() + 7);
        //                datacontext.cust.mycust.branchCutoff = cutoff;
        //                nextDeliveryDate.setDate(nextDeliveryDate.getDate() + 7)
        //                datacontext.cust.mycust.nextDeliveryDate = nextDeliveryDate;
        //                datacontext.cust.mycust.serviceStartDate = nextDeliveryDate;
        //            }
        //            alert("It is too late to submit an order for delivery tomorrow. Please select a future delivery date.");
        //            $state.go('^.3');
        //        }
        //        else if (data && data.message == 'payment-error') {
        //            alert("There was an error submitting your payment information. Please try again.");
        //            $state.go('^.6');
        //        }
        //        else {
        //            datacontext.cust.mycust.IncompleteCustomerSignup = false;
        //            datacontext.isNewCustomer = false;
        //            datacontext.isReturning = false;
        //            $state.go('^.error');
        //            common.preventBrowserBack();
        //            vm.errorMessage = 'There was an error creating your order. Please contact our Customer Service Department or try again later.';
        //        }
        //    };

        //};

        function _getNextDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.nextTotals) ? datacontext.order.orderTotals.nextTotals : 0;
        };

        function _getStandingDeliveryTotals() {
            return (datacontext.order.orderTotals) && (datacontext.order.orderTotals.standingTotals) ? datacontext.order.orderTotals.standingTotals : 0;
        };

        // Returns the delivery date for an EOW customer
        function _getCustDeliveryDateEOW() {
            vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
            return moment(vm.DeliveryDate).add(14, 'days').toDate();
        };
        
        // Returns the delivery date for a non-EOW customer
        function _getCustDeliveryDateNonEOW() {
            vm.DeliveryDate = datacontext.cust.mycust.nextDeliveryDate;
            return moment(vm.DeliveryDate).add(7, 'days').toDate();
        };


        activate();

        function activate() {
            //
            //	this code will run only once throughout the sign up of a new customer
            //
            var parameters = $state.params;

            if (datacontext.isNewCustomer) {
                if ((datacontext.cust.mycust == null) && ($state.$current.name.indexOf('sign-up.1') < 0)) {
                    $state.go('sign-up.1', null, { reload: true });
                    return;
                }
            }

            common.activateController([datacontext.primeProducts()], controllerId).then(function () {

                common.validateCustomerNumber(datacontext.cust.mycust.customerNumber);
                
                if (!vm.customer) {
                    vm.customer = datacontext.cust.mycust;
                }
                
                vm.enroll_success = (((datacontext.cust.mycust)
                    && (datacontext.cust.mycust.bankName) && datacontext.cust.mycust.bankName.length > 0)
                    && datacontext.cust.mycust.accountNumber.length > 0) ||
                    ((datacontext.cust.mycust) && datacontext.cust.mycust.payerId && datacontext.cust.mycust.payerId.length > 0) ? true : false;

                vm.products = datacontext.products.entityData;
                vm.entityProducts = datacontext.products.entityItems;
            });
        };

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        };
    }
})();;
(function () {
    "use strict";
    var controllerId = "porchBoxController";
    angular.module("app-hd").controller(controllerId, ["$scope", "$http", "$q", "common", "datacontext", "authService", porchBoxController]);

    function porchBoxController($scope, $http, $q, common, datacontext, authService) {
        var vm = this;
        vm.navigateToNext = $scope.$parent.vm.NavigateToNext;

        vm.porchBox = {};

        vm.customer = datacontext.cust.mycust;
        vm.continueButtonClicked = continueButtonClicked;
        var AuthInfo = authService.authentication;
        vm.showPorchBoxNotificationModal = false;

        // Gets the porch box price
        vm.getPorchBoxPrice = function () {
            if (datacontext.cust != null) {
                if (datacontext.cust.mycust != null) {
                    return '$' + datacontext.cust.mycust.porchBoxItems.productPrice.toFixed(2);
                }
                else {
                    return "(Price Not Currently Available)";
                }
            }
            else {
                return "(Price Not Currently Available)";
            }
        }

        function continueButtonClicked(porchBox) {

            var prod = resetPorchBox();

            if (vm.customer.porchBox == 'PURCHASE') {

                prod.push({
                    productId: datacontext.cust.mycust.porchBoxItems.productNumber,
                    standingQuantity: 0,
                    nextQuantity: 1
                });
                //add owns a bag
                prod.push(
                    {
                        productId: 27,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
            }
            else if (vm.customer.porchBox == 'FREE') {
                prod.push(
                    {
                        productId: datacontext.cust.mycust.porchBoxItems.productNumber,
                        standingQuantity: 0,
                        nextQuantity: 1
                    });
                prod.push(
                    {
                        productId: datacontext.cust.mycust.porchBoxItems.discountProductNumber,
                        standingQuantity: 0,
                        nextQuantity: 1
                    });
                //add owns a bag
                prod.push(
                    {
                        productId: 27,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
            }
            else if (vm.customer.porchBox == 'WEEKLY') {
                prod.push(
                    {
                        productId: datacontext.cust.mycust.porchBoxItems.productNumber,
                        standingQuantity: 0,
                        nextQuantity: 1
                    });
                //prod.push(
                //    {
                //        productId: datacontext.cust.mycust.porchBoxItems.discountProductNumber,
                //        standingQuantity: 0,
                //        nextQuantity: 1
                //    });
                prod.push(
                    {
                        productId: 8190,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
            }
            else if (vm.customer.porchBox == 'USEOWN') {
                prod.push({
                    productId: 115,
                    standingQuantity: 1,
                    nextQuantity: 1
                });
            }
            else if (vm.customer.porchBox == 'PREVIOUS') {
                prod.push({
                    productId: 116,
                    standingQuantity: 1,
                    nextQuantity: 1
                });
            }

            datacontext.order.PostOrderDetailUpdate(prod);
            var event_name = 'signup_step_4_complete';
            var event_data = {
                customerId: datacontext.cust.mycust.id,
                email: datacontext.cust.mycust.eMail,
                state: datacontext.cust.mycust.state,
                zip: datacontext.cust.mycust.zip,
                nextDeliveryDate: datacontext.cust.mycust.nextDeliveryDate,
                porchBox: datacontext.cust.mycust.porchBox
            };
            vm.navigateToNext(event_name, event_data);
        };

        vm.showPorchBoxNotification = function () {
            vm.showPorchBoxNotificationModal = (vm.customer.porchBox === 'PREVIOUS');
        }
        vm.cancelPorchBoxNotificationModal = function () {
            vm.showPorchBoxNotificationModal = false;
        }

        vm.showIceCreamBagNotification = function () {
            return vm.customer.showIceCreamBagModal &&
                vm.customer.porchBox === 'PREVIOUS' &&
                !vm.showPorchBoxNotificationModal;
        }

        function resetPorchBox() {
            var prod = [];

            prod.push(
                {
                    productId: datacontext.cust.mycust.porchBoxItems.productNumber,
                    standingQuantity: 0,
                    nextQuantity: 0
                });
            prod.push(
                {
                    productId: datacontext.cust.mycust.porchBoxItems.discountProductNumber,
                    standingQuantity: 0,
                    nextQuantity: 0
                });
            prod.push(
                {
                    productId: 115,
                    standingQuantity: 0,
                    nextQuantity: 0
                });
            prod.push(
                {
                    productId: 116,
                    standingQuantity: 0,
                    nextQuantity: 0
                });

            return prod;
        }

        activate();

        vm.allowCoolerFree = false;
        vm.allowCoolerWeeklyDrip = false;


        vm.saveStepChanges = function () {
            datacontext.cust.InsSignupNoComplete();
        }
        /////////////
        vm.IceCreamBagOption = "purchase";
        vm.ProcessBagOption = ProcessBagOption;
        function ProcessBagOption() {
            //
            // this is called when the continue button is pressed.
            var bag = [];

            switch ("" + vm.IceCreamBagOption) {
                case "purchase":
                    //Purchase an ice cream bag (defaulted)
                    //o    Add to Next Delivery product code 4906
                    //o    Add to Standing Order product code 27

                    bag.push(
                        {
                            productId: 4906,
                            standingQuantity: 0,
                            nextQuantity: 1,
                        });

                    resetIceCreamBagRemoveFlag();

                    bag.push(
                        {
                            productId: 27,
                            standingQuantity: 1,
                            nextQuantity: 1
                        });

                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;
                case "own":
                    // o    Add to both Next Delivery and Standing Order product code 26

                    bag.push({
                        productId: 27,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;
                case "knock":
                    //o    Add to both Next Delivery and Standing Order product code 27
                    bag.push({
                        productId: 26,
                        standingQuantity: 1,
                        nextQuantity: 1
                    });
                    datacontext.cust.mycust.hasIceCreamBag = true;
                    break;

            }
            //bag.push(vm.IceCreamBagitem);


            datacontext.order.PostOrderDetailUpdate(bag);
        
            vm.customer.showIceCreamBagModal = false;
        };

        function resetIceCreamBagRemoveFlag() {
            var itm = datacontext.products.entityItems[4906];
            if (itm) {
                itm.isRemoved = false;
            }

        }

        vm.RejectBagOption = RejectBagOption;

        function RejectBagOption() {
            //vm.IceCreamBagitem.nextQuantity = 0;
            //vm.IceCreamBagitem.standingQuantity = 0;
            //vm.showIceCreamBagModal = false;
            vm.orderItems = datacontext.order.getOrderItems();

            if (vm.orderItems) {
                vm.orderItems.forEach(function (item) {
                    if (item.requiresIceCreamBag === 1) {
                        item.nextQuantity = 0;
                        item.standingQuantity = 0;
                        item.isRemoved = false;
                    }
                });
            }
            vm.customer.showIceCreamBagModal = false;
        };

        //////////////////
        function activate() {
            common.activateController([], controllerId)
                .then(function () {
                    datacontext.primeCustomer().then(function () {

                        if (!datacontext.cust.mycust.promoCode && datacontext.cust.mycust.promotionCode) {
                            vm.checkPromo().then(function (promo) {
                                datacontext.cust.mycust.promoCode = promo;
                                vm.customer = datacontext.cust.mycust;
                                vm.checkFreeCooler();
                            });
                        }

                        vm.customer = datacontext.cust.mycust;

                        common.validateCustomerNumber(vm.customer.customerNumber);

                        vm.checkFreeCooler()

                        if (!datacontext.cust.mycust.porchBox) {
                            vm.customer.porchBox = 'PURCHASE';
                        }
                    });
                });
        }

        vm.checkFreeCooler = function () {
            var pc = vm.customer.promoCode;

            if (pc) {
                vm.allowCoolerFree = pc.allowCoolerFree;
                vm.allowCoolerWeeklyDrip = pc.allowCoolerWeeklyDrip;

                if (pc.allowCoolerFree) {
                    vm.customer.porchBox = 'FREE';
                } else if (pc.allowCoolerWeeklyDrip) {
                    vm.customer.porchBox = 'WEEKLY';
                }
            }
        }

        vm.checkPromo = function () {
            var self = this;
            var defer = $q.defer();

            if (self.promo) {
                return self.$q.when(self.promo);
            }

            var url = "api/order/getAddCouponAuth" + "?couponId=" + datacontext.cust.mycust.promotionCode + "&isSalesAdding=" + datacontext.cust.mycust.isSalesAdding;

            if (!AuthInfo.isAuth || datacontext.cust.mycust.incompleteCustomerSignup) {
                if (datacontext.cust.mycust.id == null) return;

                if (datacontext.cust.mycust.promotionCode == null) return;

                url = "api/order/getAddCouponNoAuth" + "?id=" + datacontext.cust.mycust.id + "&couponId=" + datacontext.cust.mycust.promotionCode;
            }

            $http.get(url)
                .success(function (data) {
                    self.promo = {
                        name: data.promo_Code,
                        promo_Code: data.promo_Code,
                        description: data.description,
                        allowCoolerFree: data.allowCoolerFree,
                        allowCoolerWeeklyDrip: data.allowCoolerWeeklyDrip,
                        ramsPromoCode: data.ramsPromoCode,
                        hasDeliveryDiscount: data.hasDeliveryDiscount,
                        hasDollarsOffDiscount: data.hasDollarsOffDiscount,
                        hasFirstTasteDiscount: data.hasFirstTasteDiscount,
                        hasGraduatedDiscount: data.hasGraduatedDiscount,
                        slidingDeliveryDiscountTarget: data.slidingDeliveryDiscountTarget,
                        slidingDollarsOffDiscountTarget: data.slidingDollarsOffDiscountTarget,
                        slidingGraduatedDiscountTarget: data.slidingGraduatedDiscountTarget,
                        dollarOffAmountFormatted: data.dollarOffAmountFormatted,
                        hideTicklePopup: true
                    }
                    defer.resolve(self.promo);
                })
                .error(function (data, status, headers, config) {
                    $scope.message = data;
                    $scope.checkingPromo = false;

                    defer.reject();
                });

            return defer.promise;
        };

        vm.showMainMenu = function () {
            var fullsite = "" + window.location;
            if (fullsite.indexOf('/sign-up') > 0) return false;
            else return true;
        }
    }
})();;
(function () {
    var controllerId = 'thankYouController';

    angular.module('app-hd').controller(controllerId,
        ["common", 'datacontext', '$http','googleAnalytics', thankYouController]);


    function thankYouController(common, datacontext, $http, googleAnalytics) {
        var vm = this;
        vm.getLastTotal = _getLastTotal;
        vm.isNewStart = false;
        vm.datacontext = datacontext;

        function activate() {
            common.disableBrowserBack();

            common.activateController([], controllerId)
                .then(function () {
                    datacontext.primeCustomer().then(function () {
                        var custOrderTotal = 0;
                        vm.customer = vm.datacontext.cust.mycust;
                        if (vm.customer &&
                            vm.customer.order[0] &&
                            vm.customer.order[0].orderTotal &&
                            vm.customer.order[0].orderTotal.nextTotals &&
                            vm.customer.order[0].orderTotal.nextTotals.total) {
                            custOrderTotal = vm.customer.order[0].orderTotal.nextTotals.total;
                        }
                        vm.isCurator = vm.customer.isCurator;
                        //send enhanced conversion data to GA
                        //send_to = conversion action, transaction_id = any unique value that can prevent duplicate events from being logged
                        gtag('event', 'purchase', {
                            transaction_id: sessionStorage.getItem('sessionId'),
                            currency:'USD',
                            value: custOrderTotal
                        });
                        var date = new Date();
                        var month = date.getMonth() + 1;
                        month = (month < 10) ? "0" + month : month
                        var timeZoneOffsetHours = date.getTimezoneOffset() / 60
                        var timeZonOffsetMinutes = 350 % 60
                        var formattedDate = `${date.getFullYear()}-${month}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`

                        var names = vm.customer.name.split(", ")

                        var data = {
                            //Google ads account id not our customer id
                            CustomerId: '3631937741',
                            // ID of the conversion action for which conversions are uploaded. AW-478951820
                            ConversionActionId: '478951820',
                            EmailAddress: vm.customer.eMail,
                            // The date time at which the conversion occurred. Must be after the click time, and must include the time zone offset. The format is 'yyyy-mm-dd hh:mm:ss+|-hh:mm', e.g. '2019-01-01 12:32:45-08:00'.
                            ConversionDateTime: formattedDate,
                            FirstName: names[1],
                            LastName: names[0],
                            // The conversion value.
                            ConversionValue: 1,
                            UserAgent: navigator.userAgent,
                            AddressLine1: vm.customer.addressLine1,
                            AddressLine2: vm.customer.addressLine2,
                            City: vm.customer.city,
                            State: vm.customer.state,
                            ZipCode: vm.customer.zipCode,

                            // The unique order ID (transaction ID) of the conversion.
                            OrderId: sessionStorage.getItem('sessionId')

                        }
                        //calling FB Pixel 
                        fbq('track', 'CompleteRegistration', {
                            city: vm.customer.city,
                            state: vm.customer.state,
                            zip: vm.customer.zipCode,
                            phone: vm.customer.phone,
                            email: vm.customer.eMail,
                            currency: "USD",
                            value: custOrderTotal
                        });
                        //calling FB Pixel 
                        fbq('trackCustom', 'OberweisHomeDeliveryCheckoutConfirmationPage', {
                            city: vm.customer.city,
                            state: vm.customer.state,
                            zip: vm.customer.zipCode,
                            phone: vm.customer.phone,
                            email: vm.customer.eMail,
                        });
                        var event_name = 'signup_step_8_complete';
                        var event_data = {
                            customerId: vm.customer.id,
                            city: vm.customer.city,
                            state: vm.customer.state,
                            zip: vm.customer.zipCode,
                            phone: vm.customer.phone,
                            email: vm.customer.eMail,
                            currency: "USD",
                            value: custOrderTotal
                        };
                        googleAnalytics.push(event_name, event_data);
                        //push additional to another conversion 
                        event_name = 'thank_you_page_reached';

                        googleAnalytics.push(event_name, event_data);

                        //send conversion enhancement adjustments (match )
                        // var result = $http.post('api/GoogleAnalytics/UploadEnhancedConversion', data).then((response) => console.log(response), (response) => console.log(response));                        


                    });
                });
        }

        activate();

        function _getLastTotal() {
            return vm.datacontext.lastTotal;
        }

    }
})();;
(function () {

    var controllerId = "subscriptionController";

    angular.module("app-hd").controller(controllerId,
        ["$scope",
        "$state",
        "$sce",
        "$http",
        "$stateParams",
        "config",
        "common",
        "datacontext",
        "authService",
        "$window",
        "$location",
        "unauthenticatedBranch",
        subscriptionController]);

    function subscriptionController($scope, $state, $sce, $http, $stateParams, config, common, datacontext, authService, $window, $location, unauthenticatedBranch) {

        vm = this;
        vm.baseUrl = config.baseUrl;
        vm.currentOffer = {};
        vm.offerIsValid = false;
        vm.offerInvalidMsg = '';
        vm.offerId = $stateParams.id;
        vm.agreeToPurchase = true;
        vm.agreeToTerms = false;
        vm.agreeToAutoRenew = true;
        vm.showTermsModal = false;
        vm.showPaymentModal = false;
        vm.showPaymentSuccessModal = false;
        vm.showIframe = false;
        vm.paymentMethod = {};
        vm.cardOnFileExists = false;
        vm.otp_message = '';
        vm.customerLoaded = false;

        vm.OneTimePayment = {
            billCode: 0,
            id: 0,
            customerNumber: 0,
            paymentMethod: null,
            isChecking: false,
            isWeeklyBilling: false,
            creditCard: null,
            expireMonth: null,
            expireYear: null,
            routingNumber: null,
            accountNumber: null,
            zipCode: null,
            payer_Id: null,
            date_Created: null,
            date_Deleted: null,
            bankName: null,
            amountToPay: null,
            amountToCharge: null
        };


        $scope.$watch(function () { return datacontext.cust }, function (oldVal, newVal) {
            //Nothing works if the customer is not loaded
            if (newVal && newVal.mycust) {
                vm.customerLoaded = true;
                common.$broadcast(config.events.spinnerToggle, { show: false });
            }
            else {
                common.$broadcast(config.events.spinnerToggle, { show: true });
                vm.customerLoaded = false;
            }
        });

        vm.getSubscriptionOffer = function (id) {
            $http.get("api/subscription/GetSubscriptionOfferValidated/" + id)
                .success(function (response) {
                    vm.currentOffer = response; //not sure why this one call populates response, and not response.data like everything else?
                    vm.offerIsValid = true;
                })
                .error(function (data, status, headers, config) {
                    vm.offerIsValid = false;
                    if (status == 303)
                        vm.offerInvalidMsg = data.message;
                    else
                        vm.offerInvalidMsg = " this offer is not currently valid at your location."
                });
        };

        vm.showTermsAndConditions = function () {
            vm.showTermsModal = true;
            vm.agreeToTerms = true;
        };

        vm.expirationDisplay = function () {
            if (vm.currentOffer && vm.currentOffer.expiration) {
                var result = vm.currentOffer.expiration.description;
                var isPlural = result.slice(-1) === 's';
                if (isPlural)
                    return result.slice(0, -1);
                else
                    return result;
            }
            else
                return '';
        };

        vm.collectPayment = function () {
            getPaymentMethod();
            vm.showPaymentModal = true;
        };

        vm.changedCardType = function () {
            vm.OneTimePayment.CreditCard = null;
            vm.OneTimePayment.ExpireMonth = null;
            vm.OneTimePayment.ExpireYear = null;
            vm.OneTimePayment.zipCode = null;
        }

        vm.loadCreditCardForm = function () {
            vm.otp_message = "";
            vm.showIframe = true;
            vm.OneTimePayment.amountToPay = vm.currentOffer.salePrice;
            vm.OneTimePayment.amountToCharge = vm.currentOffer.salePrice;

            //var returnUrl = '/home-delivery/shopping/subscription/';
            var returnUrl = $location.absUrl();

            datacontext.cust.getTransactionUrl(vm.OneTimePayment.amountToPay, returnUrl).then(function (result) {
                vm.paymentIframeUrl = $sce.trustAsResourceUrl(result.iFrameUrl);
                common.includePaymentScripts();
            }, function () {
                vm.otp_message = config.paymentServiceErrorMessage;
                vm.otp_success = false;
                vm.showIframe = false;
            });
        }

        function getPaymentMethod() {
            return $http.get("api/payments/getPaymentMethod")
                .success(function (response) {
                    if (response == null) {
                        $scope.hasPaymentMethod = false;
                        vm.OneTimePayment.paymentMethod = "otherCard";
                    } else {
                        $scope.hasPaymentMethod = true;
                        vm.paymentMethod = response;
                        vm.OneTimePayment.paymentMethod = (vm.paymentMethod.isChecking) ? "otherCard" : "cardonfile";
                        if(!vm.paymentMethod.isChecking)
                            vm.paymentMethod.creditCard = vm.paymentMethod.accountNumber;
                        vm.cardOnFileExists = !vm.paymentMethod.isChecking;
                    }
                })
                .error(function (data, status, headers, config) {
                    $scope.hasPaymentMethod = false;
                    vm.OneTimePayment.paymentMethod = "otherCard";
                });
        };

        //This event is configured in the ChaseJS file as the event to fire when the iFrame has processed a one-time payment
        $window.submitPaymentSuccess = function (data) {
            vm.paymentIframeUrl = "";
            vm.showIframe = false;
            vm.otp_success = data.code === "000" && data.message.toLower === "success";
 
            //This is called whether the payment succeeded or failed, that will be known when we look up the transaction
            vm.postOtherCardSubscriptionPayment(data.uID);
        };

        vm.postOtherCardSubscriptionPayment = function (chaseUID) {
            $scope.message = "Processing your subscription purchase ...";
            vm.otp_message = "";
            $scope.subscriptionPaymentSubmitted = true;
            $scope.subscriptionPaymentComplete = false;
            common.$broadcast(config.events.spinnerToggle, { show: true });

            var subscriptionPurchase = {
                PaymentData:  null,
                ProcessorOrderId: chaseUID,
                Subscription: {
                    Id: 0,
                    CustomerId: datacontext.cust.mycust.id,
                    SubscriptionOfferId: vm.currentOffer.id,
                    AutoRenew: vm.AutoRenew
                }
            };

            return $scope.promise = $http.post("api/subscription/RecordSubscriptionPurchaseOtherCard", subscriptionPurchase)
                .success(function (response) {
                    vm.otp_message = response[0];
                    $scope.subscriptionPaymentComplete = true;
                    ClosePaymentModalShowSuccess();
                    $q.all([
                        datacontext.subscription.getSubscriptionHistory(true)
                    ]);
                })
                .error(function (data, status, headers, config) {
                    vm.otp_success = false;
                    vm.otp_message = vm.handleChaseIframeError(data);
                    //vm.OneTimePayment = {};
                }).finally(function () {
                    $scope.subscriptionPaymentSubmitted = false;
                    common.$broadcast(config.events.spinnerToggle, { show: false });
                });
        };

        vm.handleChaseIframeError = function (error) {
            var msg = '';
            if (error.length > 0) {
                angular.forEach(error, function (value, key) {
                    msg += value + " ";
                });
            } else {
                msg = error;
            }
            return msg;
        };

        vm.processPaymentCardOnFile = function () {
            if (vm.OneTimePayment.paymentMethod === 'cardonfile' && vm.paymentMethod) {
                $scope.message = "Processing your subscription purchase ...";
                vm.otp_message = "";
                vm.otp_success = true;
                $scope.subscriptionPaymentSubmitted = true;
                $scope.subscriptionPaymentComplete = false;

                common.$broadcast(config.events.spinnerToggle, { show: true });

                vm.OneTimePayment.amountToPay = vm.currentOffer.salePrice;
                vm.OneTimePayment.amountToCharge = vm.currentOffer.salePrice;
                var subscriptionPurchase = {
                    PaymentData: vm.OneTimePayment,
                    ProcessorOrderId: null,
                    Subscription: {
                        Id: 0,
                        CustomerId: datacontext.cust.mycust.id,
                        SubscriptionOfferId: vm.currentOffer.id,
                        AutoRenew: vm.AutoRenew
                    }
                };

                return $scope.promise = $http.post("api/subscription/PurchaseSubscriptionCardOnFile", subscriptionPurchase)
                    .success(function (response) {
                        vm.otp_message = response[0];
                        $scope.subscriptionPaymentComplete = true;
                        ClosePaymentModalShowSuccess();
                        $q.all([
                            datacontext.subscription.getSubscriptionHistory(true)
                        ]);
                    })
                    .error(function (data, status, headers, config) {
                        vm.otp_success = false;
                        vm.otp_message = vm.handleError(data);
                        //vm.OneTimePayment = {};
                    }).finally(function () {
                        $scope.subscriptionPaymentSubmitted = false;
                        common.$broadcast(config.events.spinnerToggle, { show: false });
                    });
            }
        };

        vm.handleError = function (error) {
            var msg = '';

            if (error.length > 0) {
                angular.forEach(error, function (value, key) {
                    msg += value + " ";
                });
            } else {
                msg = error;
            }

            return msg;
        }

        vm.ContinueShopping = function () {
            vm.showPaymentSuccessModal = false;
            $state.go('shopping.categorynoparm', { notify: true });
        };

        vm.GotoSubscriptionHistory = function () {
            vm.showPaymentSuccessModal = false;
            $state.go('shopping.account', { tab: 'subscriptions' }, { notify: true });
        };


        activate();

        function activate() {
            if (datacontext.cust)
                vm.customerLoaded = true;
            else
                common.$broadcast(config.events.spinnerToggle, { show: true });

            if (vm.offerId)
                vm.getSubscriptionOffer(vm.offerId);
            else {
                datacontext.subscription.getDefaultSubscriptionOfferId()
                    .then(function () {
                        if (datacontext.subscription.defaultSubscriptionOfferId != 0)
                            vm.getSubscriptionOffer(datacontext.subscription.defaultSubscriptionOfferId);
                    });
            }
        };

        function ClosePaymentModalShowSuccess() {
            vm.showPaymentModal = false;
            vm.showPaymentSuccessModal = true;
        };

    }

})();


;
(function () {
    var app = angular.module("app-hd");
    app.directive("abnTree", ["$timeout", function ($timeout) {
        return {
            restrict: "E",
            template: "<ul style='text-align:left;' id='thelist' class=\"nav nav-list nav-pills nav-stacked abn-tree\">\n "
                + " <li ng-show='row.label && row.label.length>0'  ng-repeat=\"row in tree_rows | filter:{visible:true} track by row.branch.uid\" " +
                "ng-animate=\"'abn-tree-animate'\" ng-class=\"'level-' + {{ row.level }} + (row.branch.selected ? ' active':'') + "
                + "' ' +row.classes.join(' ')\" class=\"abn-tree-row\">" +
                "<div  id='{{row.name}}   height: 50px;'  href=\"\#/products/{{row.name}}\"   ng-click=\"user_clicks_branch(row.branch) \">"
              //  + "<img  data-cc-img-category='.png^{{row.branch.parentName}}'  style='height:40px;width:40px;padding:5px;'  ng-click=\"row.branch.expanded = !row.branch.expanded\" class=\"indented tree-icon\" ng-class=\"(row.branch.expanded ? 'expanded':'') \" > " + "</img>"
                + "<A style='height:40px;width:40px;padding:5px;' ng-click=\"row.branch.expanded = !row.branch.expanded\">" +
                "<i class=\"fa fa-plus-circle\" aria-hidden=\"true\" ng-hide=\"row.branch.expanded \"></i>"
                 + "<i class=\"fa fa-minus-circle\" aria-hidden=\"true\" ng-show=\"row.branch.expanded \"></i></A>"
               
                + "<span    class=\"indented tree-label\"      ng-click=\"RowBranchExpander(row)\" >{{ row.label }} </span></div></li>\n</ul>",

            replace: true,
            //scope: {
            //    treeData: '=',
            //    onSelect: '&',
            //    initialSelection: '@',
            //    selectText: '=',
            //    treeControl: '='
            //},
            link: function (scope, element, attrs) {
                var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
                error = function (s) {
                    console.log("ERROR:" + s);
                    return void 0;
                };
                if (attrs.iconExpand == null) {
                    attrs.iconExpand = "icon-plus  glyphicon glyphicon-plus  fa fa-plus";
                }
                if (attrs.iconCollapse == null) {
                    attrs.iconCollapse = "icon-minus glyphicon glyphicon-minus fa fa-minus";
                }
                if (attrs.iconLeaf == null) {
                    attrs.iconLeaf = "icon-file  glyphicon glyphicon-file  fa fa-file";
                }
                if (attrs.expandLevel == null) {
                    attrs.expandLevel = "5";
                }
                expand_level = parseInt(attrs.expandLevel, 10);
                if (!scope.treeData) {
                    alert("no treeData defined for the tree!");
                    return;
                }
                if (scope.treeData.length == null) {
                    if (treeData.label != null) {
                        scope.treeData = [treeData];
                    } else {
                        alert("treeData should be an array of root branches");
                        return;
                    }
                }
                for_each_branch = function (f) {
                    var do_f, root_branch, _i, _len, _ref, _results;
                    do_f = function (branch, level) {
                        var child, _i, _len, _ref, _results;
                        f(branch, level);
                        if (branch.sortedChildren != null) {
                            _ref = branch.sortedChildren;
                            _results = [];
                            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                                child = _ref[_i];
                                _results.push(do_f(child, level + 1));
                            }
                            return _results;
                        }
                    };
                    _ref = scope.treeData;
                    _results = [];
                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                        root_branch = _ref[_i];
                        _results.push(do_f(root_branch, 1));
                    }
                    return _results;
                };
                selected_branch = null;
                select_branch = function (branch) {
                    if (!branch) {
                        if (selected_branch != null) {
                            selected_branch.selected = false;
                        }
                        selected_branch = null;
                        return;
                    }
                    if (branch !== selected_branch) {
                        if (selected_branch != null) {
                            selected_branch.selected = false;
                        }
                        branch.selected = true;
                        selected_branch = branch;


                        //expand_all_parents(branch);
                        //var baby = scope.treeControl.last_descendant(branch);

                        //scope.treeControl.expand_all_kids(branch);



                        if (branch.onSelect != null) {
                            return $timeout(function () {
                                return branch.onSelect(branch);
                            });
                        } else {
                            if (scope.onSelect != null) {
                                return $timeout(function () {
                                    return scope.onSelect({
                                        branch: branch
                                    });
                                });
                            }
                        }
                    }
                };
                scope.user_clicks_branch = function (branch) {
                    if (branch !== selected_branch) {
                        //vm.gotoProduct(branch.name);
                        return select_branch(branch);
                    }
                };
                get_parent = function (child) {
                    var parent;
                    parent = void 0;
                    if (child.parent_uid) {
                        for_each_branch(function (b) {
                            if (b.uid === child.parent_uid) {
                                return parent = b;
                            }
                        });
                    }
                    return parent;
                };
                for_all_ancestors = function (child, fn) {
                    var parent;
                    parent = get_parent(child);
                    if (parent != null) {
                        fn(parent);
                        return for_all_ancestors(parent, fn);
                    }
                };
                expand_all_parents = function (child) {
                    return for_all_ancestors(child, function (b) {
                        return b.expanded = true;
                    });
                };
                scope.tree_rows = [];
                on_treeData_change = function () {
                    var add_branch_to_list, root_branch, _i, _len, _ref, _results;
                    for_each_branch(function (b, level) {
                        if (!b.uid) {
                            return b.uid = "" + Math.random();
                        }
                    });
                    console.log("UIDs are set.");
                    for_each_branch(function (b) {
                        var child, _i, _len, _ref, _results;
                        if (angular.isArray(b.sortedChildren)) {
                            _ref = b.sortedChildren;
                            _results = [];
                            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                                child = _ref[_i];
                                _results.push(child.parent_uid = b.uid);
                            }
                            return _results;
                        }
                    });
                    scope.tree_rows = [];
                    for_each_branch(function (branch) {
                        var child, f;
                        if (branch.sortedChildren) {
                            if (branch.sortedChildren.length > 0) {
                                f = function (e) {
                                    if (typeof e === "string") {
                                        return {
                                            label: e,
                                            children: []
                                        };
                                    } else {
                                        return e;
                                    }
                                };
                                return branch.sortedChildren = (function () {
                                    var _i, _len, _ref, _results;
                                    _ref = branch.sortedChildren;
                                    _results = [];
                                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                                        child = _ref[_i];
                                        _results.push(f(child));
                                    }
                                    return _results;
                                })();
                            }
                        } else {
                            return branch.sortedChildren = [];
                        }
                    });
                    add_branch_to_list = function (level, branch, visible) {
                        var child, child_visible, tree_icon, _i, _len, _ref, _results;
                        if (branch.expanded == null) {
                            branch.expanded = false;
                        }
                        if (branch.classes == null) {
                            branch.classes = [];
                        }
                        if (!branch.noLeaf && (!branch.sortedChildren || branch.sortedChildren.length === 0)) {
                            tree_icon = attrs.iconLeaf;
                            if (_.indexOf(branch.classes, "leaf") < 0) {
                                branch.classes.push("leaf");
                            }
                        } else {
                            if (branch.expanded) {
                                tree_icon = attrs.iconCollapse;
                            } else {
                                tree_icon = attrs.iconExpand;
                            }
                        }
                        scope.tree_rows.push({
                            level: level,
                            branch: branch,
                            name: branch.name,
                            label: branch.label,
                            classes: branch.classes,
                            tree_icon: tree_icon,
                            visible: visible,
                            isParent: branch.isParent,

                            prods: branch.prods
                        });
                        if (branch.sortedChildren != null) {
                            _ref = branch.sortedChildren;
                            _results = [];
                            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                                child = _ref[_i];
                                child_visible = visible && branch.expanded;
                                _results.push(add_branch_to_list(level + 1, child, child_visible));
                            }
                            return _results;
                        }
                    };
                    _ref = scope.treeData;
                    _results = [];
                    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                        root_branch = _ref[_i];
                        _results.push(add_branch_to_list(1, root_branch, true));
                    }
                    return _results;
                };
                scope.$watch("changeMe", function (evnt) {
                    if (scope.changeMe) {
                        for_each_branch(function (b) {
                            if (b.name === scope.changeMe) {
                                return select_branch(b);
                            }
                        });
                    }
                });
                scope.$watch("treeData", on_treeData_change, true);
                if (attrs.initialSelection != null) {
                    for_each_branch(function (b) {
                        if (b.label === attrs.initialSelection) {
                            return $timeout(function () {
                                return select_branch(b);
                            });
                        }
                    });
                }
                n = scope.treeData.length;
                console.log("num root branches = " + n);
                for_each_branch(function (b, level) {
                    b.level = level;
                    return b.expanded = b.level < expand_level;
                });
                if (scope.treeControl != null) {
                    if (angular.isObject(scope.treeControl)) {
                        tree = scope.treeControl;
                        tree.expand_all = function () {
                            return for_each_branch(function (b, level) {
                                return b.expanded = true;
                            });
                        };
                        tree.collapse_all = function () {
                            return for_each_branch(function (b, level) {
                                return b.expanded = false;
                            });
                        };
                        tree.get_first_branch = function () {
                            n = scope.treeData.length;
                            if (n > 0) {
                                return scope.treeData[0];
                            }
                        };
                        tree.select_first_branch = function () {
                            var b;
                            b = tree.get_first_branch();
                            return tree.select_branch(b);
                        };
                        tree.get_selected_branch = function () {
                            return selected_branch;
                        };
                        tree.get_parent_branch = function (b) {
                            return get_parent(b);
                        };
                        tree.select_branch = function (b) {
                            select_branch(b);
                            return b;
                        };
                        tree.get_children = function (b) {
                            return b.sortedChildren;
                        };
                        tree.select_parent_branch = function (b) {
                            var p;
                            if (b == null) {
                                b = tree.get_selected_branch();
                            }
                            if (b != null) {
                                p = tree.get_parent_branch(b);
                                if (p != null) {
                                    tree.select_branch(p);
                                    return p;
                                }
                            }
                        };
                        tree.expand_all_kids = function (b) {


                            var myKid = scope.treeControl.get_first_child(b);
                            if (myKid) {
                                scope.treeControl.expandSib(myKid);
                            }


                            //var kids = tree.get_children(b);
                            //if (kids.length > 0) {
                            //    if (!kids[0].expanded) {
                            //        kids.forEach(function (kid) {

                            //            scope.treeControl.expand_all_kids(b);
                            //        });
                            //    }

                            //}
                           
                            scope.treeControl.expand_branch(b);


                        }

                        tree.expandSib = function (sib) {

                            var next = scope.treeControl.get_next_sibling(sib);
                            if (next) {
                                scope.treeControl.expandSib(next);
                            }

                            scope.treeControl.expand_all_kids(sib);

                        }
                        tree.add_branch = function (parent, new_branch) {
                            if (parent != null) {
                                parent.sortedChildren.push(new_branch);
                                parent.expanded = true;
                            } else {
                                scope.treeData.push(new_branch);
                            }
                            return new_branch;
                        };
                        tree.add_root_branch = function (new_branch) {
                            tree.add_branch(null, new_branch);
                            return new_branch;
                        };
                        tree.expand_branch = function (b) {
                            if (b == null) {
                                b = tree.get_selected_branch();
                            }
                            if (b != null) {
                                b.expanded = true;
                                return b;
                            }
                        };
                        tree.collapse_branch = function (b) {
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                b.expanded = false;
                                return b;
                            }
                        };
                        tree.get_siblings = function (b) {
                            var p, siblings;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                p = tree.get_parent_branch(b);
                                if (p) {
                                    siblings = p.sortedChildren;
                                } else {
                                    siblings = scope.treeData;
                                }
                                return siblings;
                            }
                        };
                        tree.get_next_sibling = function (b) {
                            var i, siblings;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                siblings = tree.get_siblings(b);
                                n = siblings.length;
                                i = siblings.indexOf(b);
                                if (i < n) {
                                    return siblings[i + 1];
                                }
                            }
                        };
                        tree.get_prev_sibling = function (b) {
                            var i, siblings;
                            if (b == null) {
                                b = selected_branch;
                            }
                            siblings = tree.get_siblings(b);
                            n = siblings.length;
                            i = siblings.indexOf(b);
                            if (i > 0) {
                                return siblings[i - 1];
                            }
                        };
                        tree.select_next_sibling = function (b) {
                            var next;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                next = tree.get_next_sibling(b);
                                if (next != null) {
                                    return tree.select_branch(next);
                                }
                            }
                        };
                        tree.select_prev_sibling = function (b) {
                            var prev;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                prev = tree.get_prev_sibling(b);
                                if (prev != null) {
                                    return tree.select_branch(prev);
                                }
                            }
                        };
                        tree.get_first_child = function (b) {
                            var _ref;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                if (((_ref = b.sortedChildren) != null ? _ref.length : void 0) > 0) {
                                    return b.sortedChildren[0];
                                }
                            }
                        };
                        tree.get_closest_ancestor_next_sibling = function (b) {
                            var next, parent;
                            next = tree.get_next_sibling(b);
                            if (next != null) {
                                return next;
                            } else {
                                parent = tree.get_parent_branch(b);
                                return tree.get_closest_ancestor_next_sibling(parent);
                            }
                        };
                        tree.get_next_branch = function (b) {
                            var next;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                next = tree.get_first_child(b);
                                if (next != null) {
                                    return next;
                                } else {
                                    next = tree.get_closest_ancestor_next_sibling(b);
                                    return next;
                                }
                            }
                        };
                        tree.select_next_branch = function (b) {
                            var next;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                next = tree.get_next_branch(b);
                                if (next != null) {
                                    tree.select_branch(next);
                                    return next;
                                }
                            }
                        };
                        tree.last_descendant = function (b) {
                            var last_child;
                            if (b == null) {
                                b = selected_branch;
                            }

                            n = (b.sortedChildren) ? b.sortedChildren.length : 0;
                            if (n === 0) {
                                return b;
                            } else {
                                last_child = b.sortedChildren[n - 1];
                                return tree.last_descendant(last_child);
                            }
                        };
                        tree.get_prev_branch = function (b) {
                            var parent, prev_sibling;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                prev_sibling = tree.get_prev_sibling(b);
                                if (prev_sibling != null) {
                                    return tree.last_descendant(prev_sibling);
                                } else {
                                    parent = tree.get_parent_branch(b);
                                    return parent;
                                }
                            }
                        };

                        //    if (scope.selectText) {
                        //        for_each_branch(function (b) {
                        //            if (b.name === scope.selectText) {
                        //                return select_branch(b);
                        //            }
                        //        });
                        //    }
                        //});

                        return tree.select_prev_branch = function (b) {
                            var prev;
                            if (b == null) {
                                b = selected_branch;
                            }
                            if (b != null) {
                                prev = tree.get_prev_branch(b);
                                if (prev != null) {
                                    tree.select_branch(prev);
                                    return prev;
                                }
                            }
                        };
                    }
                }
            }
        };
    }
]);
//})();
}(angular.module("app-hd")));;
(function() {
    var app = angular.module("app-hd");

    app.directive('addSpaceAfter', [function () {
        return function (scope, element) {
            if (!scope.$last) {
                element.after('&nbsp;'); // &#32;');
            }
        }
    }]);
}(angular.module("app-hd")));;
/**
 * angular-input-masks
 * Personalized input masks for AngularJS
 * @version v2.1.1
 * @link http://github.com/assisrafael/angular-input-masks
 * @license MIT
 */
require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
 * br-validations
 * A library of validations applicable to several Brazilian data like I.E., CNPJ, CPF and others
 * @version v0.2.4
 * @link http://github.com/the-darc/br-validations
 * @license MIT
 */
(function (root, factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define([], factory);
	} else if (typeof exports === 'object') {
		// Node. Does not work with strict CommonJS, but
		// only CommonJS-like environments that support module.exports,
		// like Node.
		module.exports = factory();
	} else {
		// Browser globals (root is window)
		root.BrV = factory();
	}
}(this, function () {
var CNPJ = {};

CNPJ.validate = function(c) {
	var b = [6,5,4,3,2,9,8,7,6,5,4,3,2];
	c = c.replace(/[^\d]/g,'');

	var r = /^(0{14}|1{14}|2{14}|3{14}|4{14}|5{14}|6{14}|7{14}|8{14}|9{14})$/;
	if (!c || c.length !== 14 || r.test(c)) {
		return false;
	}
	c = c.split('');

	for (var i = 0, n = 0; i < 12; i++) {
		n += c[i] * b[i+1];
	}
	n = 11 - n%11;
	n = n >= 10 ? 0 : n;
	if (parseInt(c[12]) !== n)  {
		return false;
	}

	for (i = 0, n = 0; i <= 12; i++) {
		n += c[i] * b[i];
	}
	n = 11 - n%11;
	n = n >= 10 ? 0 : n;
	if (parseInt(c[13]) !== n)  {
		return false;
	}
	return true;
};


var CPF = {};

CPF.validate = function(cpf) {
	cpf = cpf.replace(/[^\d]+/g,'');
	var r = /^(0{11}|1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11})$/;
	if (!cpf || cpf.length !== 11 || r.test(cpf)) {
		return false;
	}
	function validateDigit(digit) {
		var add = 0;
		var init = digit - 9;
		for (var i = 0; i < 9; i ++) {
			add += parseInt(cpf.charAt(i + init)) * (i+1);
		}
		return (add%11)%10 === parseInt(cpf.charAt(digit));
	}
	return validateDigit(9) && validateDigit(10);
};

var IE = function(uf) {
	if (!(this instanceof IE)) {
		return new IE(uf);
	}

	this.rules = IErules[uf] || [];
	this.rule;
	IE.prototype._defineRule = function(value) {
		this.rule = undefined;
		for (var r = 0; r < this.rules.length && this.rule === undefined; r++) {
			var str = value.replace(/[^\d]/g,'');
			var ruleCandidate = this.rules[r];
			if (str.length === ruleCandidate.chars && (!ruleCandidate.match || ruleCandidate.match.test(value))) {
				this.rule = ruleCandidate;
			}
		}
		return !!this.rule;
	};

	IE.prototype.validate = function(value) {
		if (!value || !this._defineRule(value)) {
			return false;
		}
		return this.rule.validate(value);
	};
};

var IErules = {};

var algorithmSteps = {
	handleStr: {
		onlyNumbers: function(str) {
			return str.replace(/[^\d]/g,'').split('');
		},
		mgSpec: function(str) {
			var s = str.replace(/[^\d]/g,'');
			s = s.substr(0,3)+'0'+s.substr(3, s.length);
			return s.split('');
		}
	},
	sum: {
		normalSum: function(handledStr, pesos) {
			var nums = handledStr;
			var sum = 0;
			for (var i = 0; i < pesos.length; i++) {
				sum += parseInt(nums[i]) * pesos[i];
			}
			return sum;
		},
		individualSum: function(handledStr, pesos) {
			var nums = handledStr;
			var sum = 0;
			for (var i = 0; i < pesos.length; i++) {
				var mult = parseInt(nums[i]) * pesos[i];
				sum += mult%10 + parseInt(mult/10);
			}
			return sum;
		},
		apSpec: function(handledStr, pesos) {
			var sum = this.normalSum(handledStr, pesos);
			var ref = handledStr.join('');
			if (ref >= '030000010' && ref <= '030170009') {
				return sum + 5;
			}
			if (ref >= '030170010' && ref <= '030190229') {
				return sum + 9;
			}
			return sum;
		}
	},
	rest: {
		mod11: function(sum) {
			return sum%11;
		},
		mod10: function(sum) {
			return sum%10;
		},
		mod9: function(sum) {
			return sum%9;
		}
	},
	expectedDV: {
		minusRestOf11: function(rest) {
			return rest < 2 ? 0 : 11 - rest;
		},
		minusRestOf11v2: function(rest) {
			return rest < 2 ? 11 - rest - 10 : 11 - rest;
		},
		minusRestOf10: function(rest) {
			return rest < 1 ? 0 : 10 - rest;
		},
		mod10: function(rest) {
			return rest%10;
		},
		goSpec: function(rest, handledStr) {
			var ref = handledStr.join('');
			if (rest === 1) {
				return ref >= '101031050' && ref <= '101199979' ? 1 : 0;
			}
			return rest === 0 ? 0 : 11 - rest;
		},
		apSpec: function(rest, handledStr) {
			var ref = handledStr.join('');
			if (rest === 0) {
				return ref >= '030170010' && ref <= '030190229' ? 1 : 0;
			}
			return rest === 1 ? 0 : 11 - rest;
		},
		voidFn: function(rest) {
			return rest;
		}
	}
};


/**
 * options {
 *     pesos: Array of values used to operate in sum step
 *     dvPos: Position of the DV to validate considering the handledStr
 *     algorithmSteps: The four DV's validation algorithm steps names
 * }
 */
function validateDV(value, options) {
	var steps = options.algorithmSteps;

	// Step 01: Handle String
	var handledStr = algorithmSteps.handleStr[steps[0]](value);

	// Step 02: Sum chars
	var sum = algorithmSteps.sum[steps[1]](handledStr, options.pesos);

	// Step 03: Rest calculation
	var rest = algorithmSteps.rest[steps[2]](sum);

	// Fixed Step: Get current DV
	var currentDV = parseInt(handledStr[options.dvpos]);

	// Step 04: Expected DV calculation
	var expectedDV = algorithmSteps.expectedDV[steps[3]](rest, handledStr);

	// Fixed step: DV verification
	return currentDV === expectedDV;
}

function validateIE(value, rule) {
	if (rule.match && !rule.match.test(value)) {
		return false;
	}
	for (var i = 0; i < rule.dvs.length; i++) {
		// console.log('>> >> dv'+i);
		if (!validateDV(value, rule.dvs[i])) {
			return false;
		}
	}
	return true;
}

IErules.PE = [{
	//mask: new StringMask('0000000-00'),
	chars: 9,
	dvs: [{
		dvpos: 7,
		pesos: [8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	// mask: new StringMask('00.0.000.0000000-0'),
	chars: 14,
	pesos: [[1,2,3,4,5,9,8,7,6,5,4,3,2]],
	dvs: [{
		dvpos: 13,
		pesos: [5,4,3,2,1,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11v2']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.RS = [{
	// mask: new StringMask('000/0000000'),
	chars: 10,
	dvs: [{
		dvpos: 9,
		pesos: [2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.AC = [{
	// mask: new StringMask('00.000.000/000-00'),
	chars: 13,
	match: /^01/,
	dvs: [{
		dvpos: 11,
		pesos: [4,3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 12,
		pesos: [5,4,3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.MG = [{
	// mask: new StringMask('000.000.000/0000'),
	chars: 13,
	dvs: [{
		dvpos: 12,
		pesos: [1,2,1,2,1,2,1,2,1,2,1,2],
		algorithmSteps: ['mgSpec', 'individualSum', 'mod10', 'minusRestOf10']
	},{
		dvpos: 12,
		pesos: [3,2,11,10,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.SP = [{
	// mask: new StringMask('000.000.000.000'),
	chars: 12,
	match: /^[0-9]/,
	dvs: [{
		dvpos: 8,
		pesos: [1,3,4,5,6,7,8,10],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'mod10']
	},{
		dvpos: 11,
		pesos: [3,2,10,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'mod10']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	// mask: new StringMask('P-00000000.0/000')
	chars: 12,
	match: /^P/i,
	dvs: [{
		dvpos: 8,
		pesos: [1,3,4,5,6,7,8,10],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'mod10']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.DF = [{
	// mask: new StringMask('00000000000-00'),
	chars: 13,
	dvs: [{
		dvpos: 11,
		pesos: [4,3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 12,
		pesos: [5,4,3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.ES = [{
	// mask: new StringMask('000.000.00-0')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.BA = [{
	// mask: new StringMask('000000-00')
	chars: 8,
	match: /^[0123458]/,
	dvs: [{
		dvpos: 7,
		pesos: [7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod10', 'minusRestOf10']
	},{
		dvpos: 6,
		pesos: [8,7,6,5,4,3,0,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod10', 'minusRestOf10']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	chars: 8,
	match: /^[679]/,
	dvs: [{
		dvpos: 7,
		pesos: [7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 6,
		pesos: [8,7,6,5,4,3,0,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	// mask: new StringMask('0000000-00')
	chars: 9,
	match: /^[0-9][0123458]/,
	dvs: [{
		dvpos: 8,
		pesos: [8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod10', 'minusRestOf10']
	},{
		dvpos: 7,
		pesos: [9,8,7,6,5,4,3,0,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod10', 'minusRestOf10']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	chars: 9,
	match: /^[0-9][679]/,
	dvs: [{
		dvpos: 8,
		pesos: [8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 7,
		pesos: [9,8,7,6,5,4,3,0,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.AM = [{
	//mask: new StringMask('00.000.000-0')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.RN = [{
	// {mask: new StringMask('00.000.000-0')
	chars: 9,
	match: /^20/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
},{
	// {mask: new StringMask('00.0.000.000-0'), chars: 10}
	chars: 10,
	match: /^20/,
	dvs: [{
		dvpos: 8,
		pesos: [10,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.RO = [{
	// mask: new StringMask('0000000000000-0')
	chars: 14,
	dvs: [{
		dvpos: 13,
		pesos: [6,5,4,3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.PR = [{
	// mask: new StringMask('00000000-00')
	chars: 10,
	dvs: [{
		dvpos: 8,
		pesos: [3,2,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	},{
		dvpos: 9,
		pesos: [4,3,2,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.SC = [{
	// {mask: new StringMask('000.000.000'), uf: 'SANTA CATARINA'}
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.RJ = [{
	// {mask: new StringMask('00.000.00-0'), uf: 'RIO DE JANEIRO'}
	chars: 8,
	dvs: [{
		dvpos: 7,
		pesos: [2,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.PA = [{
	// {mask: new StringMask('00-000000-0')
	chars: 9,
	match: /^15/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.SE = [{
	// {mask: new StringMask('00000000-0')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.PB = [{
	// {mask: new StringMask('00000000-0')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.CE = [{
	// {mask: new StringMask('00000000-0')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.PI = [{
	// {mask: new StringMask('000000000')
	chars: 9,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.MA = [{
	// {mask: new StringMask('000000000')
	chars: 9,
	match: /^12/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.MT = [{
	// {mask: new StringMask('0000000000-0')
	chars: 11,
	dvs: [{
		dvpos: 10,
		pesos: [3,2,9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.MS = [{
	// {mask: new StringMask('000000000')
	chars: 9,
	match: /^28/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.TO = [{
	// {mask: new StringMask('00000000000'),
	chars: 11,
	match: /^[0-9]{2}((0[123])|(99))/,
	dvs: [{
		dvpos: 10,
		pesos: [9,8,0,0,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.AL = [{
	// {mask: new StringMask('000000000')
	chars: 9,
	match: /^24[03578]/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'minusRestOf11']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.RR = [{
	// {mask: new StringMask('00000000-0')
	chars: 9,
	match: /^24/,
	dvs: [{
		dvpos: 8,
		pesos: [1,2,3,4,5,6,7,8],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod9', 'voidFn']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.GO = [{
	// {mask: new StringMask('00.000.000-0')
	chars: 9,
	match: /^1[015]/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'normalSum', 'mod11', 'goSpec']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

IErules.AP = [{
	// {mask: new StringMask('000000000')
	chars: 9,
	match: /^03/,
	dvs: [{
		dvpos: 8,
		pesos: [9,8,7,6,5,4,3,2],
		algorithmSteps: ['onlyNumbers', 'apSpec', 'mod11', 'apSpec']
	}],
	validate: function(value) { return validateIE(value, this); }
}];

	return {
		ie: IE,
		cpf: CPF,
		cnpj: CNPJ
	};
}));
},{}],2:[function(require,module,exports){
//! moment.js
//! version : 2.12.0
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com

;(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    global.moment = factory()
}(this, function () { 'use strict';

    var hookCallback;

    function utils_hooks__hooks () {
        return hookCallback.apply(null, arguments);
    }

    // This is done to register the method called with moment()
    // without creating circular dependencies.
    function setHookCallback (callback) {
        hookCallback = callback;
    }

    function isArray(input) {
        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
    }

    function isDate(input) {
        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
    }

    function map(arr, fn) {
        var res = [], i;
        for (i = 0; i < arr.length; ++i) {
            res.push(fn(arr[i], i));
        }
        return res;
    }

    function hasOwnProp(a, b) {
        return Object.prototype.hasOwnProperty.call(a, b);
    }

    function extend(a, b) {
        for (var i in b) {
            if (hasOwnProp(b, i)) {
                a[i] = b[i];
            }
        }

        if (hasOwnProp(b, 'toString')) {
            a.toString = b.toString;
        }

        if (hasOwnProp(b, 'valueOf')) {
            a.valueOf = b.valueOf;
        }

        return a;
    }

    function create_utc__createUTC (input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, true).utc();
    }

    function defaultParsingFlags() {
        // We need to deep clone this object.
        return {
            empty           : false,
            unusedTokens    : [],
            unusedInput     : [],
            overflow        : -2,
            charsLeftOver   : 0,
            nullInput       : false,
            invalidMonth    : null,
            invalidFormat   : false,
            userInvalidated : false,
            iso             : false
        };
    }

    function getParsingFlags(m) {
        if (m._pf == null) {
            m._pf = defaultParsingFlags();
        }
        return m._pf;
    }

    function valid__isValid(m) {
        if (m._isValid == null) {
            var flags = getParsingFlags(m);
            m._isValid = !isNaN(m._d.getTime()) &&
                flags.overflow < 0 &&
                !flags.empty &&
                !flags.invalidMonth &&
                !flags.invalidWeekday &&
                !flags.nullInput &&
                !flags.invalidFormat &&
                !flags.userInvalidated;

            if (m._strict) {
                m._isValid = m._isValid &&
                    flags.charsLeftOver === 0 &&
                    flags.unusedTokens.length === 0 &&
                    flags.bigHour === undefined;
            }
        }
        return m._isValid;
    }

    function valid__createInvalid (flags) {
        var m = create_utc__createUTC(NaN);
        if (flags != null) {
            extend(getParsingFlags(m), flags);
        }
        else {
            getParsingFlags(m).userInvalidated = true;
        }

        return m;
    }

    function isUndefined(input) {
        return input === void 0;
    }

    // Plugins that add properties should also add the key here (null value),
    // so we can properly clone ourselves.
    var momentProperties = utils_hooks__hooks.momentProperties = [];

    function copyConfig(to, from) {
        var i, prop, val;

        if (!isUndefined(from._isAMomentObject)) {
            to._isAMomentObject = from._isAMomentObject;
        }
        if (!isUndefined(from._i)) {
            to._i = from._i;
        }
        if (!isUndefined(from._f)) {
            to._f = from._f;
        }
        if (!isUndefined(from._l)) {
            to._l = from._l;
        }
        if (!isUndefined(from._strict)) {
            to._strict = from._strict;
        }
        if (!isUndefined(from._tzm)) {
            to._tzm = from._tzm;
        }
        if (!isUndefined(from._isUTC)) {
            to._isUTC = from._isUTC;
        }
        if (!isUndefined(from._offset)) {
            to._offset = from._offset;
        }
        if (!isUndefined(from._pf)) {
            to._pf = getParsingFlags(from);
        }
        if (!isUndefined(from._locale)) {
            to._locale = from._locale;
        }

        if (momentProperties.length > 0) {
            for (i in momentProperties) {
                prop = momentProperties[i];
                val = from[prop];
                if (!isUndefined(val)) {
                    to[prop] = val;
                }
            }
        }

        return to;
    }

    var updateInProgress = false;

    // Moment prototype object
    function Moment(config) {
        copyConfig(this, config);
        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
        // Prevent infinite loop in case updateOffset creates new moment
        // objects.
        if (updateInProgress === false) {
            updateInProgress = true;
            utils_hooks__hooks.updateOffset(this);
            updateInProgress = false;
        }
    }

    function isMoment (obj) {
        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
    }

    function absFloor (number) {
        if (number < 0) {
            return Math.ceil(number);
        } else {
            return Math.floor(number);
        }
    }

    function toInt(argumentForCoercion) {
        var coercedNumber = +argumentForCoercion,
            value = 0;

        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
            value = absFloor(coercedNumber);
        }

        return value;
    }

    // compare two arrays, return the number of differences
    function compareArrays(array1, array2, dontConvert) {
        var len = Math.min(array1.length, array2.length),
            lengthDiff = Math.abs(array1.length - array2.length),
            diffs = 0,
            i;
        for (i = 0; i < len; i++) {
            if ((dontConvert && array1[i] !== array2[i]) ||
                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
                diffs++;
            }
        }
        return diffs + lengthDiff;
    }

    function warn(msg) {
        if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
                (typeof console !==  'undefined') && console.warn) {
            console.warn('Deprecation warning: ' + msg);
        }
    }

    function deprecate(msg, fn) {
        var firstTime = true;

        return extend(function () {
            if (firstTime) {
                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
                firstTime = false;
            }
            return fn.apply(this, arguments);
        }, fn);
    }

    var deprecations = {};

    function deprecateSimple(name, msg) {
        if (!deprecations[name]) {
            warn(msg);
            deprecations[name] = true;
        }
    }

    utils_hooks__hooks.suppressDeprecationWarnings = false;

    function isFunction(input) {
        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
    }

    function isObject(input) {
        return Object.prototype.toString.call(input) === '[object Object]';
    }

    function locale_set__set (config) {
        var prop, i;
        for (i in config) {
            prop = config[i];
            if (isFunction(prop)) {
                this[i] = prop;
            } else {
                this['_' + i] = prop;
            }
        }
        this._config = config;
        // Lenient ordinal parsing accepts just a number in addition to
        // number + (possibly) stuff coming from _ordinalParseLenient.
        this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
    }

    function mergeConfigs(parentConfig, childConfig) {
        var res = extend({}, parentConfig), prop;
        for (prop in childConfig) {
            if (hasOwnProp(childConfig, prop)) {
                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
                    res[prop] = {};
                    extend(res[prop], parentConfig[prop]);
                    extend(res[prop], childConfig[prop]);
                } else if (childConfig[prop] != null) {
                    res[prop] = childConfig[prop];
                } else {
                    delete res[prop];
                }
            }
        }
        return res;
    }

    function Locale(config) {
        if (config != null) {
            this.set(config);
        }
    }

    // internal storage for locale config files
    var locales = {};
    var globalLocale;

    function normalizeLocale(key) {
        return key ? key.toLowerCase().replace('_', '-') : key;
    }

    // pick the locale from the array
    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
    function chooseLocale(names) {
        var i = 0, j, next, locale, split;

        while (i < names.length) {
            split = normalizeLocale(names[i]).split('-');
            j = split.length;
            next = normalizeLocale(names[i + 1]);
            next = next ? next.split('-') : null;
            while (j > 0) {
                locale = loadLocale(split.slice(0, j).join('-'));
                if (locale) {
                    return locale;
                }
                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
                    //the next array item is better than a shallower substring of this one
                    break;
                }
                j--;
            }
            i++;
        }
        return null;
    }

    function loadLocale(name) {
        var oldLocale = null;
        // TODO: Find a better way to register and load all the locales in Node
        if (!locales[name] && (typeof module !== 'undefined') &&
                module && module.exports) {
            try {
                oldLocale = globalLocale._abbr;
                require('./locale/' + name);
                // because defineLocale currently also sets the global locale, we
                // want to undo that for lazy loaded locales
                locale_locales__getSetGlobalLocale(oldLocale);
            } catch (e) { }
        }
        return locales[name];
    }

    // This function will load locale and then set the global locale.  If
    // no arguments are passed in, it will simply return the current global
    // locale key.
    function locale_locales__getSetGlobalLocale (key, values) {
        var data;
        if (key) {
            if (isUndefined(values)) {
                data = locale_locales__getLocale(key);
            }
            else {
                data = defineLocale(key, values);
            }

            if (data) {
                // moment.duration._locale = moment._locale = data;
                globalLocale = data;
            }
        }

        return globalLocale._abbr;
    }

    function defineLocale (name, config) {
        if (config !== null) {
            config.abbr = name;
            if (locales[name] != null) {
                deprecateSimple('defineLocaleOverride',
                        'use moment.updateLocale(localeName, config) to change ' +
                        'an existing locale. moment.defineLocale(localeName, ' +
                        'config) should only be used for creating a new locale');
                config = mergeConfigs(locales[name]._config, config);
            } else if (config.parentLocale != null) {
                if (locales[config.parentLocale] != null) {
                    config = mergeConfigs(locales[config.parentLocale]._config, config);
                } else {
                    // treat as if there is no base config
                    deprecateSimple('parentLocaleUndefined',
                            'specified parentLocale is not defined yet');
                }
            }
            locales[name] = new Locale(config);

            // backwards compat for now: also set the locale
            locale_locales__getSetGlobalLocale(name);

            return locales[name];
        } else {
            // useful for testing
            delete locales[name];
            return null;
        }
    }

    function updateLocale(name, config) {
        if (config != null) {
            var locale;
            if (locales[name] != null) {
                config = mergeConfigs(locales[name]._config, config);
            }
            locale = new Locale(config);
            locale.parentLocale = locales[name];
            locales[name] = locale;

            // backwards compat for now: also set the locale
            locale_locales__getSetGlobalLocale(name);
        } else {
            // pass null for config to unupdate, useful for tests
            if (locales[name] != null) {
                if (locales[name].parentLocale != null) {
                    locales[name] = locales[name].parentLocale;
                } else if (locales[name] != null) {
                    delete locales[name];
                }
            }
        }
        return locales[name];
    }

    // returns locale data
    function locale_locales__getLocale (key) {
        var locale;

        if (key && key._locale && key._locale._abbr) {
            key = key._locale._abbr;
        }

        if (!key) {
            return globalLocale;
        }

        if (!isArray(key)) {
            //short-circuit everything else
            locale = loadLocale(key);
            if (locale) {
                return locale;
            }
            key = [key];
        }

        return chooseLocale(key);
    }

    function locale_locales__listLocales() {
        return Object.keys(locales);
    }

    var aliases = {};

    function addUnitAlias (unit, shorthand) {
        var lowerCase = unit.toLowerCase();
        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
    }

    function normalizeUnits(units) {
        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
    }

    function normalizeObjectUnits(inputObject) {
        var normalizedInput = {},
            normalizedProp,
            prop;

        for (prop in inputObject) {
            if (hasOwnProp(inputObject, prop)) {
                normalizedProp = normalizeUnits(prop);
                if (normalizedProp) {
                    normalizedInput[normalizedProp] = inputObject[prop];
                }
            }
        }

        return normalizedInput;
    }

    function makeGetSet (unit, keepTime) {
        return function (value) {
            if (value != null) {
                get_set__set(this, unit, value);
                utils_hooks__hooks.updateOffset(this, keepTime);
                return this;
            } else {
                return get_set__get(this, unit);
            }
        };
    }

    function get_set__get (mom, unit) {
        return mom.isValid() ?
            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
    }

    function get_set__set (mom, unit, value) {
        if (mom.isValid()) {
            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
        }
    }

    // MOMENTS

    function getSet (units, value) {
        var unit;
        if (typeof units === 'object') {
            for (unit in units) {
                this.set(unit, units[unit]);
            }
        } else {
            units = normalizeUnits(units);
            if (isFunction(this[units])) {
                return this[units](value);
            }
        }
        return this;
    }

    function zeroFill(number, targetLength, forceSign) {
        var absNumber = '' + Math.abs(number),
            zerosToFill = targetLength - absNumber.length,
            sign = number >= 0;
        return (sign ? (forceSign ? '+' : '') : '-') +
            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
    }

    var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;

    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;

    var formatFunctions = {};

    var formatTokenFunctions = {};

    // token:    'M'
    // padded:   ['MM', 2]
    // ordinal:  'Mo'
    // callback: function () { this.month() + 1 }
    function addFormatToken (token, padded, ordinal, callback) {
        var func = callback;
        if (typeof callback === 'string') {
            func = function () {
                return this[callback]();
            };
        }
        if (token) {
            formatTokenFunctions[token] = func;
        }
        if (padded) {
            formatTokenFunctions[padded[0]] = function () {
                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
            };
        }
        if (ordinal) {
            formatTokenFunctions[ordinal] = function () {
                return this.localeData().ordinal(func.apply(this, arguments), token);
            };
        }
    }

    function removeFormattingTokens(input) {
        if (input.match(/\[[\s\S]/)) {
            return input.replace(/^\[|\]$/g, '');
        }
        return input.replace(/\\/g, '');
    }

    function makeFormatFunction(format) {
        var array = format.match(formattingTokens), i, length;

        for (i = 0, length = array.length; i < length; i++) {
            if (formatTokenFunctions[array[i]]) {
                array[i] = formatTokenFunctions[array[i]];
            } else {
                array[i] = removeFormattingTokens(array[i]);
            }
        }

        return function (mom) {
            var output = '';
            for (i = 0; i < length; i++) {
                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
            }
            return output;
        };
    }

    // format date using native date object
    function formatMoment(m, format) {
        if (!m.isValid()) {
            return m.localeData().invalidDate();
        }

        format = expandFormat(format, m.localeData());
        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);

        return formatFunctions[format](m);
    }

    function expandFormat(format, locale) {
        var i = 5;

        function replaceLongDateFormatTokens(input) {
            return locale.longDateFormat(input) || input;
        }

        localFormattingTokens.lastIndex = 0;
        while (i >= 0 && localFormattingTokens.test(format)) {
            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
            localFormattingTokens.lastIndex = 0;
            i -= 1;
        }

        return format;
    }

    var match1         = /\d/;            //       0 - 9
    var match2         = /\d\d/;          //      00 - 99
    var match3         = /\d{3}/;         //     000 - 999
    var match4         = /\d{4}/;         //    0000 - 9999
    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
    var match1to2      = /\d\d?/;         //       0 - 99
    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
    var match1to3      = /\d{1,3}/;       //       0 - 999
    var match1to4      = /\d{1,4}/;       //       0 - 9999
    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999

    var matchUnsigned  = /\d+/;           //       0 - inf
    var matchSigned    = /[+-]?\d+/;      //    -inf - inf

    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z

    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123

    // any word (or two) characters or numbers including two/three word month in arabic.
    // includes scottish gaelic two word and hyphenated months
    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;


    var regexes = {};

    function addRegexToken (token, regex, strictRegex) {
        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
            return (isStrict && strictRegex) ? strictRegex : regex;
        };
    }

    function getParseRegexForToken (token, config) {
        if (!hasOwnProp(regexes, token)) {
            return new RegExp(unescapeFormat(token));
        }

        return regexes[token](config._strict, config._locale);
    }

    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
    function unescapeFormat(s) {
        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
            return p1 || p2 || p3 || p4;
        }));
    }

    function regexEscape(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }

    var tokens = {};

    function addParseToken (token, callback) {
        var i, func = callback;
        if (typeof token === 'string') {
            token = [token];
        }
        if (typeof callback === 'number') {
            func = function (input, array) {
                array[callback] = toInt(input);
            };
        }
        for (i = 0; i < token.length; i++) {
            tokens[token[i]] = func;
        }
    }

    function addWeekParseToken (token, callback) {
        addParseToken(token, function (input, array, config, token) {
            config._w = config._w || {};
            callback(input, config._w, config, token);
        });
    }

    function addTimeToArrayFromToken(token, input, config) {
        if (input != null && hasOwnProp(tokens, token)) {
            tokens[token](input, config._a, config, token);
        }
    }

    var YEAR = 0;
    var MONTH = 1;
    var DATE = 2;
    var HOUR = 3;
    var MINUTE = 4;
    var SECOND = 5;
    var MILLISECOND = 6;
    var WEEK = 7;
    var WEEKDAY = 8;

    function daysInMonth(year, month) {
        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
    }

    // FORMATTING

    addFormatToken('M', ['MM', 2], 'Mo', function () {
        return this.month() + 1;
    });

    addFormatToken('MMM', 0, 0, function (format) {
        return this.localeData().monthsShort(this, format);
    });

    addFormatToken('MMMM', 0, 0, function (format) {
        return this.localeData().months(this, format);
    });

    // ALIASES

    addUnitAlias('month', 'M');

    // PARSING

    addRegexToken('M',    match1to2);
    addRegexToken('MM',   match1to2, match2);
    addRegexToken('MMM',  function (isStrict, locale) {
        return locale.monthsShortRegex(isStrict);
    });
    addRegexToken('MMMM', function (isStrict, locale) {
        return locale.monthsRegex(isStrict);
    });

    addParseToken(['M', 'MM'], function (input, array) {
        array[MONTH] = toInt(input) - 1;
    });

    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
        var month = config._locale.monthsParse(input, token, config._strict);
        // if we didn't find a month name, mark the date as invalid.
        if (month != null) {
            array[MONTH] = month;
        } else {
            getParsingFlags(config).invalidMonth = input;
        }
    });

    // LOCALES

    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
    function localeMonths (m, format) {
        return isArray(this._months) ? this._months[m.month()] :
            this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
    }

    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
    function localeMonthsShort (m, format) {
        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
    }

    function localeMonthsParse (monthName, format, strict) {
        var i, mom, regex;

        if (!this._monthsParse) {
            this._monthsParse = [];
            this._longMonthsParse = [];
            this._shortMonthsParse = [];
        }

        for (i = 0; i < 12; i++) {
            // make the regex if we don't have it already
            mom = create_utc__createUTC([2000, i]);
            if (strict && !this._longMonthsParse[i]) {
                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
            }
            if (!strict && !this._monthsParse[i]) {
                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
            }
            // test the regex
            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
                return i;
            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
                return i;
            } else if (!strict && this._monthsParse[i].test(monthName)) {
                return i;
            }
        }
    }

    // MOMENTS

    function setMonth (mom, value) {
        var dayOfMonth;

        if (!mom.isValid()) {
            // No op
            return mom;
        }

        if (typeof value === 'string') {
            if (/^\d+$/.test(value)) {
                value = toInt(value);
            } else {
                value = mom.localeData().monthsParse(value);
                // TODO: Another silent failure?
                if (typeof value !== 'number') {
                    return mom;
                }
            }
        }

        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
        return mom;
    }

    function getSetMonth (value) {
        if (value != null) {
            setMonth(this, value);
            utils_hooks__hooks.updateOffset(this, true);
            return this;
        } else {
            return get_set__get(this, 'Month');
        }
    }

    function getDaysInMonth () {
        return daysInMonth(this.year(), this.month());
    }

    var defaultMonthsShortRegex = matchWord;
    function monthsShortRegex (isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, '_monthsRegex')) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsShortStrictRegex;
            } else {
                return this._monthsShortRegex;
            }
        } else {
            return this._monthsShortStrictRegex && isStrict ?
                this._monthsShortStrictRegex : this._monthsShortRegex;
        }
    }

    var defaultMonthsRegex = matchWord;
    function monthsRegex (isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, '_monthsRegex')) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsStrictRegex;
            } else {
                return this._monthsRegex;
            }
        } else {
            return this._monthsStrictRegex && isStrict ?
                this._monthsStrictRegex : this._monthsRegex;
        }
    }

    function computeMonthsParse () {
        function cmpLenRev(a, b) {
            return b.length - a.length;
        }

        var shortPieces = [], longPieces = [], mixedPieces = [],
            i, mom;
        for (i = 0; i < 12; i++) {
            // make the regex if we don't have it already
            mom = create_utc__createUTC([2000, i]);
            shortPieces.push(this.monthsShort(mom, ''));
            longPieces.push(this.months(mom, ''));
            mixedPieces.push(this.months(mom, ''));
            mixedPieces.push(this.monthsShort(mom, ''));
        }
        // Sorting makes sure if one month (or abbr) is a prefix of another it
        // will match the longer piece.
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
        for (i = 0; i < 12; i++) {
            shortPieces[i] = regexEscape(shortPieces[i]);
            longPieces[i] = regexEscape(longPieces[i]);
            mixedPieces[i] = regexEscape(mixedPieces[i]);
        }

        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
        this._monthsShortRegex = this._monthsRegex;
        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')$', 'i');
        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')$', 'i');
    }

    function checkOverflow (m) {
        var overflow;
        var a = m._a;

        if (a && getParsingFlags(m).overflow === -2) {
            overflow =
                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
                -1;

            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
                overflow = DATE;
            }
            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
                overflow = WEEK;
            }
            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
                overflow = WEEKDAY;
            }

            getParsingFlags(m).overflow = overflow;
        }

        return m;
    }

    // iso 8601 regex
    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;

    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;

    var isoDates = [
        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
        ['YYYY-DDD', /\d{4}-\d{3}/],
        ['YYYY-MM', /\d{4}-\d\d/, false],
        ['YYYYYYMMDD', /[+-]\d{10}/],
        ['YYYYMMDD', /\d{8}/],
        // YYYYMM is NOT allowed by the standard
        ['GGGG[W]WWE', /\d{4}W\d{3}/],
        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
        ['YYYYDDD', /\d{7}/]
    ];

    // iso time formats and regexes
    var isoTimes = [
        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
        ['HH:mm', /\d\d:\d\d/],
        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
        ['HHmmss', /\d\d\d\d\d\d/],
        ['HHmm', /\d\d\d\d/],
        ['HH', /\d\d/]
    ];

    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;

    // date from iso format
    function configFromISO(config) {
        var i, l,
            string = config._i,
            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
            allowTime, dateFormat, timeFormat, tzFormat;

        if (match) {
            getParsingFlags(config).iso = true;

            for (i = 0, l = isoDates.length; i < l; i++) {
                if (isoDates[i][1].exec(match[1])) {
                    dateFormat = isoDates[i][0];
                    allowTime = isoDates[i][2] !== false;
                    break;
                }
            }
            if (dateFormat == null) {
                config._isValid = false;
                return;
            }
            if (match[3]) {
                for (i = 0, l = isoTimes.length; i < l; i++) {
                    if (isoTimes[i][1].exec(match[3])) {
                        // match[2] should be 'T' or space
                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
                        break;
                    }
                }
                if (timeFormat == null) {
                    config._isValid = false;
                    return;
                }
            }
            if (!allowTime && timeFormat != null) {
                config._isValid = false;
                return;
            }
            if (match[4]) {
                if (tzRegex.exec(match[4])) {
                    tzFormat = 'Z';
                } else {
                    config._isValid = false;
                    return;
                }
            }
            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
            configFromStringAndFormat(config);
        } else {
            config._isValid = false;
        }
    }

    // date from iso format or fallback
    function configFromString(config) {
        var matched = aspNetJsonRegex.exec(config._i);

        if (matched !== null) {
            config._d = new Date(+matched[1]);
            return;
        }

        configFromISO(config);
        if (config._isValid === false) {
            delete config._isValid;
            utils_hooks__hooks.createFromInputFallback(config);
        }
    }

    utils_hooks__hooks.createFromInputFallback = deprecate(
        'moment construction falls back to js Date. This is ' +
        'discouraged and will be removed in upcoming major ' +
        'release. Please refer to ' +
        'https://github.com/moment/moment/issues/1407 for more info.',
        function (config) {
            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
        }
    );

    function createDate (y, m, d, h, M, s, ms) {
        //can't just apply() to create a date:
        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
        var date = new Date(y, m, d, h, M, s, ms);

        //the date constructor remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
            date.setFullYear(y);
        }
        return date;
    }

    function createUTCDate (y) {
        var date = new Date(Date.UTC.apply(null, arguments));

        //the Date.UTC function remaps years 0-99 to 1900-1999
        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
            date.setUTCFullYear(y);
        }
        return date;
    }

    // FORMATTING

    addFormatToken('Y', 0, 0, function () {
        var y = this.year();
        return y <= 9999 ? '' + y : '+' + y;
    });

    addFormatToken(0, ['YY', 2], 0, function () {
        return this.year() % 100;
    });

    addFormatToken(0, ['YYYY',   4],       0, 'year');
    addFormatToken(0, ['YYYYY',  5],       0, 'year');
    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');

    // ALIASES

    addUnitAlias('year', 'y');

    // PARSING

    addRegexToken('Y',      matchSigned);
    addRegexToken('YY',     match1to2, match2);
    addRegexToken('YYYY',   match1to4, match4);
    addRegexToken('YYYYY',  match1to6, match6);
    addRegexToken('YYYYYY', match1to6, match6);

    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
    addParseToken('YYYY', function (input, array) {
        array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
    });
    addParseToken('YY', function (input, array) {
        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
    });
    addParseToken('Y', function (input, array) {
        array[YEAR] = parseInt(input, 10);
    });

    // HELPERS

    function daysInYear(year) {
        return isLeapYear(year) ? 366 : 365;
    }

    function isLeapYear(year) {
        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
    }

    // HOOKS

    utils_hooks__hooks.parseTwoDigitYear = function (input) {
        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
    };

    // MOMENTS

    var getSetYear = makeGetSet('FullYear', false);

    function getIsLeapYear () {
        return isLeapYear(this.year());
    }

    // start-of-first-week - start-of-year
    function firstWeekOffset(year, dow, doy) {
        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
            fwd = 7 + dow - doy,
            // first-week day local weekday -- which local weekday is fwd
            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;

        return -fwdlw + fwd - 1;
    }

    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
        var localWeekday = (7 + weekday - dow) % 7,
            weekOffset = firstWeekOffset(year, dow, doy),
            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
            resYear, resDayOfYear;

        if (dayOfYear <= 0) {
            resYear = year - 1;
            resDayOfYear = daysInYear(resYear) + dayOfYear;
        } else if (dayOfYear > daysInYear(year)) {
            resYear = year + 1;
            resDayOfYear = dayOfYear - daysInYear(year);
        } else {
            resYear = year;
            resDayOfYear = dayOfYear;
        }

        return {
            year: resYear,
            dayOfYear: resDayOfYear
        };
    }

    function weekOfYear(mom, dow, doy) {
        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
            resWeek, resYear;

        if (week < 1) {
            resYear = mom.year() - 1;
            resWeek = week + weeksInYear(resYear, dow, doy);
        } else if (week > weeksInYear(mom.year(), dow, doy)) {
            resWeek = week - weeksInYear(mom.year(), dow, doy);
            resYear = mom.year() + 1;
        } else {
            resYear = mom.year();
            resWeek = week;
        }

        return {
            week: resWeek,
            year: resYear
        };
    }

    function weeksInYear(year, dow, doy) {
        var weekOffset = firstWeekOffset(year, dow, doy),
            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
    }

    // Pick the first defined of two or three arguments.
    function defaults(a, b, c) {
        if (a != null) {
            return a;
        }
        if (b != null) {
            return b;
        }
        return c;
    }

    function currentDateArray(config) {
        // hooks is actually the exported moment object
        var nowValue = new Date(utils_hooks__hooks.now());
        if (config._useUTC) {
            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
        }
        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
    }

    // convert an array to a date.
    // the array should mirror the parameters below
    // note: all values past the year are optional and will default to the lowest possible value.
    // [year, month, day , hour, minute, second, millisecond]
    function configFromArray (config) {
        var i, date, input = [], currentDate, yearToUse;

        if (config._d) {
            return;
        }

        currentDate = currentDateArray(config);

        //compute day of the year from weeks and weekdays
        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
            dayOfYearFromWeekInfo(config);
        }

        //if the day of the year is set, figure out what it is
        if (config._dayOfYear) {
            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);

            if (config._dayOfYear > daysInYear(yearToUse)) {
                getParsingFlags(config)._overflowDayOfYear = true;
            }

            date = createUTCDate(yearToUse, 0, config._dayOfYear);
            config._a[MONTH] = date.getUTCMonth();
            config._a[DATE] = date.getUTCDate();
        }

        // Default to current date.
        // * if no year, month, day of month are given, default to today
        // * if day of month is given, default month and year
        // * if month is given, default only year
        // * if year is given, don't default anything
        for (i = 0; i < 3 && config._a[i] == null; ++i) {
            config._a[i] = input[i] = currentDate[i];
        }

        // Zero out whatever was not defaulted, including time
        for (; i < 7; i++) {
            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
        }

        // Check for 24:00:00.000
        if (config._a[HOUR] === 24 &&
                config._a[MINUTE] === 0 &&
                config._a[SECOND] === 0 &&
                config._a[MILLISECOND] === 0) {
            config._nextDay = true;
            config._a[HOUR] = 0;
        }

        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
        // Apply timezone offset from input. The actual utcOffset can be changed
        // with parseZone.
        if (config._tzm != null) {
            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
        }

        if (config._nextDay) {
            config._a[HOUR] = 24;
        }
    }

    function dayOfYearFromWeekInfo(config) {
        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;

        w = config._w;
        if (w.GG != null || w.W != null || w.E != null) {
            dow = 1;
            doy = 4;

            // TODO: We need to take the current isoWeekYear, but that depends on
            // how we interpret now (local, utc, fixed offset). So create
            // a now version of current config (take local/utc/offset flags, and
            // create now).
            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
            week = defaults(w.W, 1);
            weekday = defaults(w.E, 1);
            if (weekday < 1 || weekday > 7) {
                weekdayOverflow = true;
            }
        } else {
            dow = config._locale._week.dow;
            doy = config._locale._week.doy;

            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
            week = defaults(w.w, 1);

            if (w.d != null) {
                // weekday -- low day numbers are considered next week
                weekday = w.d;
                if (weekday < 0 || weekday > 6) {
                    weekdayOverflow = true;
                }
            } else if (w.e != null) {
                // local weekday -- counting starts from begining of week
                weekday = w.e + dow;
                if (w.e < 0 || w.e > 6) {
                    weekdayOverflow = true;
                }
            } else {
                // default to begining of week
                weekday = dow;
            }
        }
        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
            getParsingFlags(config)._overflowWeeks = true;
        } else if (weekdayOverflow != null) {
            getParsingFlags(config)._overflowWeekday = true;
        } else {
            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
            config._a[YEAR] = temp.year;
            config._dayOfYear = temp.dayOfYear;
        }
    }

    // constant that refers to the ISO standard
    utils_hooks__hooks.ISO_8601 = function () {};

    // date from string and format string
    function configFromStringAndFormat(config) {
        // TODO: Move this to another part of the creation flow to prevent circular deps
        if (config._f === utils_hooks__hooks.ISO_8601) {
            configFromISO(config);
            return;
        }

        config._a = [];
        getParsingFlags(config).empty = true;

        // This array is used to make a Date, either with `new Date` or `Date.UTC`
        var string = '' + config._i,
            i, parsedInput, tokens, token, skipped,
            stringLength = string.length,
            totalParsedInputLength = 0;

        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];

        for (i = 0; i < tokens.length; i++) {
            token = tokens[i];
            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
            // console.log('token', token, 'parsedInput', parsedInput,
            //         'regex', getParseRegexForToken(token, config));
            if (parsedInput) {
                skipped = string.substr(0, string.indexOf(parsedInput));
                if (skipped.length > 0) {
                    getParsingFlags(config).unusedInput.push(skipped);
                }
                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
                totalParsedInputLength += parsedInput.length;
            }
            // don't parse if it's not a known token
            if (formatTokenFunctions[token]) {
                if (parsedInput) {
                    getParsingFlags(config).empty = false;
                }
                else {
                    getParsingFlags(config).unusedTokens.push(token);
                }
                addTimeToArrayFromToken(token, parsedInput, config);
            }
            else if (config._strict && !parsedInput) {
                getParsingFlags(config).unusedTokens.push(token);
            }
        }

        // add remaining unparsed input length to the string
        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
        if (string.length > 0) {
            getParsingFlags(config).unusedInput.push(string);
        }

        // clear _12h flag if hour is <= 12
        if (getParsingFlags(config).bigHour === true &&
                config._a[HOUR] <= 12 &&
                config._a[HOUR] > 0) {
            getParsingFlags(config).bigHour = undefined;
        }
        // handle meridiem
        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);

        configFromArray(config);
        checkOverflow(config);
    }


    function meridiemFixWrap (locale, hour, meridiem) {
        var isPm;

        if (meridiem == null) {
            // nothing to do
            return hour;
        }
        if (locale.meridiemHour != null) {
            return locale.meridiemHour(hour, meridiem);
        } else if (locale.isPM != null) {
            // Fallback
            isPm = locale.isPM(meridiem);
            if (isPm && hour < 12) {
                hour += 12;
            }
            if (!isPm && hour === 12) {
                hour = 0;
            }
            return hour;
        } else {
            // this is not supposed to happen
            return hour;
        }
    }

    // date from string and array of format strings
    function configFromStringAndArray(config) {
        var tempConfig,
            bestMoment,

            scoreToBeat,
            i,
            currentScore;

        if (config._f.length === 0) {
            getParsingFlags(config).invalidFormat = true;
            config._d = new Date(NaN);
            return;
        }

        for (i = 0; i < config._f.length; i++) {
            currentScore = 0;
            tempConfig = copyConfig({}, config);
            if (config._useUTC != null) {
                tempConfig._useUTC = config._useUTC;
            }
            tempConfig._f = config._f[i];
            configFromStringAndFormat(tempConfig);

            if (!valid__isValid(tempConfig)) {
                continue;
            }

            // if there is any input that was not parsed add a penalty for that format
            currentScore += getParsingFlags(tempConfig).charsLeftOver;

            //or tokens
            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;

            getParsingFlags(tempConfig).score = currentScore;

            if (scoreToBeat == null || currentScore < scoreToBeat) {
                scoreToBeat = currentScore;
                bestMoment = tempConfig;
            }
        }

        extend(config, bestMoment || tempConfig);
    }

    function configFromObject(config) {
        if (config._d) {
            return;
        }

        var i = normalizeObjectUnits(config._i);
        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
            return obj && parseInt(obj, 10);
        });

        configFromArray(config);
    }

    function createFromConfig (config) {
        var res = new Moment(checkOverflow(prepareConfig(config)));
        if (res._nextDay) {
            // Adding is smart enough around DST
            res.add(1, 'd');
            res._nextDay = undefined;
        }

        return res;
    }

    function prepareConfig (config) {
        var input = config._i,
            format = config._f;

        config._locale = config._locale || locale_locales__getLocale(config._l);

        if (input === null || (format === undefined && input === '')) {
            return valid__createInvalid({nullInput: true});
        }

        if (typeof input === 'string') {
            config._i = input = config._locale.preparse(input);
        }

        if (isMoment(input)) {
            return new Moment(checkOverflow(input));
        } else if (isArray(format)) {
            configFromStringAndArray(config);
        } else if (format) {
            configFromStringAndFormat(config);
        } else if (isDate(input)) {
            config._d = input;
        } else {
            configFromInput(config);
        }

        if (!valid__isValid(config)) {
            config._d = null;
        }

        return config;
    }

    function configFromInput(config) {
        var input = config._i;
        if (input === undefined) {
            config._d = new Date(utils_hooks__hooks.now());
        } else if (isDate(input)) {
            config._d = new Date(+input);
        } else if (typeof input === 'string') {
            configFromString(config);
        } else if (isArray(input)) {
            config._a = map(input.slice(0), function (obj) {
                return parseInt(obj, 10);
            });
            configFromArray(config);
        } else if (typeof(input) === 'object') {
            configFromObject(config);
        } else if (typeof(input) === 'number') {
            // from milliseconds
            config._d = new Date(input);
        } else {
            utils_hooks__hooks.createFromInputFallback(config);
        }
    }

    function createLocalOrUTC (input, format, locale, strict, isUTC) {
        var c = {};

        if (typeof(locale) === 'boolean') {
            strict = locale;
            locale = undefined;
        }
        // object construction must be done this way.
        // https://github.com/moment/moment/issues/1423
        c._isAMomentObject = true;
        c._useUTC = c._isUTC = isUTC;
        c._l = locale;
        c._i = input;
        c._f = format;
        c._strict = strict;

        return createFromConfig(c);
    }

    function local__createLocal (input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, false);
    }

    var prototypeMin = deprecate(
         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
         function () {
             var other = local__createLocal.apply(null, arguments);
             if (this.isValid() && other.isValid()) {
                 return other < this ? this : other;
             } else {
                 return valid__createInvalid();
             }
         }
     );

    var prototypeMax = deprecate(
        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
        function () {
            var other = local__createLocal.apply(null, arguments);
            if (this.isValid() && other.isValid()) {
                return other > this ? this : other;
            } else {
                return valid__createInvalid();
            }
        }
    );

    // Pick a moment m from moments so that m[fn](other) is true for all
    // other. This relies on the function fn to be transitive.
    //
    // moments should either be an array of moment objects or an array, whose
    // first element is an array of moment objects.
    function pickBy(fn, moments) {
        var res, i;
        if (moments.length === 1 && isArray(moments[0])) {
            moments = moments[0];
        }
        if (!moments.length) {
            return local__createLocal();
        }
        res = moments[0];
        for (i = 1; i < moments.length; ++i) {
            if (!moments[i].isValid() || moments[i][fn](res)) {
                res = moments[i];
            }
        }
        return res;
    }

    // TODO: Use [].sort instead?
    function min () {
        var args = [].slice.call(arguments, 0);

        return pickBy('isBefore', args);
    }

    function max () {
        var args = [].slice.call(arguments, 0);

        return pickBy('isAfter', args);
    }

    var now = function () {
        return Date.now ? Date.now() : +(new Date());
    };

    function Duration (duration) {
        var normalizedInput = normalizeObjectUnits(duration),
            years = normalizedInput.year || 0,
            quarters = normalizedInput.quarter || 0,
            months = normalizedInput.month || 0,
            weeks = normalizedInput.week || 0,
            days = normalizedInput.day || 0,
            hours = normalizedInput.hour || 0,
            minutes = normalizedInput.minute || 0,
            seconds = normalizedInput.second || 0,
            milliseconds = normalizedInput.millisecond || 0;

        // representation for dateAddRemove
        this._milliseconds = +milliseconds +
            seconds * 1e3 + // 1000
            minutes * 6e4 + // 1000 * 60
            hours * 36e5; // 1000 * 60 * 60
        // Because of dateAddRemove treats 24 hours as different from a
        // day when working around DST, we need to store them separately
        this._days = +days +
            weeks * 7;
        // It is impossible translate months into days without knowing
        // which months you are are talking about, so we have to store
        // it separately.
        this._months = +months +
            quarters * 3 +
            years * 12;

        this._data = {};

        this._locale = locale_locales__getLocale();

        this._bubble();
    }

    function isDuration (obj) {
        return obj instanceof Duration;
    }

    // FORMATTING

    function offset (token, separator) {
        addFormatToken(token, 0, 0, function () {
            var offset = this.utcOffset();
            var sign = '+';
            if (offset < 0) {
                offset = -offset;
                sign = '-';
            }
            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
        });
    }

    offset('Z', ':');
    offset('ZZ', '');

    // PARSING

    addRegexToken('Z',  matchShortOffset);
    addRegexToken('ZZ', matchShortOffset);
    addParseToken(['Z', 'ZZ'], function (input, array, config) {
        config._useUTC = true;
        config._tzm = offsetFromString(matchShortOffset, input);
    });

    // HELPERS

    // timezone chunker
    // '+10:00' > ['10',  '00']
    // '-1530'  > ['-15', '30']
    var chunkOffset = /([\+\-]|\d\d)/gi;

    function offsetFromString(matcher, string) {
        var matches = ((string || '').match(matcher) || []);
        var chunk   = matches[matches.length - 1] || [];
        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
        var minutes = +(parts[1] * 60) + toInt(parts[2]);

        return parts[0] === '+' ? minutes : -minutes;
    }

    // Return a moment from input, that is local/utc/zone equivalent to model.
    function cloneWithOffset(input, model) {
        var res, diff;
        if (model._isUTC) {
            res = model.clone();
            diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res);
            // Use low-level api, because this fn is low-level api.
            res._d.setTime(+res._d + diff);
            utils_hooks__hooks.updateOffset(res, false);
            return res;
        } else {
            return local__createLocal(input).local();
        }
    }

    function getDateOffset (m) {
        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
        // https://github.com/moment/moment/pull/1871
        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
    }

    // HOOKS

    // This function will be called whenever a moment is mutated.
    // It is intended to keep the offset in sync with the timezone.
    utils_hooks__hooks.updateOffset = function () {};

    // MOMENTS

    // keepLocalTime = true means only change the timezone, without
    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
    // +0200, so we adjust the time as needed, to be valid.
    //
    // Keeping the time actually adds/subtracts (one hour)
    // from the actual represented time. That is why we call updateOffset
    // a second time. In case it wants us to change the offset again
    // _changeInProgress == true case, then we have to adjust, because
    // there is no such time in the given timezone.
    function getSetOffset (input, keepLocalTime) {
        var offset = this._offset || 0,
            localAdjust;
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        if (input != null) {
            if (typeof input === 'string') {
                input = offsetFromString(matchShortOffset, input);
            } else if (Math.abs(input) < 16) {
                input = input * 60;
            }
            if (!this._isUTC && keepLocalTime) {
                localAdjust = getDateOffset(this);
            }
            this._offset = input;
            this._isUTC = true;
            if (localAdjust != null) {
                this.add(localAdjust, 'm');
            }
            if (offset !== input) {
                if (!keepLocalTime || this._changeInProgress) {
                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
                } else if (!this._changeInProgress) {
                    this._changeInProgress = true;
                    utils_hooks__hooks.updateOffset(this, true);
                    this._changeInProgress = null;
                }
            }
            return this;
        } else {
            return this._isUTC ? offset : getDateOffset(this);
        }
    }

    function getSetZone (input, keepLocalTime) {
        if (input != null) {
            if (typeof input !== 'string') {
                input = -input;
            }

            this.utcOffset(input, keepLocalTime);

            return this;
        } else {
            return -this.utcOffset();
        }
    }

    function setOffsetToUTC (keepLocalTime) {
        return this.utcOffset(0, keepLocalTime);
    }

    function setOffsetToLocal (keepLocalTime) {
        if (this._isUTC) {
            this.utcOffset(0, keepLocalTime);
            this._isUTC = false;

            if (keepLocalTime) {
                this.subtract(getDateOffset(this), 'm');
            }
        }
        return this;
    }

    function setOffsetToParsedOffset () {
        if (this._tzm) {
            this.utcOffset(this._tzm);
        } else if (typeof this._i === 'string') {
            this.utcOffset(offsetFromString(matchOffset, this._i));
        }
        return this;
    }

    function hasAlignedHourOffset (input) {
        if (!this.isValid()) {
            return false;
        }
        input = input ? local__createLocal(input).utcOffset() : 0;

        return (this.utcOffset() - input) % 60 === 0;
    }

    function isDaylightSavingTime () {
        return (
            this.utcOffset() > this.clone().month(0).utcOffset() ||
            this.utcOffset() > this.clone().month(5).utcOffset()
        );
    }

    function isDaylightSavingTimeShifted () {
        if (!isUndefined(this._isDSTShifted)) {
            return this._isDSTShifted;
        }

        var c = {};

        copyConfig(c, this);
        c = prepareConfig(c);

        if (c._a) {
            var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
            this._isDSTShifted = this.isValid() &&
                compareArrays(c._a, other.toArray()) > 0;
        } else {
            this._isDSTShifted = false;
        }

        return this._isDSTShifted;
    }

    function isLocal () {
        return this.isValid() ? !this._isUTC : false;
    }

    function isUtcOffset () {
        return this.isValid() ? this._isUTC : false;
    }

    function isUtc () {
        return this.isValid() ? this._isUTC && this._offset === 0 : false;
    }

    // ASP.NET json date format regex
    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;

    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
    // and further modified to allow for strings containing both week and day
    var isoRegex = /^(-)?P(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)W)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?$/;

    function create__createDuration (input, key) {
        var duration = input,
            // matching against regexp is expensive, do it on demand
            match = null,
            sign,
            ret,
            diffRes;

        if (isDuration(input)) {
            duration = {
                ms : input._milliseconds,
                d  : input._days,
                M  : input._months
            };
        } else if (typeof input === 'number') {
            duration = {};
            if (key) {
                duration[key] = input;
            } else {
                duration.milliseconds = input;
            }
        } else if (!!(match = aspNetRegex.exec(input))) {
            sign = (match[1] === '-') ? -1 : 1;
            duration = {
                y  : 0,
                d  : toInt(match[DATE])        * sign,
                h  : toInt(match[HOUR])        * sign,
                m  : toInt(match[MINUTE])      * sign,
                s  : toInt(match[SECOND])      * sign,
                ms : toInt(match[MILLISECOND]) * sign
            };
        } else if (!!(match = isoRegex.exec(input))) {
            sign = (match[1] === '-') ? -1 : 1;
            duration = {
                y : parseIso(match[2], sign),
                M : parseIso(match[3], sign),
                w : parseIso(match[4], sign),
                d : parseIso(match[5], sign),
                h : parseIso(match[6], sign),
                m : parseIso(match[7], sign),
                s : parseIso(match[8], sign)
            };
        } else if (duration == null) {// checks for null or undefined
            duration = {};
        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
            diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));

            duration = {};
            duration.ms = diffRes.milliseconds;
            duration.M = diffRes.months;
        }

        ret = new Duration(duration);

        if (isDuration(input) && hasOwnProp(input, '_locale')) {
            ret._locale = input._locale;
        }

        return ret;
    }

    create__createDuration.fn = Duration.prototype;

    function parseIso (inp, sign) {
        // We'd normally use ~~inp for this, but unfortunately it also
        // converts floats to ints.
        // inp may be undefined, so careful calling replace on it.
        var res = inp && parseFloat(inp.replace(',', '.'));
        // apply sign while we're at it
        return (isNaN(res) ? 0 : res) * sign;
    }

    function positiveMomentsDifference(base, other) {
        var res = {milliseconds: 0, months: 0};

        res.months = other.month() - base.month() +
            (other.year() - base.year()) * 12;
        if (base.clone().add(res.months, 'M').isAfter(other)) {
            --res.months;
        }

        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));

        return res;
    }

    function momentsDifference(base, other) {
        var res;
        if (!(base.isValid() && other.isValid())) {
            return {milliseconds: 0, months: 0};
        }

        other = cloneWithOffset(other, base);
        if (base.isBefore(other)) {
            res = positiveMomentsDifference(base, other);
        } else {
            res = positiveMomentsDifference(other, base);
            res.milliseconds = -res.milliseconds;
            res.months = -res.months;
        }

        return res;
    }

    function absRound (number) {
        if (number < 0) {
            return Math.round(-1 * number) * -1;
        } else {
            return Math.round(number);
        }
    }

    // TODO: remove 'name' arg after deprecation is removed
    function createAdder(direction, name) {
        return function (val, period) {
            var dur, tmp;
            //invert the arguments, but complain about it
            if (period !== null && !isNaN(+period)) {
                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
                tmp = val; val = period; period = tmp;
            }

            val = typeof val === 'string' ? +val : val;
            dur = create__createDuration(val, period);
            add_subtract__addSubtract(this, dur, direction);
            return this;
        };
    }

    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
        var milliseconds = duration._milliseconds,
            days = absRound(duration._days),
            months = absRound(duration._months);

        if (!mom.isValid()) {
            // No op
            return;
        }

        updateOffset = updateOffset == null ? true : updateOffset;

        if (milliseconds) {
            mom._d.setTime(+mom._d + milliseconds * isAdding);
        }
        if (days) {
            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
        }
        if (months) {
            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
        }
        if (updateOffset) {
            utils_hooks__hooks.updateOffset(mom, days || months);
        }
    }

    var add_subtract__add      = createAdder(1, 'add');
    var add_subtract__subtract = createAdder(-1, 'subtract');

    function moment_calendar__calendar (time, formats) {
        // We want to compare the start of today, vs this.
        // Getting start-of-today depends on whether we're local/utc/offset or not.
        var now = time || local__createLocal(),
            sod = cloneWithOffset(now, this).startOf('day'),
            diff = this.diff(sod, 'days', true),
            format = diff < -6 ? 'sameElse' :
                diff < -1 ? 'lastWeek' :
                diff < 0 ? 'lastDay' :
                diff < 1 ? 'sameDay' :
                diff < 2 ? 'nextDay' :
                diff < 7 ? 'nextWeek' : 'sameElse';

        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);

        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
    }

    function clone () {
        return new Moment(this);
    }

    function isAfter (input, units) {
        var localInput = isMoment(input) ? input : local__createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
        if (units === 'millisecond') {
            return +this > +localInput;
        } else {
            return +localInput < +this.clone().startOf(units);
        }
    }

    function isBefore (input, units) {
        var localInput = isMoment(input) ? input : local__createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
        if (units === 'millisecond') {
            return +this < +localInput;
        } else {
            return +this.clone().endOf(units) < +localInput;
        }
    }

    function isBetween (from, to, units) {
        return this.isAfter(from, units) && this.isBefore(to, units);
    }

    function isSame (input, units) {
        var localInput = isMoment(input) ? input : local__createLocal(input),
            inputMs;
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units || 'millisecond');
        if (units === 'millisecond') {
            return +this === +localInput;
        } else {
            inputMs = +localInput;
            return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
        }
    }

    function isSameOrAfter (input, units) {
        return this.isSame(input, units) || this.isAfter(input,units);
    }

    function isSameOrBefore (input, units) {
        return this.isSame(input, units) || this.isBefore(input,units);
    }

    function diff (input, units, asFloat) {
        var that,
            zoneDelta,
            delta, output;

        if (!this.isValid()) {
            return NaN;
        }

        that = cloneWithOffset(input, this);

        if (!that.isValid()) {
            return NaN;
        }

        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;

        units = normalizeUnits(units);

        if (units === 'year' || units === 'month' || units === 'quarter') {
            output = monthDiff(this, that);
            if (units === 'quarter') {
                output = output / 3;
            } else if (units === 'year') {
                output = output / 12;
            }
        } else {
            delta = this - that;
            output = units === 'second' ? delta / 1e3 : // 1000
                units === 'minute' ? delta / 6e4 : // 1000 * 60
                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
                delta;
        }
        return asFloat ? output : absFloor(output);
    }

    function monthDiff (a, b) {
        // difference in months
        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
            // b is in (anchor - 1 month, anchor + 1 month)
            anchor = a.clone().add(wholeMonthDiff, 'months'),
            anchor2, adjust;

        if (b - anchor < 0) {
            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
            // linear across the month
            adjust = (b - anchor) / (anchor - anchor2);
        } else {
            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
            // linear across the month
            adjust = (b - anchor) / (anchor2 - anchor);
        }

        return -(wholeMonthDiff + adjust);
    }

    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';

    function toString () {
        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
    }

    function moment_format__toISOString () {
        var m = this.clone().utc();
        if (0 < m.year() && m.year() <= 9999) {
            if (isFunction(Date.prototype.toISOString)) {
                // native implementation is ~50x faster, use it when we can
                return this.toDate().toISOString();
            } else {
                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
            }
        } else {
            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
        }
    }

    function format (inputString) {
        var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat);
        return this.localeData().postformat(output);
    }

    function from (time, withoutSuffix) {
        if (this.isValid() &&
                ((isMoment(time) && time.isValid()) ||
                 local__createLocal(time).isValid())) {
            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }

    function fromNow (withoutSuffix) {
        return this.from(local__createLocal(), withoutSuffix);
    }

    function to (time, withoutSuffix) {
        if (this.isValid() &&
                ((isMoment(time) && time.isValid()) ||
                 local__createLocal(time).isValid())) {
            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }

    function toNow (withoutSuffix) {
        return this.to(local__createLocal(), withoutSuffix);
    }

    // If passed a locale key, it will set the locale for this
    // instance.  Otherwise, it will return the locale configuration
    // variables for this instance.
    function locale (key) {
        var newLocaleData;

        if (key === undefined) {
            return this._locale._abbr;
        } else {
            newLocaleData = locale_locales__getLocale(key);
            if (newLocaleData != null) {
                this._locale = newLocaleData;
            }
            return this;
        }
    }

    var lang = deprecate(
        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
        function (key) {
            if (key === undefined) {
                return this.localeData();
            } else {
                return this.locale(key);
            }
        }
    );

    function localeData () {
        return this._locale;
    }

    function startOf (units) {
        units = normalizeUnits(units);
        // the following switch intentionally omits break keywords
        // to utilize falling through the cases.
        switch (units) {
        case 'year':
            this.month(0);
            /* falls through */
        case 'quarter':
        case 'month':
            this.date(1);
            /* falls through */
        case 'week':
        case 'isoWeek':
        case 'day':
            this.hours(0);
            /* falls through */
        case 'hour':
            this.minutes(0);
            /* falls through */
        case 'minute':
            this.seconds(0);
            /* falls through */
        case 'second':
            this.milliseconds(0);
        }

        // weeks are a special case
        if (units === 'week') {
            this.weekday(0);
        }
        if (units === 'isoWeek') {
            this.isoWeekday(1);
        }

        // quarters are also special
        if (units === 'quarter') {
            this.month(Math.floor(this.month() / 3) * 3);
        }

        return this;
    }

    function endOf (units) {
        units = normalizeUnits(units);
        if (units === undefined || units === 'millisecond') {
            return this;
        }
        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
    }

    function to_type__valueOf () {
        return +this._d - ((this._offset || 0) * 60000);
    }

    function unix () {
        return Math.floor(+this / 1000);
    }

    function toDate () {
        return this._offset ? new Date(+this) : this._d;
    }

    function toArray () {
        var m = this;
        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
    }

    function toObject () {
        var m = this;
        return {
            years: m.year(),
            months: m.month(),
            date: m.date(),
            hours: m.hours(),
            minutes: m.minutes(),
            seconds: m.seconds(),
            milliseconds: m.milliseconds()
        };
    }

    function toJSON () {
        // new Date(NaN).toJSON() === null
        return this.isValid() ? this.toISOString() : null;
    }

    function moment_valid__isValid () {
        return valid__isValid(this);
    }

    function parsingFlags () {
        return extend({}, getParsingFlags(this));
    }

    function invalidAt () {
        return getParsingFlags(this).overflow;
    }

    function creationData() {
        return {
            input: this._i,
            format: this._f,
            locale: this._locale,
            isUTC: this._isUTC,
            strict: this._strict
        };
    }

    // FORMATTING

    addFormatToken(0, ['gg', 2], 0, function () {
        return this.weekYear() % 100;
    });

    addFormatToken(0, ['GG', 2], 0, function () {
        return this.isoWeekYear() % 100;
    });

    function addWeekYearFormatToken (token, getter) {
        addFormatToken(0, [token, token.length], 0, getter);
    }

    addWeekYearFormatToken('gggg',     'weekYear');
    addWeekYearFormatToken('ggggg',    'weekYear');
    addWeekYearFormatToken('GGGG',  'isoWeekYear');
    addWeekYearFormatToken('GGGGG', 'isoWeekYear');

    // ALIASES

    addUnitAlias('weekYear', 'gg');
    addUnitAlias('isoWeekYear', 'GG');

    // PARSING

    addRegexToken('G',      matchSigned);
    addRegexToken('g',      matchSigned);
    addRegexToken('GG',     match1to2, match2);
    addRegexToken('gg',     match1to2, match2);
    addRegexToken('GGGG',   match1to4, match4);
    addRegexToken('gggg',   match1to4, match4);
    addRegexToken('GGGGG',  match1to6, match6);
    addRegexToken('ggggg',  match1to6, match6);

    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
        week[token.substr(0, 2)] = toInt(input);
    });

    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
        week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
    });

    // MOMENTS

    function getSetWeekYear (input) {
        return getSetWeekYearHelper.call(this,
                input,
                this.week(),
                this.weekday(),
                this.localeData()._week.dow,
                this.localeData()._week.doy);
    }

    function getSetISOWeekYear (input) {
        return getSetWeekYearHelper.call(this,
                input, this.isoWeek(), this.isoWeekday(), 1, 4);
    }

    function getISOWeeksInYear () {
        return weeksInYear(this.year(), 1, 4);
    }

    function getWeeksInYear () {
        var weekInfo = this.localeData()._week;
        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
    }

    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
        var weeksTarget;
        if (input == null) {
            return weekOfYear(this, dow, doy).year;
        } else {
            weeksTarget = weeksInYear(input, dow, doy);
            if (week > weeksTarget) {
                week = weeksTarget;
            }
            return setWeekAll.call(this, input, week, weekday, dow, doy);
        }
    }

    function setWeekAll(weekYear, week, weekday, dow, doy) {
        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);

        this.year(date.getUTCFullYear());
        this.month(date.getUTCMonth());
        this.date(date.getUTCDate());
        return this;
    }

    // FORMATTING

    addFormatToken('Q', 0, 'Qo', 'quarter');

    // ALIASES

    addUnitAlias('quarter', 'Q');

    // PARSING

    addRegexToken('Q', match1);
    addParseToken('Q', function (input, array) {
        array[MONTH] = (toInt(input) - 1) * 3;
    });

    // MOMENTS

    function getSetQuarter (input) {
        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
    }

    // FORMATTING

    addFormatToken('w', ['ww', 2], 'wo', 'week');
    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');

    // ALIASES

    addUnitAlias('week', 'w');
    addUnitAlias('isoWeek', 'W');

    // PARSING

    addRegexToken('w',  match1to2);
    addRegexToken('ww', match1to2, match2);
    addRegexToken('W',  match1to2);
    addRegexToken('WW', match1to2, match2);

    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
        week[token.substr(0, 1)] = toInt(input);
    });

    // HELPERS

    // LOCALES

    function localeWeek (mom) {
        return weekOfYear(mom, this._week.dow, this._week.doy).week;
    }

    var defaultLocaleWeek = {
        dow : 0, // Sunday is the first day of the week.
        doy : 6  // The week that contains Jan 1st is the first week of the year.
    };

    function localeFirstDayOfWeek () {
        return this._week.dow;
    }

    function localeFirstDayOfYear () {
        return this._week.doy;
    }

    // MOMENTS

    function getSetWeek (input) {
        var week = this.localeData().week(this);
        return input == null ? week : this.add((input - week) * 7, 'd');
    }

    function getSetISOWeek (input) {
        var week = weekOfYear(this, 1, 4).week;
        return input == null ? week : this.add((input - week) * 7, 'd');
    }

    // FORMATTING

    addFormatToken('D', ['DD', 2], 'Do', 'date');

    // ALIASES

    addUnitAlias('date', 'D');

    // PARSING

    addRegexToken('D',  match1to2);
    addRegexToken('DD', match1to2, match2);
    addRegexToken('Do', function (isStrict, locale) {
        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
    });

    addParseToken(['D', 'DD'], DATE);
    addParseToken('Do', function (input, array) {
        array[DATE] = toInt(input.match(match1to2)[0], 10);
    });

    // MOMENTS

    var getSetDayOfMonth = makeGetSet('Date', true);

    // FORMATTING

    addFormatToken('d', 0, 'do', 'day');

    addFormatToken('dd', 0, 0, function (format) {
        return this.localeData().weekdaysMin(this, format);
    });

    addFormatToken('ddd', 0, 0, function (format) {
        return this.localeData().weekdaysShort(this, format);
    });

    addFormatToken('dddd', 0, 0, function (format) {
        return this.localeData().weekdays(this, format);
    });

    addFormatToken('e', 0, 0, 'weekday');
    addFormatToken('E', 0, 0, 'isoWeekday');

    // ALIASES

    addUnitAlias('day', 'd');
    addUnitAlias('weekday', 'e');
    addUnitAlias('isoWeekday', 'E');

    // PARSING

    addRegexToken('d',    match1to2);
    addRegexToken('e',    match1to2);
    addRegexToken('E',    match1to2);
    addRegexToken('dd',   matchWord);
    addRegexToken('ddd',  matchWord);
    addRegexToken('dddd', matchWord);

    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
        var weekday = config._locale.weekdaysParse(input, token, config._strict);
        // if we didn't get a weekday name, mark the date as invalid
        if (weekday != null) {
            week.d = weekday;
        } else {
            getParsingFlags(config).invalidWeekday = input;
        }
    });

    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
        week[token] = toInt(input);
    });

    // HELPERS

    function parseWeekday(input, locale) {
        if (typeof input !== 'string') {
            return input;
        }

        if (!isNaN(input)) {
            return parseInt(input, 10);
        }

        input = locale.weekdaysParse(input);
        if (typeof input === 'number') {
            return input;
        }

        return null;
    }

    // LOCALES

    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
    function localeWeekdays (m, format) {
        return isArray(this._weekdays) ? this._weekdays[m.day()] :
            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
    }

    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
    function localeWeekdaysShort (m) {
        return this._weekdaysShort[m.day()];
    }

    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
    function localeWeekdaysMin (m) {
        return this._weekdaysMin[m.day()];
    }

    function localeWeekdaysParse (weekdayName, format, strict) {
        var i, mom, regex;

        if (!this._weekdaysParse) {
            this._weekdaysParse = [];
            this._minWeekdaysParse = [];
            this._shortWeekdaysParse = [];
            this._fullWeekdaysParse = [];
        }

        for (i = 0; i < 7; i++) {
            // make the regex if we don't have it already

            mom = local__createLocal([2000, 1]).day(i);
            if (strict && !this._fullWeekdaysParse[i]) {
                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
            }
            if (!this._weekdaysParse[i]) {
                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
            }
            // test the regex
            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
                return i;
            }
        }
    }

    // MOMENTS

    function getSetDayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
        if (input != null) {
            input = parseWeekday(input, this.localeData());
            return this.add(input - day, 'd');
        } else {
            return day;
        }
    }

    function getSetLocaleDayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
        return input == null ? weekday : this.add(input - weekday, 'd');
    }

    function getSetISODayOfWeek (input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        // behaves the same as moment#day except
        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
        // as a setter, sunday should belong to the previous week.
        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
    }

    // FORMATTING

    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');

    // ALIASES

    addUnitAlias('dayOfYear', 'DDD');

    // PARSING

    addRegexToken('DDD',  match1to3);
    addRegexToken('DDDD', match3);
    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
        config._dayOfYear = toInt(input);
    });

    // HELPERS

    // MOMENTS

    function getSetDayOfYear (input) {
        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
    }

    // FORMATTING

    function hFormat() {
        return this.hours() % 12 || 12;
    }

    addFormatToken('H', ['HH', 2], 0, 'hour');
    addFormatToken('h', ['hh', 2], 0, hFormat);

    addFormatToken('hmm', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
    });

    addFormatToken('hmmss', 0, 0, function () {
        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
            zeroFill(this.seconds(), 2);
    });

    addFormatToken('Hmm', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2);
    });

    addFormatToken('Hmmss', 0, 0, function () {
        return '' + this.hours() + zeroFill(this.minutes(), 2) +
            zeroFill(this.seconds(), 2);
    });

    function meridiem (token, lowercase) {
        addFormatToken(token, 0, 0, function () {
            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
        });
    }

    meridiem('a', true);
    meridiem('A', false);

    // ALIASES

    addUnitAlias('hour', 'h');

    // PARSING

    function matchMeridiem (isStrict, locale) {
        return locale._meridiemParse;
    }

    addRegexToken('a',  matchMeridiem);
    addRegexToken('A',  matchMeridiem);
    addRegexToken('H',  match1to2);
    addRegexToken('h',  match1to2);
    addRegexToken('HH', match1to2, match2);
    addRegexToken('hh', match1to2, match2);

    addRegexToken('hmm', match3to4);
    addRegexToken('hmmss', match5to6);
    addRegexToken('Hmm', match3to4);
    addRegexToken('Hmmss', match5to6);

    addParseToken(['H', 'HH'], HOUR);
    addParseToken(['a', 'A'], function (input, array, config) {
        config._isPm = config._locale.isPM(input);
        config._meridiem = input;
    });
    addParseToken(['h', 'hh'], function (input, array, config) {
        array[HOUR] = toInt(input);
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken('Hmm', function (input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
    });
    addParseToken('Hmmss', function (input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
    });

    // LOCALES

    function localeIsPM (input) {
        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
        // Using charAt should be more compatible.
        return ((input + '').toLowerCase().charAt(0) === 'p');
    }

    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
    function localeMeridiem (hours, minutes, isLower) {
        if (hours > 11) {
            return isLower ? 'pm' : 'PM';
        } else {
            return isLower ? 'am' : 'AM';
        }
    }


    // MOMENTS

    // Setting the hour should keep the time, because the user explicitly
    // specified which hour he wants. So trying to maintain the same hour (in
    // a new timezone) makes sense. Adding/subtracting hours does not follow
    // this rule.
    var getSetHour = makeGetSet('Hours', true);

    // FORMATTING

    addFormatToken('m', ['mm', 2], 0, 'minute');

    // ALIASES

    addUnitAlias('minute', 'm');

    // PARSING

    addRegexToken('m',  match1to2);
    addRegexToken('mm', match1to2, match2);
    addParseToken(['m', 'mm'], MINUTE);

    // MOMENTS

    var getSetMinute = makeGetSet('Minutes', false);

    // FORMATTING

    addFormatToken('s', ['ss', 2], 0, 'second');

    // ALIASES

    addUnitAlias('second', 's');

    // PARSING

    addRegexToken('s',  match1to2);
    addRegexToken('ss', match1to2, match2);
    addParseToken(['s', 'ss'], SECOND);

    // MOMENTS

    var getSetSecond = makeGetSet('Seconds', false);

    // FORMATTING

    addFormatToken('S', 0, 0, function () {
        return ~~(this.millisecond() / 100);
    });

    addFormatToken(0, ['SS', 2], 0, function () {
        return ~~(this.millisecond() / 10);
    });

    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
    addFormatToken(0, ['SSSS', 4], 0, function () {
        return this.millisecond() * 10;
    });
    addFormatToken(0, ['SSSSS', 5], 0, function () {
        return this.millisecond() * 100;
    });
    addFormatToken(0, ['SSSSSS', 6], 0, function () {
        return this.millisecond() * 1000;
    });
    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
        return this.millisecond() * 10000;
    });
    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
        return this.millisecond() * 100000;
    });
    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
        return this.millisecond() * 1000000;
    });


    // ALIASES

    addUnitAlias('millisecond', 'ms');

    // PARSING

    addRegexToken('S',    match1to3, match1);
    addRegexToken('SS',   match1to3, match2);
    addRegexToken('SSS',  match1to3, match3);

    var token;
    for (token = 'SSSS'; token.length <= 9; token += 'S') {
        addRegexToken(token, matchUnsigned);
    }

    function parseMs(input, array) {
        array[MILLISECOND] = toInt(('0.' + input) * 1000);
    }

    for (token = 'S'; token.length <= 9; token += 'S') {
        addParseToken(token, parseMs);
    }
    // MOMENTS

    var getSetMillisecond = makeGetSet('Milliseconds', false);

    // FORMATTING

    addFormatToken('z',  0, 0, 'zoneAbbr');
    addFormatToken('zz', 0, 0, 'zoneName');

    // MOMENTS

    function getZoneAbbr () {
        return this._isUTC ? 'UTC' : '';
    }

    function getZoneName () {
        return this._isUTC ? 'Coordinated Universal Time' : '';
    }

    var momentPrototype__proto = Moment.prototype;

    momentPrototype__proto.add               = add_subtract__add;
    momentPrototype__proto.calendar          = moment_calendar__calendar;
    momentPrototype__proto.clone             = clone;
    momentPrototype__proto.diff              = diff;
    momentPrototype__proto.endOf             = endOf;
    momentPrototype__proto.format            = format;
    momentPrototype__proto.from              = from;
    momentPrototype__proto.fromNow           = fromNow;
    momentPrototype__proto.to                = to;
    momentPrototype__proto.toNow             = toNow;
    momentPrototype__proto.get               = getSet;
    momentPrototype__proto.invalidAt         = invalidAt;
    momentPrototype__proto.isAfter           = isAfter;
    momentPrototype__proto.isBefore          = isBefore;
    momentPrototype__proto.isBetween         = isBetween;
    momentPrototype__proto.isSame            = isSame;
    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
    momentPrototype__proto.isValid           = moment_valid__isValid;
    momentPrototype__proto.lang              = lang;
    momentPrototype__proto.locale            = locale;
    momentPrototype__proto.localeData        = localeData;
    momentPrototype__proto.max               = prototypeMax;
    momentPrototype__proto.min               = prototypeMin;
    momentPrototype__proto.parsingFlags      = parsingFlags;
    momentPrototype__proto.set               = getSet;
    momentPrototype__proto.startOf           = startOf;
    momentPrototype__proto.subtract          = add_subtract__subtract;
    momentPrototype__proto.toArray           = toArray;
    momentPrototype__proto.toObject          = toObject;
    momentPrototype__proto.toDate            = toDate;
    momentPrototype__proto.toISOString       = moment_format__toISOString;
    momentPrototype__proto.toJSON            = toJSON;
    momentPrototype__proto.toString          = toString;
    momentPrototype__proto.unix              = unix;
    momentPrototype__proto.valueOf           = to_type__valueOf;
    momentPrototype__proto.creationData      = creationData;

    // Year
    momentPrototype__proto.year       = getSetYear;
    momentPrototype__proto.isLeapYear = getIsLeapYear;

    // Week Year
    momentPrototype__proto.weekYear    = getSetWeekYear;
    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;

    // Quarter
    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;

    // Month
    momentPrototype__proto.month       = getSetMonth;
    momentPrototype__proto.daysInMonth = getDaysInMonth;

    // Week
    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
    momentPrototype__proto.weeksInYear    = getWeeksInYear;
    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;

    // Day
    momentPrototype__proto.date       = getSetDayOfMonth;
    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
    momentPrototype__proto.dayOfYear  = getSetDayOfYear;

    // Hour
    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;

    // Minute
    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;

    // Second
    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;

    // Millisecond
    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;

    // Offset
    momentPrototype__proto.utcOffset            = getSetOffset;
    momentPrototype__proto.utc                  = setOffsetToUTC;
    momentPrototype__proto.local                = setOffsetToLocal;
    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
    momentPrototype__proto.isDST                = isDaylightSavingTime;
    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
    momentPrototype__proto.isLocal              = isLocal;
    momentPrototype__proto.isUtcOffset          = isUtcOffset;
    momentPrototype__proto.isUtc                = isUtc;
    momentPrototype__proto.isUTC                = isUtc;

    // Timezone
    momentPrototype__proto.zoneAbbr = getZoneAbbr;
    momentPrototype__proto.zoneName = getZoneName;

    // Deprecations
    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);

    var momentPrototype = momentPrototype__proto;

    function moment__createUnix (input) {
        return local__createLocal(input * 1000);
    }

    function moment__createInZone () {
        return local__createLocal.apply(null, arguments).parseZone();
    }

    var defaultCalendar = {
        sameDay : '[Today at] LT',
        nextDay : '[Tomorrow at] LT',
        nextWeek : 'dddd [at] LT',
        lastDay : '[Yesterday at] LT',
        lastWeek : '[Last] dddd [at] LT',
        sameElse : 'L'
    };

    function locale_calendar__calendar (key, mom, now) {
        var output = this._calendar[key];
        return isFunction(output) ? output.call(mom, now) : output;
    }

    var defaultLongDateFormat = {
        LTS  : 'h:mm:ss A',
        LT   : 'h:mm A',
        L    : 'MM/DD/YYYY',
        LL   : 'MMMM D, YYYY',
        LLL  : 'MMMM D, YYYY h:mm A',
        LLLL : 'dddd, MMMM D, YYYY h:mm A'
    };

    function longDateFormat (key) {
        var format = this._longDateFormat[key],
            formatUpper = this._longDateFormat[key.toUpperCase()];

        if (format || !formatUpper) {
            return format;
        }

        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
            return val.slice(1);
        });

        return this._longDateFormat[key];
    }

    var defaultInvalidDate = 'Invalid date';

    function invalidDate () {
        return this._invalidDate;
    }

    var defaultOrdinal = '%d';
    var defaultOrdinalParse = /\d{1,2}/;

    function ordinal (number) {
        return this._ordinal.replace('%d', number);
    }

    function preParsePostFormat (string) {
        return string;
    }

    var defaultRelativeTime = {
        future : 'in %s',
        past   : '%s ago',
        s  : 'a few seconds',
        m  : 'a minute',
        mm : '%d minutes',
        h  : 'an hour',
        hh : '%d hours',
        d  : 'a day',
        dd : '%d days',
        M  : 'a month',
        MM : '%d months',
        y  : 'a year',
        yy : '%d years'
    };

    function relative__relativeTime (number, withoutSuffix, string, isFuture) {
        var output = this._relativeTime[string];
        return (isFunction(output)) ?
            output(number, withoutSuffix, string, isFuture) :
            output.replace(/%d/i, number);
    }

    function pastFuture (diff, output) {
        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
    }

    var prototype__proto = Locale.prototype;

    prototype__proto._calendar       = defaultCalendar;
    prototype__proto.calendar        = locale_calendar__calendar;
    prototype__proto._longDateFormat = defaultLongDateFormat;
    prototype__proto.longDateFormat  = longDateFormat;
    prototype__proto._invalidDate    = defaultInvalidDate;
    prototype__proto.invalidDate     = invalidDate;
    prototype__proto._ordinal        = defaultOrdinal;
    prototype__proto.ordinal         = ordinal;
    prototype__proto._ordinalParse   = defaultOrdinalParse;
    prototype__proto.preparse        = preParsePostFormat;
    prototype__proto.postformat      = preParsePostFormat;
    prototype__proto._relativeTime   = defaultRelativeTime;
    prototype__proto.relativeTime    = relative__relativeTime;
    prototype__proto.pastFuture      = pastFuture;
    prototype__proto.set             = locale_set__set;

    // Month
    prototype__proto.months            =        localeMonths;
    prototype__proto._months           = defaultLocaleMonths;
    prototype__proto.monthsShort       =        localeMonthsShort;
    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
    prototype__proto.monthsParse       =        localeMonthsParse;
    prototype__proto._monthsRegex      = defaultMonthsRegex;
    prototype__proto.monthsRegex       = monthsRegex;
    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
    prototype__proto.monthsShortRegex  = monthsShortRegex;

    // Week
    prototype__proto.week = localeWeek;
    prototype__proto._week = defaultLocaleWeek;
    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;

    // Day of Week
    prototype__proto.weekdays       =        localeWeekdays;
    prototype__proto._weekdays      = defaultLocaleWeekdays;
    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
    prototype__proto.weekdaysParse  =        localeWeekdaysParse;

    // Hours
    prototype__proto.isPM = localeIsPM;
    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
    prototype__proto.meridiem = localeMeridiem;

    function lists__get (format, index, field, setter) {
        var locale = locale_locales__getLocale();
        var utc = create_utc__createUTC().set(setter, index);
        return locale[field](utc, format);
    }

    function list (format, index, field, count, setter) {
        if (typeof format === 'number') {
            index = format;
            format = undefined;
        }

        format = format || '';

        if (index != null) {
            return lists__get(format, index, field, setter);
        }

        var i;
        var out = [];
        for (i = 0; i < count; i++) {
            out[i] = lists__get(format, i, field, setter);
        }
        return out;
    }

    function lists__listMonths (format, index) {
        return list(format, index, 'months', 12, 'month');
    }

    function lists__listMonthsShort (format, index) {
        return list(format, index, 'monthsShort', 12, 'month');
    }

    function lists__listWeekdays (format, index) {
        return list(format, index, 'weekdays', 7, 'day');
    }

    function lists__listWeekdaysShort (format, index) {
        return list(format, index, 'weekdaysShort', 7, 'day');
    }

    function lists__listWeekdaysMin (format, index) {
        return list(format, index, 'weekdaysMin', 7, 'day');
    }

    locale_locales__getSetGlobalLocale('en', {
        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
        ordinal : function (number) {
            var b = number % 10,
                output = (toInt(number % 100 / 10) === 1) ? 'th' :
                (b === 1) ? 'st' :
                (b === 2) ? 'nd' :
                (b === 3) ? 'rd' : 'th';
            return number + output;
        }
    });

    // Side effect imports
    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);

    var mathAbs = Math.abs;

    function duration_abs__abs () {
        var data           = this._data;

        this._milliseconds = mathAbs(this._milliseconds);
        this._days         = mathAbs(this._days);
        this._months       = mathAbs(this._months);

        data.milliseconds  = mathAbs(data.milliseconds);
        data.seconds       = mathAbs(data.seconds);
        data.minutes       = mathAbs(data.minutes);
        data.hours         = mathAbs(data.hours);
        data.months        = mathAbs(data.months);
        data.years         = mathAbs(data.years);

        return this;
    }

    function duration_add_subtract__addSubtract (duration, input, value, direction) {
        var other = create__createDuration(input, value);

        duration._milliseconds += direction * other._milliseconds;
        duration._days         += direction * other._days;
        duration._months       += direction * other._months;

        return duration._bubble();
    }

    // supports only 2.0-style add(1, 's') or add(duration)
    function duration_add_subtract__add (input, value) {
        return duration_add_subtract__addSubtract(this, input, value, 1);
    }

    // supports only 2.0-style subtract(1, 's') or subtract(duration)
    function duration_add_subtract__subtract (input, value) {
        return duration_add_subtract__addSubtract(this, input, value, -1);
    }

    function absCeil (number) {
        if (number < 0) {
            return Math.floor(number);
        } else {
            return Math.ceil(number);
        }
    }

    function bubble () {
        var milliseconds = this._milliseconds;
        var days         = this._days;
        var months       = this._months;
        var data         = this._data;
        var seconds, minutes, hours, years, monthsFromDays;

        // if we have a mix of positive and negative values, bubble down first
        // check: https://github.com/moment/moment/issues/2166
        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
                (milliseconds <= 0 && days <= 0 && months <= 0))) {
            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
            days = 0;
            months = 0;
        }

        // The following code bubbles up values, see the tests for
        // examples of what that means.
        data.milliseconds = milliseconds % 1000;

        seconds           = absFloor(milliseconds / 1000);
        data.seconds      = seconds % 60;

        minutes           = absFloor(seconds / 60);
        data.minutes      = minutes % 60;

        hours             = absFloor(minutes / 60);
        data.hours        = hours % 24;

        days += absFloor(hours / 24);

        // convert days to months
        monthsFromDays = absFloor(daysToMonths(days));
        months += monthsFromDays;
        days -= absCeil(monthsToDays(monthsFromDays));

        // 12 months -> 1 year
        years = absFloor(months / 12);
        months %= 12;

        data.days   = days;
        data.months = months;
        data.years  = years;

        return this;
    }

    function daysToMonths (days) {
        // 400 years have 146097 days (taking into account leap year rules)
        // 400 years have 12 months === 4800
        return days * 4800 / 146097;
    }

    function monthsToDays (months) {
        // the reverse of daysToMonths
        return months * 146097 / 4800;
    }

    function as (units) {
        var days;
        var months;
        var milliseconds = this._milliseconds;

        units = normalizeUnits(units);

        if (units === 'month' || units === 'year') {
            days   = this._days   + milliseconds / 864e5;
            months = this._months + daysToMonths(days);
            return units === 'month' ? months : months / 12;
        } else {
            // handle milliseconds separately because of floating point math errors (issue #1867)
            days = this._days + Math.round(monthsToDays(this._months));
            switch (units) {
                case 'week'   : return days / 7     + milliseconds / 6048e5;
                case 'day'    : return days         + milliseconds / 864e5;
                case 'hour'   : return days * 24    + milliseconds / 36e5;
                case 'minute' : return days * 1440  + milliseconds / 6e4;
                case 'second' : return days * 86400 + milliseconds / 1000;
                // Math.floor prevents floating point math errors here
                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
                default: throw new Error('Unknown unit ' + units);
            }
        }
    }

    // TODO: Use this.as('ms')?
    function duration_as__valueOf () {
        return (
            this._milliseconds +
            this._days * 864e5 +
            (this._months % 12) * 2592e6 +
            toInt(this._months / 12) * 31536e6
        );
    }

    function makeAs (alias) {
        return function () {
            return this.as(alias);
        };
    }

    var asMilliseconds = makeAs('ms');
    var asSeconds      = makeAs('s');
    var asMinutes      = makeAs('m');
    var asHours        = makeAs('h');
    var asDays         = makeAs('d');
    var asWeeks        = makeAs('w');
    var asMonths       = makeAs('M');
    var asYears        = makeAs('y');

    function duration_get__get (units) {
        units = normalizeUnits(units);
        return this[units + 's']();
    }

    function makeGetter(name) {
        return function () {
            return this._data[name];
        };
    }

    var milliseconds = makeGetter('milliseconds');
    var seconds      = makeGetter('seconds');
    var minutes      = makeGetter('minutes');
    var hours        = makeGetter('hours');
    var days         = makeGetter('days');
    var months       = makeGetter('months');
    var years        = makeGetter('years');

    function weeks () {
        return absFloor(this.days() / 7);
    }

    var round = Math.round;
    var thresholds = {
        s: 45,  // seconds to minute
        m: 45,  // minutes to hour
        h: 22,  // hours to day
        d: 26,  // days to month
        M: 11   // months to year
    };

    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
    }

    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
        var duration = create__createDuration(posNegDuration).abs();
        var seconds  = round(duration.as('s'));
        var minutes  = round(duration.as('m'));
        var hours    = round(duration.as('h'));
        var days     = round(duration.as('d'));
        var months   = round(duration.as('M'));
        var years    = round(duration.as('y'));

        var a = seconds < thresholds.s && ['s', seconds]  ||
                minutes <= 1           && ['m']           ||
                minutes < thresholds.m && ['mm', minutes] ||
                hours   <= 1           && ['h']           ||
                hours   < thresholds.h && ['hh', hours]   ||
                days    <= 1           && ['d']           ||
                days    < thresholds.d && ['dd', days]    ||
                months  <= 1           && ['M']           ||
                months  < thresholds.M && ['MM', months]  ||
                years   <= 1           && ['y']           || ['yy', years];

        a[2] = withoutSuffix;
        a[3] = +posNegDuration > 0;
        a[4] = locale;
        return substituteTimeAgo.apply(null, a);
    }

    // This function allows you to set a threshold for relative time strings
    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
        if (thresholds[threshold] === undefined) {
            return false;
        }
        if (limit === undefined) {
            return thresholds[threshold];
        }
        thresholds[threshold] = limit;
        return true;
    }

    function humanize (withSuffix) {
        var locale = this.localeData();
        var output = duration_humanize__relativeTime(this, !withSuffix, locale);

        if (withSuffix) {
            output = locale.pastFuture(+this, output);
        }

        return locale.postformat(output);
    }

    var iso_string__abs = Math.abs;

    function iso_string__toISOString() {
        // for ISO strings we do not use the normal bubbling rules:
        //  * milliseconds bubble up until they become hours
        //  * days do not bubble at all
        //  * months bubble up until they become years
        // This is because there is no context-free conversion between hours and days
        // (think of clock changes)
        // and also not between days and months (28-31 days per month)
        var seconds = iso_string__abs(this._milliseconds) / 1000;
        var days         = iso_string__abs(this._days);
        var months       = iso_string__abs(this._months);
        var minutes, hours, years;

        // 3600 seconds -> 60 minutes -> 1 hour
        minutes           = absFloor(seconds / 60);
        hours             = absFloor(minutes / 60);
        seconds %= 60;
        minutes %= 60;

        // 12 months -> 1 year
        years  = absFloor(months / 12);
        months %= 12;


        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
        var Y = years;
        var M = months;
        var D = days;
        var h = hours;
        var m = minutes;
        var s = seconds;
        var total = this.asSeconds();

        if (!total) {
            // this is the same as C#'s (Noda) and python (isodate)...
            // but not other JS (goog.date)
            return 'P0D';
        }

        return (total < 0 ? '-' : '') +
            'P' +
            (Y ? Y + 'Y' : '') +
            (M ? M + 'M' : '') +
            (D ? D + 'D' : '') +
            ((h || m || s) ? 'T' : '') +
            (h ? h + 'H' : '') +
            (m ? m + 'M' : '') +
            (s ? s + 'S' : '');
    }

    var duration_prototype__proto = Duration.prototype;

    duration_prototype__proto.abs            = duration_abs__abs;
    duration_prototype__proto.add            = duration_add_subtract__add;
    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
    duration_prototype__proto.as             = as;
    duration_prototype__proto.asMilliseconds = asMilliseconds;
    duration_prototype__proto.asSeconds      = asSeconds;
    duration_prototype__proto.asMinutes      = asMinutes;
    duration_prototype__proto.asHours        = asHours;
    duration_prototype__proto.asDays         = asDays;
    duration_prototype__proto.asWeeks        = asWeeks;
    duration_prototype__proto.asMonths       = asMonths;
    duration_prototype__proto.asYears        = asYears;
    duration_prototype__proto.valueOf        = duration_as__valueOf;
    duration_prototype__proto._bubble        = bubble;
    duration_prototype__proto.get            = duration_get__get;
    duration_prototype__proto.milliseconds   = milliseconds;
    duration_prototype__proto.seconds        = seconds;
    duration_prototype__proto.minutes        = minutes;
    duration_prototype__proto.hours          = hours;
    duration_prototype__proto.days           = days;
    duration_prototype__proto.weeks          = weeks;
    duration_prototype__proto.months         = months;
    duration_prototype__proto.years          = years;
    duration_prototype__proto.humanize       = humanize;
    duration_prototype__proto.toISOString    = iso_string__toISOString;
    duration_prototype__proto.toString       = iso_string__toISOString;
    duration_prototype__proto.toJSON         = iso_string__toISOString;
    duration_prototype__proto.locale         = locale;
    duration_prototype__proto.localeData     = localeData;

    // Deprecations
    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
    duration_prototype__proto.lang = lang;

    // Side effect imports

    // FORMATTING

    addFormatToken('X', 0, 0, 'unix');
    addFormatToken('x', 0, 0, 'valueOf');

    // PARSING

    addRegexToken('x', matchSigned);
    addRegexToken('X', matchTimestamp);
    addParseToken('X', function (input, array, config) {
        config._d = new Date(parseFloat(input, 10) * 1000);
    });
    addParseToken('x', function (input, array, config) {
        config._d = new Date(toInt(input));
    });

    // Side effect imports


    utils_hooks__hooks.version = '2.12.0';

    setHookCallback(local__createLocal);

    utils_hooks__hooks.fn                    = momentPrototype;
    utils_hooks__hooks.min                   = min;
    utils_hooks__hooks.max                   = max;
    utils_hooks__hooks.now                   = now;
    utils_hooks__hooks.utc                   = create_utc__createUTC;
    utils_hooks__hooks.unix                  = moment__createUnix;
    utils_hooks__hooks.months                = lists__listMonths;
    utils_hooks__hooks.isDate                = isDate;
    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
    utils_hooks__hooks.invalid               = valid__createInvalid;
    utils_hooks__hooks.duration              = create__createDuration;
    utils_hooks__hooks.isMoment              = isMoment;
    utils_hooks__hooks.weekdays              = lists__listWeekdays;
    utils_hooks__hooks.parseZone             = moment__createInZone;
    utils_hooks__hooks.localeData            = locale_locales__getLocale;
    utils_hooks__hooks.isDuration            = isDuration;
    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
    utils_hooks__hooks.defineLocale          = defineLocale;
    utils_hooks__hooks.updateLocale          = updateLocale;
    utils_hooks__hooks.locales               = locale_locales__listLocales;
    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
    utils_hooks__hooks.prototype             = momentPrototype;

    var _moment = utils_hooks__hooks;

    return _moment;

}));
},{}],3:[function(require,module,exports){
(function (root, factory) {
	if (typeof define === 'function' && define.amd) {
		// AMD. Register as an anonymous module.
		define([], factory);
	} else if (typeof exports === 'object') {
		// Node. Does not work with strict CommonJS, but
		// only CommonJS-like environments that support module.exports,
		// like Node.
		module.exports = factory();
	} else {
		// Browser globals (root is window)
		root.StringMask = factory();
	}
}(this, function () {
	var tokens = {
		'0': {pattern: /\d/, _default: '0'},
		'9': {pattern: /\d/, optional: true},
		'#': {pattern: /\d/, optional: true, recursive: true},
		'S': {pattern: /[a-zA-Z]/},
		'U': {pattern: /[a-zA-Z]/, transform: function (c) { return c.toLocaleUpperCase(); }},
		'L': {pattern: /[a-zA-Z]/, transform: function (c) { return c.toLocaleLowerCase(); }},
		'$': {escape: true}
	};

	function isEscaped(pattern, pos) {
		var count = 0;
		var i = pos - 1;
		var token = {escape: true};
		while (i >= 0 && token && token.escape) {
			token = tokens[pattern.charAt(i)];
			count += token && token.escape ? 1 : 0;
			i--;
		}
		return count > 0 && count%2 === 1;
	}

	function calcOptionalNumbersToUse(pattern, value) {
		var numbersInP = pattern.replace(/[^0]/g,'').length;
		var numbersInV = value.replace(/[^\d]/g,'').length;
		return numbersInV - numbersInP;
	}

	function concatChar(text, character, options, token) {
		if (token && typeof token.transform === 'function') character = token.transform(character);
		if (options.reverse) return character + text;
		return text + character;
	}

	function hasMoreTokens(pattern, pos, inc) {
		var pc = pattern.charAt(pos);
		var token = tokens[pc];
		if (pc === '') return false;
		return token && !token.escape ? true : hasMoreTokens(pattern, pos + inc, inc);
	}

	function insertChar(text, char, position) {
		var t = text.split('');
		t.splice(position >= 0 ? position: 0, 0, char);
		return t.join('');
	}

	function StringMask(pattern, opt) {
		this.options = opt || {};
		this.options = {
			reverse: this.options.reverse || false,
			usedefaults: this.options.usedefaults || this.options.reverse
		};
		this.pattern = pattern;
	}

	StringMask.prototype.process = function proccess(value) {
		if (!value) return '';
		value = value + '';
		var pattern2 = this.pattern;
		var valid = true;
		var formatted = '';
		var valuePos = this.options.reverse ? value.length - 1 : 0;
		var optionalNumbersToUse = calcOptionalNumbersToUse(pattern2, value);
		var escapeNext = false;
		var recursive = [];
		var inRecursiveMode = false;

		var steps = {
			start: this.options.reverse ? pattern2.length - 1 : 0,
			end: this.options.reverse ? -1 : pattern2.length,
			inc: this.options.reverse ? -1 : 1
		};

		function continueCondition(options) {
			if (!inRecursiveMode && hasMoreTokens(pattern2, i, steps.inc)) {
				return true;
			} else if (!inRecursiveMode) {
				inRecursiveMode = recursive.length > 0;
			}

			if (inRecursiveMode) {
				var pc = recursive.shift();
				recursive.push(pc);
				if (options.reverse && valuePos >= 0) {
					i++;
					pattern2 = insertChar(pattern2, pc, i);
					return true;
				} else if (!options.reverse && valuePos < value.length) {
					pattern2 = insertChar(pattern2, pc, i);
					return true;
				}
			}
			return i < pattern2.length && i >= 0;
		}

		for (var i = steps.start; continueCondition(this.options); i = i + steps.inc) {
			var pc = pattern2.charAt(i);
			var vc = value.charAt(valuePos);
			var token = tokens[pc];
			if (!inRecursiveMode || vc) {
				if (this.options.reverse && isEscaped(pattern2, i)) {
					formatted = concatChar(formatted, pc, this.options, token);
					i = i + steps.inc;
					continue;
				} else if (!this.options.reverse && escapeNext) {
					formatted = concatChar(formatted, pc, this.options, token);
					escapeNext = false;
					continue;
				} else if (!this.options.reverse && token && token.escape) {
					escapeNext = true;
					continue;
				}
			}

			if (!inRecursiveMode && token && token.recursive) {
				recursive.push(pc);
			} else if (inRecursiveMode && !vc) {
				if (!token || !token.recursive) formatted = concatChar(formatted, pc, this.options, token);
				continue;
			} else if (recursive.length > 0 && token && !token.recursive) {
				// Recursive tokens most be the last tokens of the pattern
				valid = false;
				continue;
			} else if (!inRecursiveMode && recursive.length > 0 && !vc) {
				continue;
			}

			if (!token) {
				formatted = concatChar(formatted, pc, this.options, token);
				if (!inRecursiveMode && recursive.length) {
					recursive.push(pc);
				}
			} else if (token.optional) {
				if (token.pattern.test(vc) && optionalNumbersToUse) {
					formatted = concatChar(formatted, vc, this.options, token);
					valuePos = valuePos + steps.inc;
					optionalNumbersToUse--;
				} else if (recursive.length > 0 && vc) {
					valid = false;
					break;
				}
			} else if (token.pattern.test(vc)) {
				formatted = concatChar(formatted, vc, this.options, token);
				valuePos = valuePos + steps.inc;
			} else if (!vc && token._default && this.options.usedefaults) {
				formatted = concatChar(formatted, token._default, this.options, token);
			} else {
				valid = false;
				break;
			}
		}

		return {result: formatted, valid: valid};
	};

	StringMask.prototype.apply = function(value) {
		return this.process(value).result;
	};

	StringMask.prototype.validate = function(value) {
		return this.process(value).valid;
	};

	StringMask.process = function(value, pattern, options) {
		return new StringMask(pattern, options).process(value);
	};

	StringMask.apply = function(value, pattern, options) {
		return new StringMask(pattern, options).apply(value);
	};

	StringMask.validate = function(value, pattern, options) {
		return new StringMask(pattern, options).validate(value);
	};

	return StringMask;
}));

},{}],4:[function(require,module,exports){
module.exports = angular.module('ui.utils.masks', [
	require('./global/global-masks'),
	require('./br/br-masks'),
	require('./us/us-masks')
]).name;

},{"./br/br-masks":6,"./global/global-masks":16,"./us/us-masks":24}],5:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

var boletoBancarioMask = new StringMask('00000.00000 00000.000000 00000.000000 0 00000000000000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^0-9]/g, '').slice(0, 47);
	},
	format: function(cleanValue) {
		if (cleanValue.length === 0) {
			return cleanValue;
		}

		return boletoBancarioMask.apply(cleanValue).replace(/[^0-9]$/, '');
	},
	validations: {
		brBoletoBancario: function(value) {
			return value.length === 47;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],6:[function(require,module,exports){
'use strict';

var m = angular.module('ui.utils.masks.br', [
	require('../helpers'),
])
.directive('uiBrBoletoBancarioMask', require('./boleto-bancario/boleto-bancario'))
.directive('uiBrCepMask', require('./cep/cep'))
.directive('uiBrCnpjMask', require('./cnpj/cnpj'))
.directive('uiBrCpfMask', require('./cpf/cpf'))
.directive('uiBrCpfcnpjMask', require('./cpf-cnpj/cpf-cnpj'))
.directive('uiBrIeMask', require('./inscricao-estadual/ie'))
.directive('uiNfeAccessKeyMask', require('./nfe/nfe'))
.directive('uiBrCarPlateMask', require('./car-plate/car-plate'))
.directive('uiBrPhoneNumber', require('./phone/br-phone'));

module.exports = m.name;

},{"../helpers":22,"./boleto-bancario/boleto-bancario":5,"./car-plate/car-plate":7,"./cep/cep":8,"./cnpj/cnpj":9,"./cpf-cnpj/cpf-cnpj":10,"./cpf/cpf":11,"./inscricao-estadual/ie":12,"./nfe/nfe":13,"./phone/br-phone":14}],7:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

var carPlateMask = new StringMask('UUU-0000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^a-zA-Z0-9]/g, '').slice(0, 7);
	},
	format: function(cleanValue) {
		return (carPlateMask.apply(cleanValue) || '').replace(/[^a-zA-Z0-9]$/, '');
	},
	validations: {
		carPlate: function(value) {
			return value.length === 7;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],8:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

var cepMask = new StringMask('00000-000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^0-9]/g, '').slice(0, 8);
	},
	format: function(cleanValue) {
		return (cepMask.apply(cleanValue) || '').replace(/[^0-9]$/, '');
	},
	validations: {
		cep: function(value) {
			return value.length === 8;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],9:[function(require,module,exports){
var StringMask = require('string-mask');
var BrV = require('br-validations');
var maskFactory = require('mask-factory');

var cnpjPattern = new StringMask('00.000.000\/0000-00');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^\d]/g, '').slice(0, 14);
	},
	format: function(cleanValue) {
		return (cnpjPattern.apply(cleanValue) || '').trim().replace(/[^0-9]$/, '');
	},
	validations: {
		cnpj: function(value) {
			return BrV.cnpj.validate(value);
		}
	}
});

},{"br-validations":1,"mask-factory":"mask-factory","string-mask":3}],10:[function(require,module,exports){
var StringMask = require('string-mask');
var BrV = require('br-validations');
var maskFactory = require('mask-factory');

var cnpjPattern = new StringMask('00.000.000\/0000-00');
var cpfPattern = new StringMask('000.000.000-00');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^\d]/g, '').slice(0, 14);
	},
	format: function(cleanValue) {
		var formatedValue;

		if (cleanValue.length > 11) {
			formatedValue = cnpjPattern.apply(cleanValue);
		} else {
			formatedValue = cpfPattern.apply(cleanValue) || '';
		}

		return formatedValue.trim().replace(/[^0-9]$/, '');
	},
	validations: {
		cpf: function(value) {
			return value.length > 11 || BrV.cpf.validate(value);
		},
		cnpj: function(value) {
			return value.length <= 11 || BrV.cnpj.validate(value);
		}
	}
});

},{"br-validations":1,"mask-factory":"mask-factory","string-mask":3}],11:[function(require,module,exports){
var StringMask = require('string-mask');
var BrV = require('br-validations');
var maskFactory = require('mask-factory');

var cpfPattern = new StringMask('000.000.000-00');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^\d]/g, '').slice(0, 11);
	},
	format: function(cleanValue) {
		return (cpfPattern.apply(cleanValue) || '').trim().replace(/[^0-9]$/, '');
	},
	validations: {
		cpf: function(value) {
			return BrV.cpf.validate(value);
		}
	}
});

},{"br-validations":1,"mask-factory":"mask-factory","string-mask":3}],12:[function(require,module,exports){
var StringMask = require('string-mask');
var BrV = require('br-validations');

function BrIeMaskDirective($parse) {
	var ieMasks = {
		'AC': [{mask: new StringMask('00.000.000/000-00')}],
		'AL': [{mask: new StringMask('000000000')}],
		'AM': [{mask: new StringMask('00.000.000-0')}],
		'AP': [{mask: new StringMask('000000000')}],
		'BA': [{chars: 8, mask: new StringMask('000000-00')},
			   {mask: new StringMask('0000000-00')}],
		'CE': [{mask: new StringMask('00000000-0')}],
		'DF': [{mask: new StringMask('00000000000-00')}],
		'ES': [{mask: new StringMask('00000000-0')}],
		'GO': [{mask: new StringMask('00.000.000-0')}],
		'MA': [{mask: new StringMask('000000000')}],
		'MG': [{mask: new StringMask('000.000.000/0000')}],
		'MS': [{mask: new StringMask('000000000')}],
		'MT': [{mask: new StringMask('0000000000-0')}],
		'PA': [{mask: new StringMask('00-000000-0')}],
		'PB': [{mask: new StringMask('00000000-0')}],
		'PE': [{chars: 9, mask: new StringMask('0000000-00')},
			   {mask: new StringMask('00.0.000.0000000-0')}],
		'PI': [{mask: new StringMask('000000000')}],
		'PR': [{mask: new StringMask('000.00000-00')}],
		'RJ': [{mask: new StringMask('00.000.00-0')}],
		'RN': [{chars: 9, mask: new StringMask('00.000.000-0')},
			   {mask: new StringMask('00.0.000.000-0')}],
		'RO': [{mask: new StringMask('0000000000000-0')}],
		'RR': [{mask: new StringMask('00000000-0')}],
		'RS': [{mask: new StringMask('000/0000000')}],
		'SC': [{mask: new StringMask('000.000.000')}],
		'SE': [{mask: new StringMask('00000000-0')}],
		'SP': [{mask: new StringMask('000.000.000.000')},
			   {mask: new StringMask('-00000000.0/000')}],
		'TO': [{mask: new StringMask('00000000000')}]
	};

	function clearValue (value) {
		if (!value) {
			return value;
		}

		return value.replace(/[^0-9]/g, '');
	}

	function getMask(uf, value) {
		if (!uf || !ieMasks[uf]) {
			return undefined;
		}

		if (uf === 'SP' && /^P/i.test(value)) {
			return ieMasks.SP[1].mask;
		}

		var masks = ieMasks[uf];
		var i = 0;
		while(masks[i].chars && masks[i].chars < clearValue(value).length && i < masks.length - 1) {
			i++;
		}

		return masks[i].mask;
	}

	function applyIEMask(value, uf) {
		var mask = getMask(uf, value);

		if(!mask) {
			return value;
		}

		var processed = mask.process(clearValue(value));
		var formatedValue = processed.result || '';
		formatedValue = formatedValue.trim().replace(/[^0-9]$/, '');

		if (uf === 'SP' && /^p/i.test(value)) {
			return 'P' + formatedValue;
		}

		return formatedValue;
	}

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, element, attrs, ctrl) {
			var state = ($parse(attrs.uiBrIeMask)(scope) || '').toUpperCase();

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				return applyIEMask(value, state);
			}

			function parser(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var formatedValue = applyIEMask(value, state);
				var actualValue = clearValue(formatedValue);

				if (ctrl.$viewValue !== formatedValue) {
					ctrl.$setViewValue(formatedValue);
					ctrl.$render();
				}

				if (state && state.toUpperCase() === 'SP' && /^p/i.test(value)) {
					return 'P' + actualValue;
				}

				return actualValue;
			}

			ctrl.$formatters.push(formatter);
			ctrl.$parsers.push(parser);

			ctrl.$validators.ie = function validator(modelValue) {
				return ctrl.$isEmpty(modelValue) || BrV.ie(state).validate(modelValue);
			};

			scope.$watch(attrs.uiBrIeMask, function(newState) {
				state = (newState || '').toUpperCase();

				parser(ctrl.$viewValue);
				ctrl.$validate();
			});
		}
	};
}
BrIeMaskDirective.$inject = ['$parse'];

module.exports = BrIeMaskDirective;

},{"br-validations":1,"string-mask":3}],13:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

var nfeAccessKeyMask = new StringMask('0000 0000 0000 0000 0000' +
	' 0000 0000 0000 0000 0000 0000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.replace(/[^0-9]/g, '').slice(0, 44);
	},
	format: function(cleanValue) {
		return (nfeAccessKeyMask.apply(cleanValue) || '').replace(/[^0-9]$/, '');
	},
	validations: {
		nfeAccessKey: function(value) {
			return value.length === 44;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],14:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

/**
 * FIXME: all numbers will have 9 digits after 2016.
 * see http://portal.embratel.com.br/embratel/9-digito/
 */
var phoneMask8D = new StringMask('(00) 0000-0000'),
	phoneMask9D = new StringMask('(00) 00000-0000'),
	phoneMask0800 = new StringMask('0000-000-0000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.toString().replace(/[^0-9]/g, '').slice(0, 11);
	},
	format: function(cleanValue) {
		var formatedValue;
		if(cleanValue.indexOf('0800') === 0) {
			formatedValue = phoneMask0800.apply(cleanValue);
		}else if(cleanValue.length < 11){
			formatedValue = phoneMask8D.apply(cleanValue) || '';
		}else{
			formatedValue = phoneMask9D.apply(cleanValue);
		}

		return formatedValue.trim().replace(/[^0-9]$/, '');
	},
	getModelValue: function(formattedValue, originalModelType) {
		var cleanValue = this.clearValue(formattedValue);

		return originalModelType === 'number' ? parseInt(cleanValue) : cleanValue;
	},
	validations: {
		brPhoneNumber: function(value) {
			var valueLength = value && value.toString().length;
			return valueLength === 10 || valueLength === 11;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],15:[function(require,module,exports){
var moment = require('moment');
var StringMask = require('string-mask');

function isISODateString(date) {
	return /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z$/
		.test(date.toString());
}

function DateMaskDirective($locale) {
	var dateFormatMapByLocale = {
		'pt-br': 'DD/MM/YYYY',
	};

	var dateFormat = dateFormatMapByLocale[$locale.id] || 'YYYY-MM-DD';

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, element, attrs, ctrl) {
			var dateMask = new StringMask(dateFormat.replace(/[YMD]/g,'0'));

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var cleanValue = value;
				if (typeof value === 'object' || isISODateString(value)) {
					cleanValue = moment(value).format(dateFormat);
				}

				cleanValue = cleanValue.replace(/[^0-9]/g, '');
				var formatedValue = dateMask.apply(cleanValue) || '';

				return formatedValue.trim().replace(/[^0-9]$/, '');
			}

			ctrl.$formatters.push(formatter);

			ctrl.$parsers.push(function parser(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var formatedValue = formatter(value);

				if (ctrl.$viewValue !== formatedValue) {
					ctrl.$setViewValue(formatedValue);
					ctrl.$render();
				}

				return moment(formatedValue, dateFormat).toDate();
			});

			ctrl.$validators.date =	function validator(modelValue, viewValue) {
				if (ctrl.$isEmpty(modelValue)) {
					return true;
				}

				return moment(viewValue, dateFormat).isValid() && viewValue.length === dateFormat.length;
			};
		}
	};
}
DateMaskDirective.$inject = ['$locale'];

module.exports = DateMaskDirective;

},{"moment":2,"string-mask":3}],16:[function(require,module,exports){
'use strict';

var m = angular.module('ui.utils.masks.global', [
	require('../helpers'),
])
.directive('uiDateMask', require('./date/date'))
.directive('uiMoneyMask', require('./money/money'))
.directive('uiNumberMask', require('./number/number'))
.directive('uiPercentageMask', require('./percentage/percentage'))
.directive('uiScientificNotationMask', require('./scientific-notation/scientific-notation'))
.directive('uiTimeMask', require('./time/time'));

module.exports = m.name;

},{"../helpers":22,"./date/date":15,"./money/money":17,"./number/number":18,"./percentage/percentage":19,"./scientific-notation/scientific-notation":20,"./time/time":21}],17:[function(require,module,exports){
var StringMask = require('string-mask');
var validators = require('validators');

function MoneyMaskDirective($locale, $parse, PreFormatters) {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, ctrl) {
			var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
				thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
				currencySym = $locale.NUMBER_FORMATS.CURRENCY_SYM,
				decimals = $parse(attrs.uiMoneyMask)(scope);

			function maskFactory(decimals) {
					var decimalsPattern = decimals > 0 ? decimalDelimiter + new Array(decimals + 1).join('0') : '';
					var maskPattern = currencySym + ' #' + thousandsDelimiter + '##0' + decimalsPattern;
					return new StringMask(maskPattern, {reverse: true});
			}

			if (angular.isDefined(attrs.uiHideGroupSep)){
				thousandsDelimiter = '';
			}

			if(isNaN(decimals)) {
				decimals = 2;
			}

			var moneyMask = maskFactory(decimals);

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}
				var prefix = (angular.isDefined(attrs.uiNegativeNumber) && value < 0) ? '-' : '';
				var valueToFormat = PreFormatters.prepareNumberToFormatter(value, decimals);
				return prefix + moneyMask.apply(valueToFormat);
			}

			function parser(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var actualNumber = value.replace(/[^\d]+/g,'');
				actualNumber = actualNumber.replace(/^[0]+([1-9])/,'$1');
				var formatedValue = moneyMask.apply(actualNumber);

				if (angular.isDefined(attrs.uiNegativeNumber)) {
						var isNegative = (value[0] === '-'),
						needsToInvertSign = (value.slice(-1) === '-');

					//only apply the minus sign if it is negative or(exclusive)
					//needs to be negative and the number is different from zero
					if (needsToInvertSign ^ isNegative && !!actualNumber) {
						actualNumber *= -1;
						formatedValue = '-' + formatedValue;
					}
				}

				if (value !== formatedValue) {
					ctrl.$setViewValue(formatedValue);
					ctrl.$render();
				}

				return formatedValue ? parseInt(formatedValue.replace(/[^\d\-]+/g,''))/Math.pow(10,decimals) : null;
			}

			ctrl.$formatters.push(formatter);
			ctrl.$parsers.push(parser);

			if (attrs.uiMoneyMask) {
				scope.$watch(attrs.uiMoneyMask, function(_decimals) {
					decimals = isNaN(_decimals) ? 2 : _decimals;
					moneyMask = maskFactory(decimals);

					parser(ctrl.$viewValue);
				});
			}

			if (attrs.min) {
				var minVal;

				ctrl.$validators.min = function(modelValue) {
					return validators.minNumber(ctrl, modelValue, minVal);
				};

				scope.$watch(attrs.min, function(value) {
					minVal = value;
					ctrl.$validate();
				});
			}

			if (attrs.max) {
				var maxVal;
				
				ctrl.$validators.max = function(modelValue) {
					return validators.maxNumber(ctrl, modelValue, maxVal);
				};

				scope.$watch(attrs.max, function(value) {
					maxVal = value;
					ctrl.$validate();
				});
			}
		}
	};
}
MoneyMaskDirective.$inject = ['$locale', '$parse', 'PreFormatters'];

module.exports = MoneyMaskDirective;

},{"string-mask":3,"validators":"validators"}],18:[function(require,module,exports){
var validators = require('validators');

function NumberMaskDirective($locale, $parse, PreFormatters, NumberMasks) {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, ctrl) {
			var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
				thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
				decimals = $parse(attrs.uiNumberMask)(scope);

			if (angular.isDefined(attrs.uiHideGroupSep)){
				thousandsDelimiter = '';
			}

			if(isNaN(decimals)) {
				decimals = 2;
			}

			var viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter),
				modelMask = NumberMasks.modelMask(decimals);

			function parser(value) {
				if(ctrl.$isEmpty(value)) {
					return null;
				}

				var valueToFormat = PreFormatters.clearDelimitersAndLeadingZeros(value) || '0';
				var formatedValue = viewMask.apply(valueToFormat);
				var actualNumber = parseFloat(modelMask.apply(valueToFormat));

				if (angular.isDefined(attrs.uiNegativeNumber)) {
					var isNegative = (value[0] === '-'),
						needsToInvertSign = (value.slice(-1) === '-');

					//only apply the minus sign if it is negative or(exclusive)
					//needs to be negative and the number is different from zero
					if (needsToInvertSign ^ isNegative && !!actualNumber) {
						actualNumber *= -1;
						formatedValue = '-' + formatedValue;
					}
				}

				if (ctrl.$viewValue !== formatedValue) {
					ctrl.$setViewValue(formatedValue);
					ctrl.$render();
				}

				return actualNumber;
			}

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var prefix = (angular.isDefined(attrs.uiNegativeNumber) && value < 0) ? '-' : '';
				var valueToFormat = PreFormatters.prepareNumberToFormatter(value, decimals);
				return prefix + viewMask.apply(valueToFormat);
			}

			ctrl.$formatters.push(formatter);
			ctrl.$parsers.push(parser);

			if (attrs.uiNumberMask) {
				scope.$watch(attrs.uiNumberMask, function(_decimals) {
					decimals = isNaN(_decimals) ? 2 : _decimals;
					viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter);
					modelMask = NumberMasks.modelMask(decimals);

					parser(ctrl.$viewValue);
				});
			}

			if (attrs.min) {
				var minVal;

				ctrl.$validators.min = function(modelValue) {
					return validators.minNumber(ctrl, modelValue, minVal);
				};

				scope.$watch(attrs.min, function(value) {
					minVal = value;
					ctrl.$validate();
				});
			}

			if (attrs.max) {
				var maxVal;

				ctrl.$validators.max = function(modelValue) {
					return validators.maxNumber(ctrl, modelValue, maxVal);
				};

				scope.$watch(attrs.max, function(value) {
					maxVal = value;
					ctrl.$validate();
				});
			}
		}
	};
}
NumberMaskDirective.$inject = ['$locale', '$parse', 'PreFormatters', 'NumberMasks'];

module.exports = NumberMaskDirective;

},{"validators":"validators"}],19:[function(require,module,exports){
var validators = require('validators');

function PercentageMaskDirective($locale, $parse, PreFormatters, NumberMasks) {
	function preparePercentageToFormatter(value, decimals, modelMultiplier) {
		return PreFormatters.clearDelimitersAndLeadingZeros((parseFloat(value)*modelMultiplier).toFixed(decimals));
	}

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function (scope, element, attrs, ctrl) {
			var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
				thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
				decimals = parseInt(attrs.uiPercentageMask);

			var modelValue = {
				multiplier : 100,
				decimalMask: 2
			};

			if (angular.isDefined(attrs.uiHideGroupSep)){
				thousandsDelimiter = '';
			}

			if (angular.isDefined(attrs.uiPercentageValue)) {
				modelValue.multiplier  = 1;
				modelValue.decimalMask = 0;
			}

			if(isNaN(decimals)) {
				decimals = 2;
			}

			var numberDecimals = decimals + modelValue.decimalMask;
			var viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter),
				modelMask = NumberMasks.modelMask(numberDecimals);

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var valueToFormat = preparePercentageToFormatter(value, decimals, modelValue.multiplier);
				return viewMask.apply(valueToFormat) + ' %';
			}

			function parse(value) {
				if (ctrl.$isEmpty(value)) {
					return null;
				}

				var valueToFormat = PreFormatters.clearDelimitersAndLeadingZeros(value) || '0';
				if (value.length > 1 && value.indexOf('%') === -1) {
					valueToFormat = valueToFormat.slice(0,valueToFormat.length-1);
				}
				var formatedValue = viewMask.apply(valueToFormat) + ' %';
				var actualNumber = parseFloat(modelMask.apply(valueToFormat));

				if (ctrl.$viewValue !== formatedValue) {
					ctrl.$setViewValue(formatedValue);
					ctrl.$render();
				}

				return actualNumber;
			}

			ctrl.$formatters.push(formatter);
			ctrl.$parsers.push(parse);

			if (attrs.uiPercentageMask) {
				scope.$watch(attrs.uiPercentageMask, function(_decimals) {
					decimals = isNaN(_decimals) ? 2 : _decimals;

					if (angular.isDefined(attrs.uiPercentageValue)) {
						modelValue.multiplier  = 1;
						modelValue.decimalMask = 0;
					}

					numberDecimals = decimals + modelValue.decimalMask;
					viewMask = NumberMasks.viewMask(decimals, decimalDelimiter, thousandsDelimiter);
					modelMask = NumberMasks.modelMask(numberDecimals);

					parse(ctrl.$viewValue);
				});
			}

			if (attrs.min) {
				var minVal;

				ctrl.$validators.min = function(modelValue) {
					return validators.minNumber(ctrl, modelValue, minVal);
				};

				scope.$watch(attrs.min, function(value) {
					minVal = value;
					ctrl.$validate();
				});
			}

			if (attrs.max) {
				var maxVal;

				ctrl.$validators.max = function(modelValue) {
					return validators.maxNumber(ctrl, modelValue, maxVal);
				};

				scope.$watch(attrs.max, function(value) {
					maxVal = value;
					ctrl.$validate();
				});
			}
		}
	};
}
PercentageMaskDirective.$inject = ['$locale', '$parse', 'PreFormatters', 'NumberMasks'];

module.exports = PercentageMaskDirective;

},{"validators":"validators"}],20:[function(require,module,exports){
var StringMask = require('string-mask');

function ScientificNotationMaskDirective($locale, $parse) {
	var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
		defaultPrecision = 2;

	function significandMaskBuilder(decimals) {
		var mask = '0';

		if (decimals > 0) {
			mask += decimalDelimiter;
			for (var i = 0; i < decimals; i++) {
				mask += '0';
			}
		}

		return new StringMask(mask, {
			reverse: true
		});
	}

	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, element, attrs, ctrl) {
			var decimals = $parse(attrs.uiScientificNotationMask)(scope);

			if (isNaN(decimals)) {
				decimals = defaultPrecision;
			}

			var significandMask = significandMaskBuilder(decimals);

			function splitNumber (value) {
				var stringValue = value.toString(),
					splittedNumber = stringValue.match(/(-?[0-9]*)[\.]?([0-9]*)?[Ee]?([\+-]?[0-9]*)?/);

				return {
					integerPartOfSignificand: splittedNumber[1],
					decimalPartOfSignificand: splittedNumber[2],
					exponent: splittedNumber[3] | 0
				};
			}

			function formatter (value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				if (typeof value === 'string') {
					value = value.replace(decimalDelimiter, '.');
				} else if (typeof value === 'number') {
					value = value.toExponential(decimals);
				}

				var formattedValue, exponent;
				var splittedNumber = splitNumber(value);

				var integerPartOfSignificand = splittedNumber.integerPartOfSignificand || 0;
				var numberToFormat = integerPartOfSignificand.toString();
				if (angular.isDefined(splittedNumber.decimalPartOfSignificand)) {
					numberToFormat += splittedNumber.decimalPartOfSignificand;
				}

				var needsNormalization =
					(integerPartOfSignificand >= 1 || integerPartOfSignificand <= -1) &&
					(
						(angular.isDefined(splittedNumber.decimalPartOfSignificand) &&
						splittedNumber.decimalPartOfSignificand.length > decimals) ||
						(decimals === 0 && numberToFormat.length >= 2)
					);

				if (needsNormalization) {
					exponent = numberToFormat.slice(decimals + 1, numberToFormat.length);
					numberToFormat = numberToFormat.slice(0, decimals + 1);
				}

				formattedValue = significandMask.apply(numberToFormat);

				if (splittedNumber.exponent !== 0) {
					exponent = splittedNumber.exponent;
				}

				if (angular.isDefined(exponent)) {
					formattedValue += 'e' + exponent;
				}

				return formattedValue;
			}

			function parser (value) {
				if(ctrl.$isEmpty(value)) {
					return value;
				}

				var viewValue = formatter(value),
					modelValue = parseFloat(viewValue.replace(decimalDelimiter, '.'));

				if (ctrl.$viewValue !== viewValue) {
					ctrl.$setViewValue(viewValue);
					ctrl.$render();
				}

				return modelValue;
			}

			ctrl.$formatters.push(formatter);
			ctrl.$parsers.push(parser);

			ctrl.$validators.max = function validator (value) {
				return ctrl.$isEmpty(value) || value < Number.MAX_VALUE;
			};
		}
	};
}
ScientificNotationMaskDirective.$inject = ['$locale', '$parse'];

module.exports = ScientificNotationMaskDirective;

},{"string-mask":3}],21:[function(require,module,exports){
var StringMask = require('string-mask');

module.exports = function TimeMaskDirective() {
	return {
		restrict: 'A',
		require: 'ngModel',
		link: function(scope, element, attrs, ctrl) {
			var timeFormat = '00:00:00';

			if (angular.isDefined(attrs.uiTimeMask) && attrs.uiTimeMask === 'short') {
				timeFormat = '00:00';
			}

			var formattedValueLength = timeFormat.length;
			var unformattedValueLength = timeFormat.replace(':', '').length;
			var timeMask = new StringMask(timeFormat);

			function formatter(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var cleanValue = value.replace(/[^0-9]/g, '').slice(0, unformattedValueLength) || '';
				return (timeMask.apply(cleanValue) || '').replace(/[^0-9]$/, '');
			}

			ctrl.$formatters.push(formatter);

			ctrl.$parsers.push(function parser(value) {
				if (ctrl.$isEmpty(value)) {
					return value;
				}

				var viewValue = formatter(value);
				var modelValue = viewValue;

				if (ctrl.$viewValue !== viewValue) {
					ctrl.$setViewValue(viewValue);
					ctrl.$render();
				}

				return modelValue;
			});

			ctrl.$validators.time = function (modelValue) {
				if (ctrl.$isEmpty(modelValue)) {
					return true;
				}

				var splittedValue = modelValue.toString().split(/:/).filter(function(v) {
					return !!v;
				});

				var hours = parseInt(splittedValue[0]),
					minutes = parseInt(splittedValue[1]),
					seconds = parseInt(splittedValue[2] || 0);

				return modelValue.toString().length === formattedValueLength &&
					hours < 24 && minutes < 60 && seconds < 60;
			};
		}
	};
};

},{"string-mask":3}],22:[function(require,module,exports){
var StringMask = require('string-mask');

var m = angular.module('ui.utils.masks.helpers', []);

module.exports = m.name;

m.factory('PreFormatters', [function(){
	function clearDelimitersAndLeadingZeros(value) {
		if (value === '0') {
			return '0';
		}

		var cleanValue = value.replace(/^-/,'').replace(/^0*/, '');
		return cleanValue.replace(/[^0-9]/g, '');
	}

	function prepareNumberToFormatter (value, decimals) {
		return clearDelimitersAndLeadingZeros((parseFloat(value)).toFixed(decimals));
	}

	return {
		clearDelimitersAndLeadingZeros: clearDelimitersAndLeadingZeros,
		prepareNumberToFormatter: prepareNumberToFormatter
	};
}])
.factory('NumberValidators', [function() {
	return {
		maxNumber: function maxValidator(ctrl, value, limit) {
			var max = parseFloat(limit);
			var validity = ctrl.$isEmpty(value) || isNaN(max)|| value <= max;
			ctrl.$setValidity('max', validity);
			return value;
		},
		minNumber: function minValidator(ctrl, value, limit) {
			var min = parseFloat(limit);
			var validity = ctrl.$isEmpty(value) || isNaN(min) || value >= min;
			ctrl.$setValidity('min', validity);
			return value;
		}
	};
}])
.factory('NumberMasks', [function(){
	return {
		viewMask: function (decimals, decimalDelimiter, thousandsDelimiter) {
			var mask = '#' + thousandsDelimiter + '##0';

			if(decimals > 0) {
				mask += decimalDelimiter;
				for (var i = 0; i < decimals; i++) {
					mask += '0';
				}
			}

			return new StringMask(mask, {
				reverse: true
			});
		},
		modelMask: function (decimals) {
			var mask = '###0';

			if(decimals > 0) {
				mask += '.';
				for (var i = 0; i < decimals; i++) {
					mask += '0';
				}
			}

			return new StringMask(mask, {
				reverse: true
			});
		}
	};
}]);

},{"string-mask":3}],23:[function(require,module,exports){
var StringMask = require('string-mask');
var maskFactory = require('mask-factory');

var phoneMaskUS = new StringMask('(000) 000-0000'),
	phoneMaskINTL = new StringMask('+00-00-000-000000');

module.exports = maskFactory({
	clearValue: function(rawValue) {
		return rawValue.toString().replace(/[^0-9]/g, '');
	},
	format: function(cleanValue) {
		var formattedValue;

		if(cleanValue.length < 11){
			formattedValue = phoneMaskUS.apply(cleanValue) || '';
		}else{
			formattedValue = phoneMaskINTL.apply(cleanValue);
		}

		return formattedValue.trim().replace(/[^0-9]$/, '');
	},
	validations: {
		usPhoneNumber: function(value) {
			return value.length > 9;
		}
	}
});

},{"mask-factory":"mask-factory","string-mask":3}],24:[function(require,module,exports){
'use strict';

var m = angular.module('ui.utils.masks.us', [
	require('../helpers')
])
.directive('uiUsPhoneNumber', require('./phone/us-phone'));

module.exports = m.name;

},{"../helpers":22,"./phone/us-phone":23}],"mask-factory":[function(require,module,exports){
'use strict';

module.exports = function maskFactory(maskDefinition) {
	return function MaskDirective() {
		return {
			restrict: 'A',
			require: 'ngModel',
			link: function(scope, element, attrs, ctrl) {
				ctrl.$formatters.push(function formatter(value) {
					if (ctrl.$isEmpty(value)) {
						return value;
					}

					var cleanValue = maskDefinition.clearValue(value);
					return maskDefinition.format(cleanValue);
				});

				ctrl.$parsers.push(function parser(value) {
					if (ctrl.$isEmpty(value)) {
						return value;
					}

					var cleanValue = maskDefinition.clearValue(value);
					var formattedValue = maskDefinition.format(cleanValue);

					if (ctrl.$viewValue !== formattedValue) {
						ctrl.$setViewValue(formattedValue);
						ctrl.$render();
					}

					if (angular.isUndefined(maskDefinition.getModelValue)) {
						return cleanValue;
					}

					var actualModelType = typeof ctrl.$modelValue;
					return maskDefinition.getModelValue(formattedValue, actualModelType);
				});

				angular.forEach(maskDefinition.validations, function(validatorFn, validationErrorKey) {
					ctrl.$validators[validationErrorKey] = function validator(modelValue, viewValue) {
						return ctrl.$isEmpty(modelValue) || validatorFn(modelValue, viewValue);
					};
				});
			}
		};
	};
};

},{}],"validators":[function(require,module,exports){
'use strict';

module.exports = {
	maxNumber: function(ctrl, value, limit) {
		var max = parseFloat(limit, 10);
		return ctrl.$isEmpty(value) || isNaN(max) || value <= max;
	},
	minNumber: function(ctrl, value, limit) {
		var min = parseFloat(limit, 10);
		return ctrl.$isEmpty(value) || isNaN(min) || value >= min;
	}
};

},{}]},{},[4]);
;
(function () {
    var app = angular.module("app-hd");

    app.directive('autoFocus', function ($timeout) {
        return {
            restrict: 'AC',
            link: function (_scope, _element) {
                $timeout(function () {
                    //_element[0].focus();
                    var x = window.scrollX, y = window.scrollY;
                    _element[0].focus();
                    window.scrollTo(x, y);
                }, 0);
            }
        };
    });
//})();
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");

    app.directive('back', ['$window', function ($window) {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.bind('click', function () {
                    $window.history.back();
                });
            }
        };
    }]);
}(angular.module("app-hd")));;
app.directive('blinkMe', function () {
    return {
        restrict: 'A',
        link: {
            pre: function (scope, element, attrs) {
                blinkNTimes(element, attrs.blinkMe);
            }
        }
    };

    function blinkNTimes(ctrl, n) {
        ctrl.fadeOut(500,
            function () {
                ctrl.fadeIn(200, function () {
                    if (--n > 0) {
                        blinkNTimes(ctrl, n);
                    }
                });
            });
    }
});
(function () {
    var app = angular.module("app-hd");
    app.directive("cat", function () {
        function link(scope, element, attributes) {
            scope.$watch(attributes.category);
        }

        // Return the isolate-scope directive configuration.
        return ({
            link: link,
            templateUrl: "app/hd/views/shopping-category-products-grid.html" + appVersion
        });
    });
})();
(function () {

    angular.module("app-hd").directive('copyToClipboard', function () {
        return {
            restrict: 'A',
            link: function (scope, elem, attrs) {
                elem.click(function () {
                    if (attrs.copyToClipboard) {
                        var $temp_input = $("<input>");
                        $("body").append($temp_input);
                        $temp_input.val(attrs.copyToClipboard).select();
                        document.execCommand("copy");
                        $temp_input.remove();
                    }
                });
            }
        };
    });;

}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");

    app.directive('jqdatepickerflex', function () {
        return {
            restrict: 'A',
            scope: {
                //'mindate': '=',
                'maxdate': '='
            },
            require: 'ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {
                
                //var currentMinDate = {};
                var currentMaxDate = {};
                
                scope.$watch('maxdate', function (newVal) {
                    currentMaxDate = new Date(newVal);

                    element.datepicker({
                        dateFormat: 'yy-MM-dd',
                        //minDate: currentMinDate,
                        maxDate: newVal,
                        defaultDate: ngModelCtrl.$viewValue,
                        onSelect: function (date) {
                            ngModelCtrl.$setViewValue(date);
                            //scope.$parent.selectedDate = date;
                            //scope.$apply();
                        }
                    });
                });
            }
        };
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");

    app.directive('jqdatepicker', function () {
        return {
            restrict: 'A',
            scope: {
                'possibleDates': '=',
            },
            require: 'ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {

                var _allowedDates = {};



                scope.$watch('possibleDates', function (newVal) {

                    _allowedDates = angular.copy(newVal);

                    var minDate = new Date(_allowedDates[0].value);
                    var maxDate = angular.copy(minDate);
                    maxDate.setMonth(maxDate.getMonth() + 2);

                    element.datepicker({
                        dateFormat: 'mm/dd/yy',
                        minDate: minDate,
                        maxDate: maxDate,
                        defaultDate: ngModelCtrl.$viewValue,
                        onSelect: function (date) {
                            scope.$parent.dateOptionSelected(date)
                            //scope.$parent.selectedDate = date;
                            scope.$apply();
                        },
                        beforeShowDay: function allowedDates(date) {
                            date = date.getTime();
                            for (i in _allowedDates)
                                if (date == new Date(_allowedDates[i].text).getTime())
                                    return [true, ""];

                            return [false, ""];
                        }
                    });
                });
            }
        };
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");

    app.directive('dollarsCents', ["common", function (common) {
        function link(scope, element, attributes) {
            scope.$watch('amount', function (newVal, oldVal) {
                scope.minus = scope.amount < 0 ? '-' : '';
                scope.dollars = common.getDollars(Math.abs(scope.amount));
                scope.cents = common.getCents(Math.abs(scope.amount));
            });
        }
        return {
            templateUrl: "app/hd/views/dollars-cents.html" + appVersion,
            link: link,
            scope: {
                amount: '='
            }
        };
    }]);
}(angular.module("app-hd")));;
var fileInput = function ($parse) {
    return {
        restrict: "EA",
        template: "<input type='file' />",
        replace: true,
        link: function (scope, element, attrs) {

            var modelGet = $parse(attrs.fileInput);
            var modelSet = modelGet.assign;
            var onChange = $parse(attrs.onChange);

            var updateModel = function () {
                scope.$apply(function () {
                    modelSet(scope, element[0].files[0]);
                    onChange(scope);
                });
            };

            element.bind('change', updateModel);
        }
    };
};;
(function () {

    angular.module("app-hd").directive('customOnChange', function () {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                var onChangeFunc = scope.$eval(attrs.customOnChange);
                element.bind('change', onChangeFunc);
            }
        };
    });

}(angular.module("app-hd")));;
(function () {
    var datePicker = angular.module('app-hd');

    datePicker.directive('inputDatepicker', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModelCtrl) {
                element.datepicker({
                    dateFormat: 'mm/dd/yy',
                    changeMonth: true,
                    changeYear: true,
                    yearRange: '-100:+0',
                    onSelect: function (date) {
                        ngModelCtrl.$setViewValue(date);
                    }
                });
            }
        };
    });
}(angular.module("app-hd")));;
(function () {
    var myModalApp = angular.module("app-hd");

    myModalApp.directive('modal', ["$timeout", function ($timeout) {
        return {
            template: '<div class="modal fade {{ class }}" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true"><div class="modal-dialog modal-sm"><div class="modal-content" ng-transclude><div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><h4 class="modal-title" id="myModalLabel">Modal title</h4></div></div></div></div>',
            restrict: 'E',
            transclude: true,
            replace: true,
            scope: { visible: '=', onShow: '&', onHide: '&' },
            link: function postLink(scope, element, attrs) {
                scope.class = attrs.class;
                $(element).modal({
                    show: false,
                    backdrop: 'static', 
                    keyboard: false
                });

                scope.$watch(function () { return scope.visible; }, function (value) {
                    if (value == true) {
                        $(element).modal('show');
                    } else {
                        $(element).modal('hide');
                        $(".modal-backdrop.in").hide();
                    }
                });

                $(element).on('shown.bs.modal', function () {
                    $timeout(function () {
                        scope.$apply(function () {
                            scope.$parent[attrs.visible] = true;
                        });
                    });
                });

                $(element).on('shown.bs.modal', function () {
                    $timeout(function () {
                        scope.$apply(function () {
                            scope.onShow({});
                        });
                    });
                });

                $(element).on('hidden.bs.modal', function () {
                    scope.$apply(function () {
                        scope.$parent[attrs.visible] = false;
                    });
                });

                $(element).on('hidden.bs.modal', function () {
                    scope.$apply(function () {
                        scope.onHide({});
                        //TODO: Why did I need to add this in order to close and reopen when background is clicked?
                        //http://jsfiddle.net/hasan2002/huspb8to/
                        scope.visible = false;
                    });
                });
            }
        };
    }]);

    myModalApp.directive('modalHeader', function () {
        return {
            template: '<div class="modal-header"><button type="button" ng-click="onClose()" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button><h3 class="modal-title">{{title}}</h3></div>',
            replace: true,
            restrict: 'E',
            scope: { title: '@', onClose: '&' }
        };
    });

    myModalApp.directive('modalBody', function () {
        return {
            template: '<div class="modal-body" ng-transclude></div>',
            replace: true,
            restrict: 'E',
            transclude: true
        };
    });

    myModalApp.directive('modalFooter', function () {
        return {
            template: '<div class="modal-footer" ng-transclude></div>',
            replace: true,
            restrict: 'E',
            transclude: true
        };
    });
}(angular.module("app-hd")));

//window.onhashchange = function () {
//    $(".modal-backdrop.in").hide();
//    $('.modal').modal('hide');
//}
;
var app = angular.module("app-hd");

app.filter('percentage', ['$filter', function ($filter) {
    return function (input, decimals) {
        return $filter('number')(input * 100, decimals) + '%';
    };
}]);;
(function () {
    var app = angular.module("app-hd");
    app.directive("productTile", function () {
        function link(scope, element, attributes) {
            scope.$watch(attributes.product);
        }

        // Return the isolate-scope directive configuration.
        return ({
            link: link,
            templateUrl: "app/hd/views/shopping-product-tile.html" + appVersion
        });
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");
    app.directive("productTileCart", function () {
        function link(scope, element, attributes) {
            scope.$watch(attributes.product);
        }

        // Return the isolate-scope directive configuration.
        return ({
            link: link,
            templateUrl: "app/hd/views/shopping-product-tile-cart.html" + appVersion
        });
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");
    app.directive("productTileFeatured", function () {
        function link(scope, element, attributes) {
            scope.$watch(attributes.product);
        }

        // Return the isolate-scope directive configuration.
        return ({
            link: link,
            templateUrl: "app/hd/views/shopping-product-tile-featured.html" + appVersion
        });
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");
    app.directive("retailProductTile", function () {
        function link(scope, element, attributes) {
            scope.$watch(attributes.product);
        }

        // Return the isolate-scope directive configuration.
        return ({
            link: link,
            templateUrl: "app/hd/views/retail-product-tile.html" + appVersion
        });
    });
}(angular.module("app-hd")));;
// adapted from http://ngmodules.org/modules/ngScrollTo

(function () {
    var app = angular.module("app-hd");

    app.directive('scrollTo', ['ScrollTo', function (ScrollTo) {
        return {
            restrict: "AC",
            compile: function () {
                return function (scope, element, attr) {
                    element.bind("click", function (event) {
                        ScrollTo.idOrName(attr.scrollTo, attr.offset);
                    });
                };
            }
        };
    }])
    .service('ScrollTo', ['$window', 'ngScrollToOptions', function ($window, ngScrollToOptions) {
        this.idOrName = function (idOrName, offset, focus) {//find element with the given id or name and scroll to the first element it finds
            var document = $window.document;

            if (!idOrName) {//move to top if idOrName is not provided
                $window.scrollTo(0, 0);
            }

            if (focus === undefined) { //set default action to focus element
                focus = true;
            }

            //check if an element can be found with id attribute
            var el = document.getElementById(idOrName);
            if (!el) {//check if an element can be found with name attribute if there is no such id
                el = document.getElementsByName(idOrName);

                if (el && el.length)
                    el = el[0];
                else
                    el = null;
            }

            if (el) { //if an element is found, scroll to the element
                if (focus) {
                    el.focus();
                }

                ngScrollToOptions.handler(el, offset);
            }

            //otherwise, ignore
        }
    }])
    .provider("ngScrollToOptions", function () {
        this.options = {
            handler: function (el, offset) {
                if (offset) {
                    var top = $(el).offset().top - offset;
                    window.scrollTo(0, top);
                }
                else {
                    el.scrollIntoView();
                }
            }
        };
        this.$get = function () {
            return this.options;
        };
        this.extend = function (options) {
            this.options = angular.extend(this.options, options);
        };
    });
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");
    app.directive("spinner", [
        "$window", function ($window) {
            // Description:
            //  Creates a new Spinner and sets its options
            // Usage:
            //  <div data-spinner="vm.spinnerOptions"></div>
            var directive = {
                link: link,
                restrict: "A"
            };
            return directive;

            function link(scope, element, attrs) {
                scope.spinner = null;
                scope.$watch(attrs.spinner, function (options) {
                    if (scope.spinner) {
                        scope.spinner.stop();
                    }
                    scope.spinner = new $window.Spinner(options);
                    scope.spinner.spin(element[0]);
                }, true);
            }
        }
    ]);
}(angular.module("app-hd")));;
(function () {
    var app = angular.module('app-hd');
    app.directive("stickyNav", ['$window',
        function stickyNav($window) {
            function stickyNavLink(scope, element) {
                var cats = [];
                var w = angular.element($window),
                    size = element[0].clientHeight,
                    top = 0;

                function toggleStickyNav() {
                    var b2 = 0;
                    cats = [];
                    if (cats.length == 0) {
                        var elems = element.find(".shopping-category");
                        elems.each(function (inx) {
                            var self = elems[inx];
                            cats.push(self);
                        });
                        var titleHeight = 150;
                        for (var inx = 0; inx < cats.length; inx++) {
                            var elem = cats[inx];
                            var bcr2 = elem.getBoundingClientRect();
                            var nextTop = 0;
                            if (inx < cats.length - 1) {
                                var nelem = cats[inx + 1];
                                var lab = $('#current-category');
                                if ((!lab) && (lab.length != 0))
                                    titleHeight = lab[0].offsetTop + lab[0].offsetHeight;
                                var lastCategory = '';
                                nextTop = nelem.getBoundingClientRect().top - titleHeight;
                            }
                            var t = bcr2.top - titleHeight;
                            if (elem.firstElementChild) {
                                var name = elem.firstElementChild.outerText;
                                if ((t < 0) && nextTop > 0) {
                                    if (name != lastCategory) {
                                        $('#current-category').text(name);
                                        lastCategory = name;
                                    }
                                    break;
                                }
                            }
                        }
                        return;
                    }
                }
                scope.$watch(function () {
                    return element[0].getBoundingClientRect().top + $window.pageYOffset;
                }, function (newValue, oldValue) {
                    if (newValue !== oldValue && !element.hasClass('catFixed')) {
                        top = newValue;
                    }
                });

                w.bind('resize', function stickyNavResize() {
                    element.removeClass('catFixed');
                    top = element[0].getBoundingClientRect().top + $window.pageYOffset;
                    toggleStickyNav();
                });
                w.bind('scroll', toggleStickyNav);
            }

            return {
                scope: {},
                restrict: 'A',
                link: stickyNavLink
            };
        }]);
}(angular.module("app-hd")));;
(function () {
    var app = angular.module("app-hd");

    app.directive("uiMask",
		function () {
		    var maskDefinitions = {
		        '9': /\d/,
		        'A': /[a-zA-Z]/,
		        '*': /[a-zA-Z0-9]/
		    };
		    return {
		        priority: 100,
		        require: "ngModel",
		        restrict: "A",
		        link: function (scope, iElement, iAttrs, controller) {
		            var maskProcessed = false,
						eventsBound = false,
						maskCaretMap,
						maskPatterns,
						maskPlaceholder,
						maskComponents,
						validValue,
						// Minimum required length of the value to be considered valid
						minRequiredLength,
						value,
						valueMasked,
						isValid,
						// Vars for initializing/uninitialized
						originalPlaceholder = iAttrs.placeholder,
						originalMaxlength = iAttrs.maxlength,
						// Vars used exclusively in eventHandler()
						oldValue,
						oldValueUnmasked,
						oldCaretPosition,
						oldSelectionLength;

		            function initialize(maskAttr) {
		                if (!angular.isDefined(maskAttr)) {
		                    return uninitialize();
		                }
		                processRawMask(maskAttr);
		                if (!maskProcessed) {
		                    return uninitialize();
		                }
		                initializeElement();
		                bindEventListeners();
		            }

		            function formatter(fromModelValue) {
		                if (!maskProcessed) {
		                    return fromModelValue;
		                }
		                value = unmaskValue(fromModelValue || "");
		                isValid = validateValue(value);
		                controller.$setValidity("mask", isValid);

		                if (isValid) validValue = value;
		                //console.log('formatter valid:'+validValue);
		                return isValid && value.length ? maskValue(value) : undefined;
		            }

		            function parser(fromViewValue) {
		                if (!maskProcessed) {
		                    return fromViewValue;
		                }
		                value = unmaskValue(fromViewValue || "");
		                isValid = validateValue(value);
		                viewValue = value.length ? maskValue(value) : "";
		                // We have to set viewValue manually as the reformatting of the input
		                // value performed by eventHandler() doesn't happen until after
		                // this parser is called, which causes what the user sees in the input
		                // to be out-of-sync with what the controller's $viewValue is set to.
		                controller.$viewValue = viewValue;
		                controller.$setValidity("mask", isValid);
		                if (value === "" && controller.$error.required !== undefined) {
		                    controller.$setValidity("required", false);
		                }
		                if (isValid) validValue = value;
		                //console.log('parser valid:'+validValue);
		                return isValid ? value : undefined;
		            }

		            iAttrs.$observe("uiMask", initialize);
		            controller.$formatters.push(formatter);
		            controller.$parsers.push(parser);

		            function uninitialize() {
		                maskProcessed = false;
		                unbindEventListeners();

		                if (angular.isDefined(originalPlaceholder)) {
		                    iElement.attr("placeholder", originalPlaceholder);
		                } else {
		                    iElement.removeAttr("placeholder");
		                }

		                if (angular.isDefined(originalMaxlength)) {
		                    iElement.attr("maxlength", originalMaxlength);
		                } else {
		                    iElement.removeAttr("maxlength");
		                }

		                iElement.val(controller.$modelValue);
		                controller.$viewValue = controller.$modelValue;
		                return false;
		            }

		            function initializeElement() {
		                value = oldValueUnmasked = unmaskValue(controller.$modelValue || "");
		                valueMasked = oldValue = maskValue(value);
		                isValid = validateValue(value);
		                viewValue = isValid && value.length ? valueMasked : "";
		                if (iAttrs.maxlength) { // Double maxlength to allow pasting new val at end of mask
		                    iElement.attr("maxlength", maskCaretMap[maskCaretMap.length - 1] * 2);
		                }
		                iElement.attr("placeholder", maskPlaceholder);
		                iElement.val(viewValue);
		                controller.$viewValue = viewValue;
		                // Not using $setViewValue so we don't clobber the model value and dirty the form
		                // without any kind of user interaction.
		            }

		            function bindEventListeners() {
		                if (eventsBound) {
		                    return true;
		                }
		                iElement.bind("blur", blurHandler);
		                iElement.bind("mousedown mouseup", mouseDownUpHandler);
		                iElement.bind("input keyup click", eventHandler);
		                eventsBound = true;
		            }

		            function unbindEventListeners() {
		                if (!eventsBound) {
		                    return true;
		                }
		                iElement.unbind("blur", blurHandler);
		                iElement.unbind("mousedown", mouseDownUpHandler);
		                iElement.unbind("mouseup", mouseDownUpHandler);
		                iElement.unbind("input", eventHandler);
		                iElement.unbind("keyup", eventHandler);
		                iElement.unbind("click", eventHandler);
		                eventsBound = false;
		            }

		            function validateValue(value) {
		                // Zero-length value validity is ngRequired's determination
		                return value.length ? value.length >= minRequiredLength : true;
		            }

		            function unmaskValue(value) {
		                var valueUnmasked = "",
							maskPatternsCopy = maskPatterns.slice();
		                // Preprocess by stripping mask components from value
		                value = value.toString();
		                angular.forEach(maskComponents, function (component, i) {
		                    value = value.replace(component, "");
		                });
		                angular.forEach(value.split(""), function (chr, i) {
		                    if (maskPatternsCopy.length && maskPatternsCopy[0].test(chr)) {
		                        valueUnmasked += chr;
		                        maskPatternsCopy.shift();
		                    }
		                });
		                return valueUnmasked;
		            }

		            function maskValue(unmaskedValue) {
		                var valueMasked = "",
							maskCaretMapCopy = maskCaretMap.slice();
		                angular.forEach(maskPlaceholder.split(""), function (chr, i) {
		                    if (unmaskedValue.length && i === maskCaretMapCopy[0]) {
		                        valueMasked += unmaskedValue.charAt(0) || "_";
		                        unmaskedValue = unmaskedValue.substr(1);
		                        maskCaretMapCopy.shift();
		                    } else {
		                        valueMasked += chr;
		                    }
		                });
		                return valueMasked;
		            }

		            function processRawMask(mask) {
		                var characterCount = 0;
		                maskCaretMap = [];
		                maskPatterns = [];
		                maskPlaceholder = "";

		                // No complex mask support for now...
		                // if (mask instanceof Array) {
		                //   angular.forEach(mask, function(item, i) {
		                //     if (item instanceof RegExp) {
		                //       maskCaretMap.push(characterCount++);
		                //       maskPlaceholder += '_';
		                //       maskPatterns.push(item);
		                //     }
		                //     else if (typeof item == 'string') {
		                //       angular.forEach(item.split(''), function(chr, i) {
		                //         maskPlaceholder += chr;
		                //         characterCount++;
		                //       });
		                //     }
		                //   });
		                // }
		                // Otherwise it's a simple mask
		                // else

		                if (typeof mask === "string") {
		                    minRequiredLength = 0;
		                    var isOptional = false;

		                    angular.forEach(mask.split(""), function (chr, i) {
		                        if (maskDefinitions[chr]) {
		                            maskCaretMap.push(characterCount);
		                            maskPlaceholder += "_";
		                            maskPatterns.push(maskDefinitions[chr]);

		                            characterCount++;
		                            if (!isOptional) {
		                                minRequiredLength++;
		                            }
		                        } else if (chr === "?") {
		                            isOptional = true;
		                        } else {
		                            maskPlaceholder += chr;
		                            characterCount++;
		                        }
		                    });
		                }
		                // Caret position immediately following last position is valid.
		                maskCaretMap.push(maskCaretMap.slice().pop() + 1);
		                // Generate array of mask components that will be stripped from a masked value
		                // before processing to prevent mask components from being added to the unmasked value.
		                // E.g., a mask pattern of '+7 9999' won't have the 7 bleed into the unmasked value.
		                // If a maskable char is followed by a mask char and has a mask
		                // char behind it, we'll split it into it's own component so if
		                // a user is aggressively deleting in the input and a char ahead
		                // of the maskable char gets deleted, we'll still be able to strip
		                // it in the unmaskValue() preprocessing.
		                maskComponents = maskPlaceholder.replace(/[_]+/g, "_").replace(/([^_]+)([a-zA-Z0-9])([^_])/g, "$1$2_$3").split("_");
		                maskProcessed = maskCaretMap.length > 1 ? true : false;
		            }

		            function blurHandler(e) {
		                oldCaretPosition = 0;
		                oldSelectionLength = 0;
		                if (!isValid || value.length === 0) {
		                    valueMasked = "";
		                    iElement.val("");
		                    scope.$apply(function () {
		                        controller.$setViewValue("");
		                    });
		                }
		            }

		            function mouseDownUpHandler(e) {
		                if (e.type === "mousedown") {
		                    iElement.bind("mouseout", mouseoutHandler);
		                } else {
		                    iElement.unbind("mouseout", mouseoutHandler);
		                }
		            }

		            iElement.bind("mousedown mouseup", mouseDownUpHandler);

		            function mouseoutHandler(e) {
		                oldSelectionLength = getSelectionLength(this);
		                iElement.unbind("mouseout", mouseoutHandler);
		            }

		            function eventHandler(e) {
		                e = e || {};
		                // Allows more efficient minification
		                var eventWhich = e.which,
							eventType = e.type;
		                // Prevent shift and ctrl from mucking with old values
		                if (eventWhich === 16 || eventWhich === 91) {
		                    return true;
		                }

		                var val = iElement.val(),
							valOld = oldValue,
							valMasked,
							valUnmasked = unmaskValue(val),
							valUnmaskedOld = oldValueUnmasked,
							valAltered = false,

							caretPos = getCaretPosition(this) || 0,
							caretPosOld = oldCaretPosition || 0,
							caretPosDelta = caretPos - caretPosOld,
							caretPosMin = maskCaretMap[0],
							caretPosMax = maskCaretMap[valUnmasked.length] || maskCaretMap.slice().shift(),

							selectionLen = getSelectionLength(this),
							selectionLenOld = oldSelectionLength || 0,
							isSelected = selectionLen > 0,
							wasSelected = selectionLenOld > 0,

							// Case: Typing a character to overwrite a selection
							isAddition = (val.length > valOld.length) || (selectionLenOld && val.length > valOld.length - selectionLenOld),
							// Case: Delete and backspace behave identically on a selection
							isDeletion = (val.length < valOld.length) || (selectionLenOld && val.length === valOld.length - selectionLenOld),
							isSelection = (eventWhich >= 37 && eventWhich <= 40) && e.shiftKey, // Arrow key codes

							isKeyLeftArrow = eventWhich === 37,
							// Necessary due to "input" event not providing a key code
							isKeyBackspace = eventWhich === 8 || (eventType !== "keyup" && isDeletion && (caretPosDelta === -1)),
							isKeyDelete = eventWhich === 46 || (eventType !== "keyup" && isDeletion && (caretPosDelta === 0) && !wasSelected),

							// Handles cases where caret is moved and placed in front of invalid maskCaretMap position. Logic below
							// ensures that, on click or leftward caret placement, caret is moved leftward until directly right of
							// non-mask character. Also applied to click since users are (arguably) more likely to backspace
							// a character when clicking within a filled input.
							caretBumpBack = (isKeyLeftArrow || isKeyBackspace || eventType === "click") && caretPos > caretPosMin;

		                oldSelectionLength = selectionLen;

		                // These events don't require any action
		                if (isSelection || (isSelected && (eventType === "click" || eventType === "keyup"))) {
		                    return true;
		                }

		                // Value Handling
		                // ==============

		                // User attempted to delete but raw value was unaffected--correct this grievous offense

		                if ((eventType === "input") && isDeletion && !wasSelected && valUnmasked === valUnmaskedOld) {
		                    // console.log("Value HandlingAAAAAAAAAAAAAAAAAAAA!!!!");
		                    while (isKeyBackspace && caretPos > caretPosMin && !isValidCaretPosition(caretPos)) {
		                        caretPos--;
		                    }
		                    while (isKeyDelete && caretPos < caretPosMax && maskCaretMap.indexOf(caretPos) === -1) {
		                        caretPos++;
		                    }
		                    var charIndex = maskCaretMap.indexOf(caretPos);
		                    // Strip out non-mask character that user would have deleted if mask hadn't been in the way.
		                    valUnmasked = valUnmasked.substring(0, charIndex) + valUnmasked.substring(charIndex + 1);
		                    valAltered = true;
		                }

		                // Update values
		                valMasked = maskValue(valUnmasked);
		                oldValue = valMasked;
		                oldValueUnmasked = valUnmasked;
		                iElement.val(valMasked);
		                if (valAltered) {
		                    // We've altered the raw value after it's been $digest'ed, we need to $apply the new value.
		                    scope.$apply(function () {
		                        controller.$setViewValue(valUnmasked);
		                    });
		                }
		                // Caret Repositioning
		                // ===================

		                // Ensure that typing always places caret ahead of typed character in cases where the first char of
		                // the input is a mask char and the caret is placed at the 0 position.
		                if (isAddition && (caretPos <= caretPosMin)) {
		                    caretPos = caretPosMin + 1;
		                }

		                if (caretBumpBack) {
		                    caretPos--;
		                }

		                // Make sure caret is within min and max position limits
		                caretPos = caretPos > caretPosMax ? caretPosMax : caretPos < caretPosMin ? caretPosMin : caretPos;

		                // Scoot the caret back or forth until it's in a non-mask position and within min/max position limits
		                while (!isValidCaretPosition(caretPos) && caretPos > caretPosMin && caretPos < caretPosMax) {
		                    caretPos += caretBumpBack ? -1 : 1;
		                }

		                if ((caretBumpBack && caretPos < caretPosMax) || (isAddition && !isValidCaretPosition(caretPosOld))) {
		                    caretPos++;
		                }
		                oldCaretPosition = caretPos;
		                setCaretPosition(this, caretPos);
		            }

		            function isValidCaretPosition(pos) {
		                return maskCaretMap.indexOf(pos) > -1;
		            }

		            function getCaretPosition(input) {
		                if (input.selectionStart !== undefined) {
		                    return input.selectionStart;
		                } else if (document.selection) {
		                    // Curse you IE
		                    input.focus();
		                    var selection = document.selection.createRange();
		                    selection.moveStart("character", -input.value.length);
		                    return selection.text.length;
		                }
		            }

		            function setCaretPosition(input, pos) {
		                if (input.offsetWidth === 0 || input.offsetHeight === 0) {
		                    return true; // Input's hidden
		                }
		                if (input.setSelectionRange) {
		                    input.focus();
		                    input.setSelectionRange(pos, pos);
		                } else if (input.createTextRange) {
		                    // Curse you IE
		                    var range = input.createTextRange();
		                    range.collapse(true);
		                    range.moveEnd("character", pos);
		                    range.moveStart("character", pos);
		                    range.select();
		                }
		            }

		            function getSelectionLength(input) {
		                if (input.selectionStart !== undefined) {
		                    return (input.selectionEnd - input.selectionStart);
		                }
		                if (document.selection) {
		                    return (document.selection.createRange().text.length);
		                }
		            }

		            // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf
		            if (!Array.prototype.indexOf) {
		                Array.prototype.indexOf = function (searchElement /*, fromIndex */) {
		                    "use strict";
		                    if (this === null) {
		                        throw new TypeError();
		                    }
		                    var t = Object(this);
		                    var len = t.length >>> 0;
		                    if (len === 0) {
		                        return -1;
		                    }
		                    var n = 0;
		                    if (arguments.length > 1) {
		                        n = Number(arguments[1]);
		                        if (n !== n) { // shortcut for verifying if it's NaN
		                            n = 0;
		                        } else if (n !== 0 && n !== Infinity && n !== -Infinity) {
		                            n = (n > 0 || -1) * Math.floor(Math.abs(n));
		                        }
		                    }
		                    if (n >= len) {
		                        return -1;
		                    }
		                    var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
		                    for (; k < len; k++) {
		                        if (k in t && t[k] === searchElement) {
		                            return k;
		                        }
		                    }
		                    return -1;
		                };
		            }
		        }
		    };
		}
	);
}(angular.module("app-hd")));;
/**
 * Filters out all duplicate items from an array by checking the specified key
 * @param [key] {string} the name of the attribute of each object to compare for uniqueness
 if the key is empty, the entire object will be compared
 if the key === false then no filtering will be performed
 * @return {array}
 */
var app = angular.module("app-hd");

app.filter('unique', function () {

    return function (items, filterOn) {

        if (filterOn === false) {
            return items;
        }

        if ((filterOn || angular.isUndefined(filterOn)) && angular.isArray(items)) {
            var hashCheck = {}, newItems = [];

            var extractValueToCompare = function (item) {
                if (angular.isObject(item) && angular.isString(filterOn)) {
                    return item[filterOn];
                } else {
                    return item;
                }
            };

            angular.forEach(items, function (item) {
                var valueToCheck, isDuplicate = false;

                for (var i = 0; i < newItems.length; i++) {
                    if (angular.equals(extractValueToCompare(newItems[i]), extractValueToCompare(item))) {
                        isDuplicate = true;
                        break;
                    }
                }
                if (!isDuplicate) {
                    newItems.push(item);
                }

            });
            items = newItems;
        }
        return items;
    };
});;
(function () {
    'use strict';
    var serviceId = "authInterceptorService";
    angular.module("app-hd").factory(serviceId, ['$q', '$injector', '$cookies', 'localStorageService', authInterceptorService]);

    function authInterceptorService($q, $injector, $cookies, localStorageService) {

        var authInterceptorServiceFactory = {};
        var $http;
        var $state;
        var authService;

        var _request = function (config) {
            var deferred = $q.defer();
            _checkToken().then(function () {
                config.headers = config.headers || {};

                var authData = $cookies.getObject('authorizationData');
                if (authData) {
                    config.headers.Authorization = 'Bearer ' + authData.token;
                }
                deferred.resolve(config);
            }, function () {
                deferred.reject(config);
            });

            return deferred.promise;
        }

        var _responseError = function (rejection) {
            if (rejection.status === 401) {
                var authService = $injector.get('authService');

                if (authService.authentication.isAuth) {
                    var deferred = $q.defer();
                    _retryHttpRequest(rejection.config, deferred);
                    return deferred.promise;
                }

                authService.logOut();
            }
            return $q.reject(rejection);
        }

        var _retryHttpRequest = function (config, deferred) {
            $http = $http || $injector.get('$http');
            $http(config).then(function (response) {
                deferred.resolve(response);
            }, function (response) {
                deferred.reject(response);
            });
        }

        function _checkToken() {
            var deferred = $q.defer();
            authService = authService || $injector.get('authService');
            if (authService.authentication.isAuth) {
                var secondsToSlide = 900;
                var secondsToExpire = 1800;

                var td = authService.authentication.tokenDate;

                var marker = moment(td);
                var slideAt = moment().add(-secondsToSlide, 'seconds');
                var expireAt = moment().add(-secondsToExpire, 'seconds');

                var refresh = td != null && marker < slideAt && marker > expireAt;
                var expire = td != null && marker <= expireAt;

                if (refresh) {
                    authService.refreshToken().then(function () {
                        deferred.resolve();
                    }, function () {
                        _logout();
                        deferred.reject();
                    });
                }
                else if (expire) {
                    _logout();
                    deferred.reject();
                } else {
                    deferred.resolve();
                }
            } else {
                deferred.resolve();
            }
            return deferred.promise;
        }

        function _logout() {
            authService = authService || $injector.get('authService');
            authService.logOut();
            $state = $state || $injector.get('$state');
            $state.go('sign-in');
        }

        authInterceptorServiceFactory.request = _request;
        authInterceptorServiceFactory.responseError = _responseError;

        return authInterceptorServiceFactory;
    }
})();;
(function () {
    "use strict";

    var serviceId = "authService";

    angular.module("app-hd").
        factory(serviceId, ['$http', '$injector', '$q', '$cookies', 'localStorageService', 'ngAuthSettings', '$window',authService]);
    function authService($http, $injector, $q, $cookies, localStorageService, ngAuthSettings, $window) {
        var serviceBase = ngAuthSettings.apiServiceBaseUri;
        var authServiceFactory = {};

        var _authentication = {
            isAuth: false,
            userName: "",
            userId: "",
            useRefreshTokens: false,
            convertedUser: false,
            tokenDate: null
        };

        var _externalAuthData = {
            provider: "",
            userName: "",
            userId: "",
            externalAccessToken: ""
        };

        var _saveRegistration = function (registration) {
            var deferred = $q.defer();
            _logOut();

            $http.post('api/account/register', registration)
                .success(function (response) {
                    deferred.resolve(response);
                })
                .error(function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        };

        var _resetUser = function (registration) {
            var deferred = $q.defer();
            _logOut();

            $http.post('api/account/resetUser', registration)
                .success(function (response) {
                    deferred.resolve(response);
                })
                .error(function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        };

        var _changePassword = function (passwordData) {
            var deferred = $q.defer();
            $http.post("api/account/ChangePassword", passwordData)
                .success(function (response) {
                    deferred.resolve(response);
                })
                .error(function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }

        var _setPassword = function (passwordData) {
            var deferred = $q.defer();
            $http.post("api/Account/SetPassword", passwordData)
                .success(function (response) {
                    deferred.resolve(response);
                })
                .error(function (err, status) {
                    deferred.reject(err);
                });

            return deferred.promise;
        }

        var _login = function (loginData) {
            var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;

            if (loginData.useRefreshTokens) {
                data = data + "&client_id=" + ngAuthSettings.clientId;
            }

            var deferred = $q.defer();

            $http.post('authorization/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
                .success(function (response) {

                    if (!isObject(response)) {
                        _logOut();
                        var reason = { errorMessage: "A problem occurred retrieving your account information. Please try again." };
                        deferred.reject(reason);
                        return;
                    }

                    var expireDateTime = new Date(response[".expires"]);

                    $cookies.putObject('authorizationData',
                        {
                            token: response.access_token
                            , userName: loginData.userName
                            , refreshToken: response.refresh_token
                            , useRefreshTokens: true
                            , tokenDate: new Date()
                        }, { expires: expireDateTime });

                    _authentication.isAuth = true;
                    _authentication.userName = loginData.userName;
                    _authentication.useRefreshTokens = loginData.useRefreshTokens;
                    _authentication.convertedUser = response.convertedUse == 'true';
                    _authentication.tokenDate = new Date();

                    deferred.resolve(response);
                }).error(function (err, status) {
                    _logOut();
                    deferred.reject(err);
                });

            return deferred.promise;
        };

        var _logOut = function () {
            $cookies.remove('authorizationData');
            $window.dispatchEvent(new CustomEvent("customerLoggedOut", { detail: { customerNumber: null } }));

            _authentication.isAuth = false;
            _authentication.userName = "";
            _authentication.tokenDate = null;

            var dc = $injector.get('datacontext');

        };

        var isObject = function (str) {
            return typeof str === 'object';
        }

        var _fillAuthData = function () {
            var authData = $cookies.getObject('authorizationData');
            if (authData) {

                if (!authData.useRefreshTokens || authData.tokenDate == null) {
                    _logOut();
                }

                _authentication.isAuth = true;
                _authentication.userName = authData.userName;
                _authentication.useRefreshTokens = authData.useRefreshTokens;
                _authentication.tokenDate = authData.tokenDate;
            }
        };

        var _refreshToken = function () {
            var deferred = $q.defer();

            var authData = $cookies.getObject('authorizationData');

            if (authData) {
                var data = "grant_type=refresh_token&refresh_token=" + authData.refreshToken + "&client_id=" + ngAuthSettings.clientId;
                $cookies.remove('authorizationData');

                _authentication.tokenDate = null;

                $http.post('authorization/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
                    .success(function (response) {

                        var expireDateTime = new Date(response[".expires"]);

                        $cookies.putObject('authorizationData',
                            {
                                token: response.access_token
                                , userName: response.userName
                                , refreshToken: response.refresh_token
                                , useRefreshTokens: true
                                , tokenDate: new Date()
                            }, { expires: expireDateTime });

                        _authentication.tokenDate = new Date();

                        deferred.resolve(response);
                    }).error(function (err, status) {
                        _logOut();
                        deferred.reject(err);
                    });
            }

            return deferred.promise;
        };

        var _obtainAccessToken = function (externalData) {
            var deferred = $q.defer();

            $http.get('api/account/ObtainLocalAccessToken', { params: { provider: externalData.provider, externalAccessToken: externalData.externalAccessToken } }).success(function (response) {
                $cookies.putObject('authorizationData', { token: response.access_token, userName: response.userName, refreshToken: "", useRefreshTokens: false });

                _authentication.isAuth = true;
                _authentication.userName = response.userName;
                _authentication.useRefreshTokens = false;
                _authentication.tokenDate = new Date();

                deferred.resolve(response);
            }).error(function (err, status) {
                _logOut();
                deferred.reject(err);
            });

            return deferred.promise;
        };

        var _registerExternal = function (registerExternalData) {
            var deferred = $q.defer();

            $http.post('api/account/registerexternal', registerExternalData).success(function (response) {
                $cookies.putObject('authorizationData', { token: response.access_token, userName: response.userName, refreshToken: "", useRefreshTokens: false });

                _authentication.isAuth = true;
                _authentication.userName = response.userName;
                _authentication.useRefreshTokens = false;

                deferred.resolve(response);
            }).error(function (err, status) {
                _logOut();
                deferred.reject(err);
            });

            return deferred.promise;
        };

        authServiceFactory.saveRegistration = _saveRegistration;
        authServiceFactory.resetUser = _resetUser;
        authServiceFactory.login = _login;
        authServiceFactory.logOut = _logOut;
        authServiceFactory.fillAuthData = _fillAuthData;
        authServiceFactory.changePassword = _changePassword;
        authServiceFactory.setPassword = _setPassword;
        authServiceFactory.authentication = _authentication;
        authServiceFactory.refreshToken = _refreshToken;

        authServiceFactory.obtainAccessToken = _obtainAccessToken;
        authServiceFactory.externalAuthData = _externalAuthData;
        authServiceFactory.registerExternal = _registerExternal;

        return authServiceFactory;
    }
})();;
(function() {
    "use strict";
    angular.module("app-hd").factory("customFetch", ["$cookies", service]);

    function service($cookies) {
        /**
         * Fetch wrapper that adds authorization header and application/json content type header
         * @param {RequestInfo | URL} url
         * @param {RequestInit} [options]
         * @return {Promise<Response>}
         */
        function customFetch(url, options) {
            const defaultHeaders = {
                "Content-Type": "application/json"
            };

            const authorizationData = $cookies.getObject("authorizationData");
            if (authorizationData) {
                defaultHeaders.Authorization = `Bearer ${authorizationData.token}`;
            }

            const headers = options && options.headers ? {...defaultHeaders, ...options.headers} : defaultHeaders;
            const fetchOptions = {...options, headers};

            return fetch(url, fetchOptions);
        }

        return customFetch;
    }
})();
;
(function () {
    "use strict";

    var serviceId = "datacontext";
    angular.module("app-hd").factory(serviceId, ["$http", "$q","$cookies", "repositories", "authService", "$window",
        "unauthenticatedBranch", datacontext]);

    function datacontext($http, $q, $cookies, repositories, authService, $window, unauthenticatedBranch) {
        var primePromise;

        this.primeCustomerPromise;
        this.isNewCustomer = false;
        this.isReturning = false;

        //
        //  all repositories that are on demand requested need to be included in array below
        //
        var repoNames = ["cust", "order", "products", "category", "promo_banners", "promotion", "productcategory", "store", "customer_source", "subscription"];

        var currentCategory = "notset";
        var _isInit = false; // has this data context been created before

        var currentInstanceIds = {
            branchNumber: -999,
            priceSchedule: -999
        }

        var service = {
            currentCategory: currentCategory,
            isReady: isReady,
            primeProducts: primeProducts,
            primePromise: undefined,
            primeCustomer: primeCustomer,
            reset: reset,
            refreshOrderInfo: refreshOrderInfo, 
            primeCustomerPromise: this.primeCustomerPromise,
            isNewCustomer: this.isNewCustomer,
            isReturning: this.isReturning,
            lastTotal: 0,
            isTableUptoDatePromise: undefined,

            lastUpdateStatsPromise: undefined,
            tableCachePromises: {},
            resetAllData: resetAllData,
            currentInstanceIds: currentInstanceIds,
            hideOneTimeDeliveryDiscountModal: false
        };

        init();
        function init() {
            repositories.init();
            defineLazyLoadedRepos();
        }

        function reset() {
            service.order.ResetOrderItems();
        }
        function refreshOrderInfo() {
            return service.order.reloadOrder();
        }

        function resetAllData() {
            service.primeCustomerPromise = undefined;
            service.primePromise = undefined;

            $cookies.remove("PromoCookie");
            //service.lastUpdateStatsPromise = undefined;
            $q.all([
                service.cust.reset(),
                service.category.reset(),
                service.products.reset()
            ]).then(function () {
            });
        }

        function primeCustomer() {
            var self = this;
            if (service.primeCustomerPromise) return service.primeCustomerPromise.promise;

            service.primeCustomerPromise = $q.defer();

            var isAuth = authService.authentication.isAuth;

            service.cust.getCustomerWithOrder(isAuth).then(
                function (data) {
                    currentInstanceIds.branchNumber = service.cust.mycust.branch;
                    currentInstanceIds.priceSchedule = service.cust.mycust.price_schedule;

                    $cookies.put("customerId", service.cust.mycust.id);
                    //emit event with cust number, listen to event in chat.js and reload chat if cust number changes
                    $window.dispatchEvent(new CustomEvent("customerPrimed", { detail: { customerNumber: service.cust.mycust.customerNumber, customerId: service.cust.mycust.id, name: service.cust.mycust.name  } }));

                    if (service.primeCustomerPromise)
                        service.primeCustomerPromise.resolve(data);
                }, function (err) {
                    err.errorMessage = "We're sorry. Our system did not respond. Please click the Log In button again. If you are not able to log in please contact customer service at 866-623-7934.";
                    service.primeCustomerPromise.reject(err);
                });
            return service.primeCustomerPromise.promise;
        }

        function primeProducts(forcerefresh) {
            var self = this;
            if (!forcerefresh) {
                if (service.primePromise) return service.primePromise.promise;
            }
            var promise = service.primePromise = $q.defer();

            service.primeCustomer().then(
                function (data) {
                    loadProductData(data);
                });
            return service.primePromise.promise;

            function loadProductData(data) {
                // this is called after the customer is obtained
                // if the user is not logged in the default user
                //  has been obtained

                //if ((service.category.isLoaded && service.products.isLoaded)
                //       && (
                //               service.cust.mycust.branch == self.currentInstanceIds.branchNumber
                //            && service.currentInstanceIds.priceSchedule == service.cust.mycust.price_schedule))
                //    service.primePromise.resolve();
                //else

                var branch = service.cust.mycust.branch;
                var priceSchedule = service.cust.mycust.price_schedule;
                if (!authService.authentication.isAuth && unauthenticatedBranch.state.selectedLocationBranch) {
                    branch = unauthenticatedBranch.state.selectedLocationBranch.branchNumber;
                    priceSchedule = unauthenticatedBranch.state.selectedLocationBranch.priceSchedule;
                }
                $q.all([
                    service.category.getCatTree(branch, true),
                    service.products.getProductPartialsForPriceCode(priceSchedule, service.cust.mycust.nextDeliveryDate, branch),
                    service.products.loadProductAttributes(),
                ]).then(extendMetadata);
            }

            function extendMetadata(data1, data2) {
                //  this is where the exclusion list must be processed

                var itms = service.products.entityItems;
                if ((service.cust.mycust) && (service.cust.mycust.order)) {
                    service.order.processOrderUpdateFromServer(service.cust.mycust.order);
                }

                // next update the products with out of stock information
                if (service.cust.mycust) {
                    var oosProdids = service.cust.mycust.outOfStockProdIds;
                    angular.forEach(oosProdids, function (item, key) {
                        if (itms[item]) {
                            itms[item].outOfStock = true;
                        }
                    });
                }
                service.products.getProductDetails().then(function () { promise.resolve(); });
                service.products.pairProductAttributes();
            }
        }

        return service;

        function defineLazyLoadedRepos() {
            repoNames.forEach(function (name) {
                Object.defineProperty(service, name, {
                    configurable: true,
                    get: function () {
                        //
                        // the 1st time the repois request via this prop
                        //  we ask the repositories for it  will be injected
                        //
                        //
                        var repo = repositories.getRepo(name);
                        Object.defineProperty(service, name, {
                            value: repo,
                            configurable: false,
                            enumerable: true
                        });
                        return repo;
                    }
                });
            });
        }

        function isReady() {
            return _isInit;
        }
    }
})();
;
(function () {
    "use strict";

    var serviceId = "deliveryFeedback";
    angular.module("app-hd").factory(serviceId, ["$http", "$q", "$cookies", "repositories", "authService", deliveryFeedback]);

    function deliveryFeedback($http, $q) {

        deliveryFeedback = {}
        var self = this;
        function submitFeedback(data) {
            var defer = $q.defer();
            $http.post('api/UserFeedback/UploadDeliveryFeedback', data).then(function (response) {
                console.log(response)
                if (response.status == 200) {
                    document.getElementById("thank-you").style.display = "block"
                    document.getElementById("form").style.display = "none"
                } else {
                    document.getElementById("error-submit").style.display = "block"
                }
                
            })
            return defer.promise;
        }

        deliveryFeedback.submitFeedback = submitFeedback;

        return deliveryFeedback
    }

})();;
(function() {
    var app = angular.module("app-hd");

    app.directive("conchange", function ($window) {
        return function (scope, element) {
            var w = angular.element($window);
            scope.getWindowStatus = function () {
                return {
                    status: navigator.onLine ? "online" : "offline"

                    //'h': w.height(),
                    // 'w': w.width()
                };
            };
            scope.$watch(scope.getWindowStatus, function (newValue, oldValue) {
                scope.status = newValue.status;
            }, true);

            w.bind("conchange", function () {
                scope.$apply();
            });
        };
    });

    app.directive("oberdatepicker", function () {
        return {
            restrict: "A",
            require: "ngModel",
            transclude: true,
            link: function (scope, elem, attrs, ngModelCtrl) {
                var firstDate = scope.$parent.vm.firstSuspendDate;
                var CurrentDate = new Date();

                function availableDay(date) {
                    var dd = firstDate;
                    var ddate = Date.parse(scope.$parent.vm.DeliveryDate);
                    var validDayofWeek = moment(ddate).format("d");

                    var dayofWeekBeingChecked = moment(date).format("d");

                    if (moment(date.toDateString()).isBefore(moment(CurrentDate.toDateString()).add(1, 'days')))
                        return [false, ""];

                    if (isHoliday(date)) {
                        return [false, ""];
                    }

                    if (validDayofWeek == dayofWeekBeingChecked) {
                        if (scope.$parent.vm.EOW != 0) {
                            var even = moment(date.toDateString()).week() % 2 == 0;
                            return [(scope.$parent.vm.EOW == 1 && even) || (scope.$parent.vm.EOW == 2 && !even), ""];
                        }
                        return [true, ""];
                    } else {
                        return [false, ""];
                    }
                }

                //	//Determine if date is a Holiday
                var isHoliday = function (date) {
                    // Christmas is 12/25 every year

                    if (date.getMonth() == 6 && date.getDate() == 4) {
                        return true;
                    }
                    if (date.getMonth() == 11 && date.getDate() == 25) {
                        return true;
                    }

                    // Thanksgiving is the 4th Thursday of November every year
                    if (date.getMonth() == 10) {
                        var nTh = 4; // Fourth
                        var nTargetDay = 4; // Thursday
                        var nTargetMonth = 10; // November
                        var nTargetYear = date.getFullYear();

                        var nEarliestDate = (1 + (7 * (nTh - 1)));

                        var dtEarliestDate = new Date(nTargetYear, nTargetMonth, nEarliestDate);
                        var nWeekday = dtEarliestDate.getDay();

                        var nOffset = 0;

                        if (nTargetDay == nWeekday) {
                            nOffset = 0;
                        } else {
                            if (nTargetDay < nWeekday) {
                                nOffset = nTargetDay + (7 - nWeekday);
                            } else {
                                nOffset = (nTargetDay + (7 - nWeekday)) - 7;
                            }
                        }

                        var dtHolidayDate = new Date(nTargetYear, nTargetMonth, nEarliestDate + nOffset);
                        if (+date == +dtHolidayDate) {
                            return true;
                        }
                    }

                    // Not a holiday
                    return false;
                };
                var updateModel = function (dateText) {
                    scope.$apply(function () {
                        ngModelCtrl.$setViewValue(dateText);
                    });
                };
                var options = {
                    dateFormat: "mm/dd/yy",
                    beforeShowDay: availableDay,
                    setDate: new Date(firstDate),
                    onSelect: function (dateText) {
                        updateModel(dateText);
                    }
                };
                elem.datepicker(options);
                /* if (!angular.isUndefined(scope.firstSuspendDate)) {
					 var fd = moment(new Date(firstDate)).format('L');
					 elem.datepicker("setDate", fd);
				 }*/
            }
        };
    });

    app.directive("resize", function ($window) {
        return function (scope, element) {
            var w = angular.element($window);
            scope.getWindowDimensions = function () {
                return {
                    'h': w.height(),
                    'w': w.width()
                };
            };
            scope.$watch(scope.getWindowDimensions, function (newValue, oldValue) {
                scope.windowHeight = newValue.h;
                scope.windowWidth = newValue.w;

                scope.style = function () {
                    return {
                        'height': (newValue.h - 100) + "px",
                        'width': (newValue.w - 100) + "px"
                    };
                };
            }, true);

            w.bind("resize", function () {
                scope.$apply();
            });
        };
    });

    app.directive("ccImgCategory", [
		"config", function (config) {
		    //Usage:
		    //<img data-cc-img-person="{{s.speaker.imageSource}}"/>
		    var basePath = config.imageCategory.basePath;
		    var noImage = config.imageCategory.noImage;
		    var directive = {
		        link: link,
		        restrict: "A"
		    };
		    return directive;

		    function link(scope, element, attrs) {
		        attrs.$observe("ccImgCategory", function (value) {
		            if (!value) {
		                attrs.removeAttr("src");
		            } else {
		                var prts = value.split("^");
		                if (prts[1] == "") {
		                    value = prts[0];
		                    value = basePath + value;
		                    attrs.$set("src", value);
		                } else {
		                    value = noImage;
		                    attrs.$set("style", "height:0px;width:0px;");
		                    attrs.$set("class", "hidden");
		                    attrs.$set("src", '');
		                }
		            }
		        });
		    }
		}
    ]);

    app.directive("ccSidebar", function () {
        // Opens and clsoes the sidebar menu.
        // Usage:
        //  <div data-cc-sidebar>
        // Creates:
        //  <div data-cc-sidebar class="sidebar">
        var directive = {
            link: link,
            restrict: "A"
        };
        return directive;

        function getNode(className, element) {
            var tempCliejnts = [];
            var kids = element.children;
            angular.forEach(kids, function (node) {
                angular.forEach(node.classList, function (tclass) {
                    if (tclass == className) {
                        tempCliejnts.push(node);
                    }
                });
            });
            return tempCliejnts[0];
        }

        function link(scope, element, attrs) {
            var $sidebarInner = getNode("zsidebar-inner", element[0]);
            //element.find('.sidebar-inner');
            var $dropdownElement = getNode("sidebar-dropdown", element[0]);
            $dropdownElement = $dropdownElement.children[0];

            element.addClass("sidebar");

            //$dropdownElement.click(dropdown);

            function dropdown(e) {
                var dropClass = "dropy";
                e.preventDefault();
                if (!$dropdownElement.hasClass(dropClass)) {
                    hideAllSidebars();
                    $sidebarInner.slideDown(350);
                    $dropdownElement.addClass(dropClass);
                } else if ($dropdownElement.hasClass(dropClass)) {
                    $dropdownElement.removeClass(dropClass);
                    $sidebarInner.slideUp(350);
                }

                function hideAllSidebars() {
                    $sidebarInner.slideUp(350);
                    $(".sidebar-dropdown a").removeClass(dropClass);
                }
            }
        }
    });

    app.directive("ccSidebar2", function () {
        // Opens and clsoes the sidebar menu.
        // Usage:
        //  <div data-cc-sidebar>
        // Creates:
        //  <div data-cc-sidebar class="sidebar">
        var directive = {
            link: link,
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            var $sidebarInner = element.find(".zsidebar-inner");
            var $dropdownElement = element.find(".sidebar-dropdown a");
            element.addClass("sidebar");
            $dropdownElement.click(dropdown);

            function dropdown(e) {
                var dropClass = "dropy";
                e.preventDefault();
                if (!$dropdownElement.hasClass(dropClass)) {
                    hideAllSidebars();
                    $sidebarInner.slideDown(350);
                    $dropdownElement.addClass(dropClass);
                } else if ($dropdownElement.hasClass(dropClass)) {
                    $dropdownElement.removeClass(dropClass);
                    $sidebarInner.slideUp(350);
                }

                function hideAllSidebars() {
                    $sidebarInner.slideUp(350);
                    $(".sidebar-dropdown a").removeClass(dropClass);
                }
            }
        }
    });

    app.directive("ccWidgetClose", function () {
        // Usage:
        // <a data-cc-widget-close></a>
        // Creates:
        // <a data-cc-widget-close="" href="#" class="wclose">
        //     <i class="fa fa-remove"></i>
        // </a>
        var directive = {
            link: link,
            template: "<i class=\"fa fa-remove\"></i>",
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            attrs.$set("href", "#");
            attrs.$set("wclose");
            element.click(close);

            function close(e) {
                e.preventDefault();
                element.parent().parent().parent().hide(100);
            }
        }
    });

    app.directive("ccWidgetMinimize", function () {
        // Usage:
        // <a data-cc-widget-minimize></a>
        // Creates:
        // <a data-cc-widget-minimize="" href="#"><i class="fa fa-chevron-up"></i></a>
        var directive = {
            link: link,
            template: "<i class=\"fa fa-chevron-up\"></i>",
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            //$('body').on('click', '.widget .wminimize', minimize);
            attrs.$set("href", "#");
            attrs.$set("wminimize");
            element.click(minimize);

            function minimize(e) {
                e.preventDefault();
                var $wcontent = element.parent().parent().next(".widget-content");
                var iElement = element.children("i");
                if ($wcontent.is(":visible")) {
                    iElement.removeClass("fa fa-chevron-up");
                    iElement.addClass("fa fa-chevron-down");
                } else {
                    iElement.removeClass("fa fa-chevron-down");
                    iElement.addClass("fa fa-chevron-up");
                }
                $wcontent.toggle(500);
            }
        }
    });

    app.directive("ccScrollToTop", [
		"$window",
		// Usage:
		// <span data-cc-scroll-to-top></span>
		// Creates:
		// <span data-cc-scroll-to-top="" class="totop">
		//      <a href="#"><i class="fa fa-chevron-up"></i></a>
		// </span>
		function ($window) {
		    var directive = {
		        link: link,
		        template: "<a href=\"#\"><i class=\"fa fa-chevron-up\"></i></a>",
		        restrict: "A"
		    };
		    return directive;

		    function link(scope, element, attrs) {
		        var $win = $($window);
		        element.addClass("totop");
		        $win.scroll(toggleIcon);

		        element.find("a").click(function (e) {
		            e.preventDefault();
		            // Learning Point: $anchorScroll works, but no animation
		            //$anchorScroll();
		            $("body").animate({ scrollTop: 0 }, 500);
		        });

		        function toggleIcon() {
		            $win.scrollTop() > 300 ? element.slideDown() : element.slideUp();
		        }
		    }
		}
    ]);

    app.directive("ccSpinner", [
		"$window", function ($window) {
		    // Description:
		    //  Creates a new Spinner and sets its options
		    // Usage:
		    //  <div data-cc-spinner="vm.spinnerOptions"></div>
		    var directive = {
		        link: link,
		        restrict: "A"
		    };
		    return directive;

		    function link(scope, element, attrs) {
		        scope.spinner = null;
		        scope.$watch(attrs.ccSpinner, function (options) {
		            if (scope.spinner) {
		                scope.spinner.stop();
		            }
		            scope.spinner = new $window.Spinner(options);
		            scope.spinner.spin(element[0]);
		        }, true);
		    }
		}
    ]);

    app.directive("ccCartWidgetHeader", function () {
        //Usage:
        //<div data-cc-widget-header title="vm.map.title"></div>
        var directive = {
            link: link,
            scope: {
                'title': "@",
                'subtitle': "@",
                'rightText': "@",
                'allowCollapse': "@"
            },
			templateUrl: "app/views/layout/cARTwidgetheader.html" + appVersion,
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            attrs.$set("class", "widget-head");
        }
    });

    app.directive("ccWidgetHeader", function () {
        //Usage:
        //<div data-cc-widget-header title="vm.map.title"></div>
        var directive = {
            link: link,
            scope: {
                'title': "@",
                'subtitle': "@",
                'rightText': "@",
                'allowCollapse': "@"
            },
			templateUrl: "app/views/layout/widgetheader.html" + appVersion,
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            attrs.$set("class", "widget-head");
        }
    });

    app.directive("oberWidgetHeader", function () {
        //Usage:
        //<div data-cc-widget-header title="vm.map.title"></div>
        var directive = {
            link: link,
            scope: {
                'title': "@",
                'subtitle': "@",
                'rightText': "@",
                'allowCollapse': "@"
            },
			templateUrl: "app/views/layout/catHeader.html" + appVersion,
            restrict: "A"
        };
        return directive;

        function link(scope, element, attrs) {
            attrs.$set("class", "oberwidget-head");
        }
    });

    app.directive("abnTree2", [
		"$timeout", function ($timeout) {
		    return {
		        restrict: "E",
		        template: "<ul id='thelist' class=\"nav nav-list nav-pills nav-stacked abn-tree\">\n "
					+ " <li ng-repeat=\"row in tree_rows | filter:{visible:true} track by row.branch.uid\" " +
					"ng-animate=\"'abn-tree-animate'\" ng-class=\"'level-' + {{ row.level }} + (row.branch.selected ? ' active':'') + "
					+ "' ' +row.classes.join(' ')\" class=\"abn-tree-row\">" +
					"<div  id='{{row.name}}   height: 50px;'  href=\"\#/products/{{row.name}}\"   ng-click=\"user_clicks_branch(row.branch) \">"
					+ "<img  data-cc-img-category='{{row.label}}.png^{{row.branch.parentName}}'  style='height:40px;width:40px;padding:5px;'  ng-click=\"row.branch.expanded = !row.branch.expanded\" class=\"indented tree-icon\"> " + "</img>"

					+ "<span    class=\"indented tree-label\"      ng-click=\"RowBranchExpander(row)\" >{{ row.label }} </span></div></li>\n</ul>",

		        replace: true,
		        //scope: {
		        //    treeData: '=',
		        //    onSelect: '&',
		        //    initialSelection: '@',
		        //    selectText: '=',
		        //    treeControl: '='
		        //},
		        link: function (scope, element, attrs) {
		            var error, expand_all_parents, expand_level, for_all_ancestors, for_each_branch, get_parent, n, on_treeData_change, select_branch, selected_branch, tree;
		            error = function (s) {
		                console.log("ERROR:" + s);
		                return void 0;
		            };
		            if (attrs.iconExpand == null) {
		                attrs.iconExpand = "icon-plus  glyphicon glyphicon-plus  fa fa-plus";
		            }
		            if (attrs.iconCollapse == null) {
		                attrs.iconCollapse = "icon-minus glyphicon glyphicon-minus fa fa-minus";
		            }
		            if (attrs.iconLeaf == null) {
		                attrs.iconLeaf = "icon-file  glyphicon glyphicon-file  fa fa-file";
		            }
		            if (attrs.expandLevel == null) {
		                attrs.expandLevel = "3";
		            }
		            expand_level = parseInt(attrs.expandLevel, 10);
		            if (!scope.treeData) {
		                alert("no treeData defined for the tree!");
		                return;
		            }
		            if (scope.treeData.length == null) {
		                if (treeData.label != null) {
		                    scope.treeData = [treeData];
		                } else {
		                    alert("treeData should be an array of root branches");
		                    return;
		                }
		            }
		            for_each_branch = function (f) {
		                var do_f, root_branch, _i, _len, _ref, _results;
		                do_f = function (branch, level) {
		                    var child, _i, _len, _ref, _results;
		                    f(branch, level);
		                    if (branch.children != null) {
		                        _ref = branch.children;
		                        _results = [];
		                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                            child = _ref[_i];
		                            _results.push(do_f(child, level + 1));
		                        }
		                        return _results;
		                    }
		                };
		                _ref = scope.treeData;
		                _results = [];
		                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                    root_branch = _ref[_i];
		                    _results.push(do_f(root_branch, 1));
		                }
		                return _results;
		            };
		            selected_branch = null;
		            select_branch = function (branch) {
		                if (!branch) {
		                    if (selected_branch != null) {
		                        selected_branch.selected = false;
		                    }
		                    selected_branch = null;
		                    return;
		                }
		                if (branch !== selected_branch) {
		                    if (selected_branch != null) {
		                        selected_branch.selected = false;
		                    }
		                    branch.selected = true;
		                    selected_branch = branch;
		                    expand_all_parents(branch);
		                    if (branch.onSelect != null) {
		                        return $timeout(function () {
		                            return branch.onSelect(branch);
		                        });
		                    } else {
		                        if (scope.onSelect != null) {
		                            return $timeout(function () {
		                                return scope.onSelect({
		                                    branch: branch
		                                });
		                            });
		                        }
		                    }
		                }
		            };
		            scope.user_clicks_branch = function (branch) {
		                if (branch !== selected_branch) {
		                    //vm.gotoProduct(branch.name);
		                    return select_branch(branch);
		                }
		            };
		            get_parent = function (child) {
		                var parent;
		                parent = void 0;
		                if (child.parent_uid) {
		                    for_each_branch(function (b) {
		                        if (b.uid === child.parent_uid) {
		                            return parent = b;
		                        }
		                    });
		                }
		                return parent;
		            };
		            for_all_ancestors = function (child, fn) {
		                var parent;
		                parent = get_parent(child);
		                if (parent != null) {
		                    fn(parent);
		                    return for_all_ancestors(parent, fn);
		                }
		            };
		            expand_all_parents = function (child) {
		                return for_all_ancestors(child, function (b) {
		                    return b.expanded = true;
		                });
		            };
		            scope.tree_rows = [];
		            on_treeData_change = function () {
		                var add_branch_to_list, root_branch, _i, _len, _ref, _results;
		                for_each_branch(function (b, level) {
		                    if (!b.uid) {
		                        return b.uid = "" + Math.random();
		                    }
		                });
		                console.log("UIDs are set.");
		                for_each_branch(function (b) {
		                    var child, _i, _len, _ref, _results;
		                    if (angular.isArray(b.children)) {
		                        _ref = b.children;
		                        _results = [];
		                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                            child = _ref[_i];
		                            _results.push(child.parent_uid = b.uid);
		                        }
		                        return _results;
		                    }
		                });
		                scope.tree_rows = [];
		                for_each_branch(function (branch) {
		                    var child, f;
		                    if (branch.children) {
		                        if (branch.children.length > 0) {
		                            f = function (e) {
		                                if (typeof e === "string") {
		                                    return {
		                                        label: e,
		                                        children: []
		                                    };
		                                } else {
		                                    return e;
		                                }
		                            };
		                            return branch.children = (function () {
		                                var _i, _len, _ref, _results;
		                                _ref = branch.children;
		                                _results = [];
		                                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                                    child = _ref[_i];
		                                    _results.push(f(child));
		                                }
		                                return _results;
		                            })();
		                        }
		                    } else {
		                        return branch.children = [];
		                    }
		                });
		                add_branch_to_list = function (level, branch, visible) {
		                    var child, child_visible, tree_icon, _i, _len, _ref, _results;
		                    if (branch.expanded == null) {
		                        branch.expanded = false;
		                    }
		                    if (branch.classes == null) {
		                        branch.classes = [];
		                    }
		                    if (!branch.noLeaf && (!branch.children || branch.children.length === 0)) {
		                        tree_icon = attrs.iconLeaf;
		                        if (_.indexOf(branch.classes, "leaf") < 0) {
		                            branch.classes.push("leaf");
		                        }
		                    } else {
		                        if (branch.expanded) {
		                            tree_icon = attrs.iconCollapse;
		                        } else {
		                            tree_icon = attrs.iconExpand;
		                        }
		                    }
		                    scope.tree_rows.push({
		                        level: level,
		                        branch: branch,
		                        name: branch.name,
		                        label: branch.label,
		                        classes: branch.classes,
		                        tree_icon: tree_icon,
		                        visible: visible,
		                        isParent: branch.isParent,

		                        prods: branch.prods
		                    });
		                    if (branch.children != null) {
		                        _ref = branch.children;
		                        _results = [];
		                        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                            child = _ref[_i];
		                            child_visible = visible && branch.expanded;
		                            _results.push(add_branch_to_list(level + 1, child, child_visible));
		                        }
		                        return _results;
		                    }
		                };
		                _ref = scope.treeData;
		                _results = [];
		                for (_i = 0, _len = _ref.length; _i < _len; _i++) {
		                    root_branch = _ref[_i];
		                    _results.push(add_branch_to_list(1, root_branch, true));
		                }
		                return _results;
		            };
		            scope.$watch("changeMe", function (evnt) {
		                if (scope.changeMe) {
		                    for_each_branch(function (b) {
		                        if (b.name === scope.changeMe) {
		                            return select_branch(b);
		                        }
		                    });
		                }
		            });
		            scope.$watch("treeData", on_treeData_change, true);
		            if (attrs.initialSelection != null) {
		                for_each_branch(function (b) {
		                    if (b.label === attrs.initialSelection) {
		                        return $timeout(function () {
		                            return select_branch(b);
		                        });
		                    }
		                });
		            }
		            n = scope.treeData.length;
		            console.log("num root branches = " + n);
		            for_each_branch(function (b, level) {
		                b.level = level;
		                return b.expanded = b.level < expand_level;
		            });
		            if (scope.treeControl != null) {
		                if (angular.isObject(scope.treeControl)) {
		                    tree = scope.treeControl;
		                    tree.expand_all = function () {
		                        return for_each_branch(function (b, level) {
		                            return b.expanded = true;
		                        });
		                    };
		                    tree.collapse_all = function () {
		                        return for_each_branch(function (b, level) {
		                            return b.expanded = false;
		                        });
		                    };
		                    tree.get_first_branch = function () {
		                        n = scope.treeData.length;
		                        if (n > 0) {
		                            return scope.treeData[0];
		                        }
		                    };
		                    tree.select_first_branch = function () {
		                        var b;
		                        b = tree.get_first_branch();
		                        return tree.select_branch(b);
		                    };
		                    tree.get_selected_branch = function () {
		                        return selected_branch;
		                    };
		                    tree.get_parent_branch = function (b) {
		                        return get_parent(b);
		                    };
		                    tree.select_branch = function (b) {
		                        select_branch(b);
		                        return b;
		                    };
		                    tree.get_children = function (b) {
		                        return b.children;
		                    };
		                    tree.select_parent_branch = function (b) {
		                        var p;
		                        if (b == null) {
		                            b = tree.get_selected_branch();
		                        }
		                        if (b != null) {
		                            p = tree.get_parent_branch(b);
		                            if (p != null) {
		                                tree.select_branch(p);
		                                return p;
		                            }
		                        }
		                    };
		                    tree.add_branch = function (parent, new_branch) {
		                        if (parent != null) {
		                            parent.children.push(new_branch);
		                            parent.expanded = true;
		                        } else {
		                            scope.treeData.push(new_branch);
		                        }
		                        return new_branch;
		                    };
		                    tree.add_root_branch = function (new_branch) {
		                        tree.add_branch(null, new_branch);
		                        return new_branch;
		                    };
		                    tree.expand_branch = function (b) {
		                        if (b == null) {
		                            b = tree.get_selected_branch();
		                        }
		                        if (b != null) {
		                            b.expanded = true;
		                            return b;
		                        }
		                    };
		                    tree.collapse_branch = function (b) {
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            b.expanded = false;
		                            return b;
		                        }
		                    };
		                    tree.get_siblings = function (b) {
		                        var p, siblings;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            p = tree.get_parent_branch(b);
		                            if (p) {
		                                siblings = p.children;
		                            } else {
		                                siblings = scope.treeData;
		                            }
		                            return siblings;
		                        }
		                    };
		                    tree.get_next_sibling = function (b) {
		                        var i, siblings;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            siblings = tree.get_siblings(b);
		                            n = siblings.length;
		                            i = siblings.indexOf(b);
		                            if (i < n) {
		                                return siblings[i + 1];
		                            }
		                        }
		                    };
		                    tree.get_prev_sibling = function (b) {
		                        var i, siblings;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        siblings = tree.get_siblings(b);
		                        n = siblings.length;
		                        i = siblings.indexOf(b);
		                        if (i > 0) {
		                            return siblings[i - 1];
		                        }
		                    };
		                    tree.select_next_sibling = function (b) {
		                        var next;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            next = tree.get_next_sibling(b);
		                            if (next != null) {
		                                return tree.select_branch(next);
		                            }
		                        }
		                    };
		                    tree.select_prev_sibling = function (b) {
		                        var prev;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            prev = tree.get_prev_sibling(b);
		                            if (prev != null) {
		                                return tree.select_branch(prev);
		                            }
		                        }
		                    };
		                    tree.get_first_child = function (b) {
		                        var _ref;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            if (((_ref = b.children) != null ? _ref.length : void 0) > 0) {
		                                return b.children[0];
		                            }
		                        }
		                    };
		                    tree.get_closest_ancestor_next_sibling = function (b) {
		                        var next, parent;
		                        next = tree.get_next_sibling(b);
		                        if (next != null) {
		                            return next;
		                        } else {
		                            parent = tree.get_parent_branch(b);
		                            return tree.get_closest_ancestor_next_sibling(parent);
		                        }
		                    };
		                    tree.get_next_branch = function (b) {
		                        var next;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            next = tree.get_first_child(b);
		                            if (next != null) {
		                                return next;
		                            } else {
		                                next = tree.get_closest_ancestor_next_sibling(b);
		                                return next;
		                            }
		                        }
		                    };
		                    tree.select_next_branch = function (b) {
		                        var next;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            next = tree.get_next_branch(b);
		                            if (next != null) {
		                                tree.select_branch(next);
		                                return next;
		                            }
		                        }
		                    };
		                    tree.last_descendant = function (b) {
		                        var last_child;
		                        if (b == null) {
		                        }
		                        n = b.children.length;
		                        if (n === 0) {
		                            return b;
		                        } else {
		                            last_child = b.children[n - 1];
		                            return tree.last_descendant(last_child);
		                        }
		                    };
		                    tree.get_prev_branch = function (b) {
		                        var parent, prev_sibling;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            prev_sibling = tree.get_prev_sibling(b);
		                            if (prev_sibling != null) {
		                                return tree.last_descendant(prev_sibling);
		                            } else {
		                                parent = tree.get_parent_branch(b);
		                                return parent;
		                            }
		                        }
		                    };

		                    //    if (scope.selectText) {
		                    //        for_each_branch(function (b) {
		                    //            if (b.name === scope.selectText) {
		                    //                return select_branch(b);
		                    //            }
		                    //        });
		                    //    }
		                    //});

		                    return tree.select_prev_branch = function (b) {
		                        var prev;
		                        if (b == null) {
		                            b = selected_branch;
		                        }
		                        if (b != null) {
		                            prev = tree.get_prev_branch(b);
		                            if (prev != null) {
		                                tree.select_branch(prev);
		                                return prev;
		                            }
		                        }
		                    };
		                }
		            }
		        }
		    };
		}
    ]);
})();

(function (module) {
    var watcherFor = function (form, name) {
        return function () {
            if (name && form[name]) {
                return form[name].$invalid;
            }
        };
    };

    var updaterFor = function (element) {
        return function (hasError) {
            if (hasError) {
                element.removeClass("has-success")
					.addClass("has-error");
            } else {
                element.addClass("has-success")
					.removeClass("has-error");
            }
        };
    };

    var setupDom = function (element) {
        if (!angular.isDefined(element)) return;

        var input = element[0].querySelector("input, textarea, select, otf-rating");

        if (!input) return;
        try {
            input.classList.add("col-xs-8");
        } catch (ex) {
        }
        var type = 'radio';
        try {
            type = input.getAttribute("type");
        } catch (ex) {
        }

        var name = "";
        try {
            name = input.getAttribute("name");
        } catch (ex) {
        }
        if (type !== "checkbox" && type !== "radio") {
            input.classList.add("form-control");
        }

        var label = element[0].querySelector("label");
        try {
            label.classList.add("control-label");
            label.classList.add("col-xs-12");
        } catch (ex) {
        }

        return name;
        //ng-Messages-include='app/template/Messages.html'
    };

    var addMessages = function (form, element, name, $compile, scope) {
        var Messages = "<div class='help-block' ng-Messages='" +
			form.$name + "." + name + ".$error" +
			"' >  <div ng-Message='required'>You did not enter a field</div><div>";
        element.append($compile(Messages)(scope));
    };

    var link = function ($compile) {
        return function (scope, element, attributes, form) {
            var name = setupDom(element);
            addMessages(form, element, name, $compile, scope);
            scope.$watch(watcherFor(form, name), updaterFor(element));
        };
    };

    var forminput = function ($compile) {
        return {
            restrict: "A",
            require: "^form",
            link: link($compile)
        };
    };

    module.directive("forminput", forminput);
}(angular.module("app-hd")));;
(function () {
    "use strict";
    angular.module("app-hd").factory("eGiftCardService", ["$http" ,"$q", service]);

    function service($http, $q) {
        /**
         * @param {string} claimCode
         * @param {boolean} isSignUp Set if in the signup process
         * @param {number} customerId Only required if signup customer
         */
        function applyEgiftCardToAccount(claimCode, isSignUp, customerId) {
            var deferred = $q.defer();
            
            if (claimCode.length < 10 || claimCode.length > 30) {
                deferred.reject("Invalid claim code");
                return deferred.promise;
            }
            
            var baseUri = isSignUp ? 'signup-unclaimed-card' : 'unclaimed-card';
            var queryString = isSignUp ? `?customerId=${customerId}` : '';
            
            $http.get(`/api/egift-card/${baseUri}/${claimCode}/add-to-account${queryString}`).then(
                function () {
                    deferred.resolve();
                })
                .catch(function (err) {
                    if (err && err.status === 400) {
                        deferred.reject("Invalid claim code");
                    } else {
                        deferred.reject("Unknown error, please try again later");
                    }
                });
            
            return deferred.promise;
        }
        
        function getUnclaimedEGiftCardDetails(claimCode) {
            return $http.get(`/api/egift-card/unclaimed-card/${claimCode}/details`);
        }
        
        function getUnclaimedEGiftCardStatus(claimCode) {
            return $http.get(`/api/egift-card/unclaimed-card/${claimCode}/status`);
        }
        
        function getSignUpGiftCards(customerId) {
            return $http.get(`/api/egift-card/signup/cards?customerId=${customerId}`);
        }
        
        return {
            applyEgiftCardToAccount,
            getUnclaimedEGiftCardDetails,
            getUnclaimedEGiftCardStatus,
            getSignUpGiftCards
        }
    }
})();
;

//angular.module("app-hd")
//  .config(["$provide", function ($provide) {

//      var _errorCount = 0;

//      $provide.decorator("$exceptionHandler", ["$injector", "$delegate", function ($injector, $delegate) {
//          return function (exception, cause) {
//              try {
//                  $delegate(exception, cause);

//                  var $http = $injector.get('$http');
//                  var $cookies = $injector.get('$cookies');
//                  var url = window.location.href;
//                  var customerId = $cookies.get('customerId');

//                  if (customerId && customerId > 0 && _errorCount <= 3) {

//                      var errObj = {
//                          message: exception.message,
//                          url: url,
//                          line: exception.lineNumber,
//                          stack: exception.stack,
//                          cause: cause,
//                          customerId: customerId
//                      }
//                      _errorCount += 1;
//                      $http.post("/client-error", errObj);
//                  }

//              }
//              catch (err) {
//                  console.log(err);
//              }
//          };
//      }]);
//  }]);
;
(function() {
    "use strict";
    angular.module("app-hd").factory("giftCardService", ["customFetch", service]);

    function service(customFetch) {

        async function getLinkedGiftCards() {
            const response = await customFetch("/api/gift-card/linked-cards");

            if (response.status === 200) {
                return response.json();
            }
        }

        async function getValidCardBalance() {
            const response = await customFetch("/api/gift-card/valid-card-balance");

            if (response.status === 200) {
                return response.json();
            }
        }

        /**
         * @param {string} cardNumber
         * @param {string} cardRegCode
         */
        async function linkGiftCard(cardNumber, cardRegCode) {
            if (cardNumber.length < 10 || cardNumber.length > 30) {
                return {success: false, message: "Invalid card number"};
            }

            try {
                const response = await customFetch("/api/gift-card/linked-cards", {
                    method: "POST",
                    body: JSON.stringify({cardNumber, cardRegCode})
                });

                if (response.status === 200) {
                    return {success: true};
                }

                if (response.status === 400) {
                    return {success: false, message: (await response.json()).message};
                }

                return {success: false, message: "An error occurred"};
            } catch (e) {
                return {success: false, message: "An error occurred"};
            }
        }

        async function refreshGiftCardStatus(giftCardId) {
            try {
                const response = await customFetch(`/api/gift-card/refresh-status`, {
                    method: "PUT",
                    body: JSON.stringify({giftCardId})
                });

                if (response.status === 200) {
                    return {success: true, data: await response.json()};
                }

                return {success: false, message: "An error occurred"};

            } catch (e) {
                return {success: false, message: "An error occurred"};
            }
        }

        async function postOneTimePayment(amount) {
            try {
                const response = await customFetch("/api/payments/postGiftCardPayment", {
                    method: "POST",
                    body: JSON.stringify({amount})
                });

                if (response.status === 200) {
                    return {success: true, data: await response.json()};
                }
                
                if (response.status === 400) {
                    return {success: false, message: (await response.json()).message};
                }

                return {success: false, message: "An error occurred"};

            } catch (e) {
                return {success: false, message: "An error occurred"};
            }
        }

        return {
            linkGiftCard,
            getLinkedGiftCards,
            getValidCardBalance,
            refreshGiftCardStatus,
            postOneTimePayment
        };
    }
})();
;
(function () {
    "use strict";

    var serviceId = "googleAnalytics";
    angular.module('app-hd').factory(serviceId, function () {
        var dataLayer = window.dataLayer || [];

        function pushToDataLayer(event, data) {
            dataLayer.push({
                event: event,
                data: data
            });
        }

        return {
            push: pushToDataLayer
        };
    });


})();;
(function() {
    "use strict";
    angular.module("app-hd").factory("legacyEGiftCardService", ["$http", "$q", service]);

    function service($http, $q) {
        function applyEgiftCardToAccount(claimCode) {
            var deferred = $q.defer();

            if (claimCode.length < 10 || claimCode.length > 30) {
                deferred.reject("Invalid claim code");
                return deferred.promise;
            }
           
            $http.post("api/gift-card/linked-cards", {cardNumber: claimCode}).then(
                function() {
                    deferred.resolve();
                })
                .catch(function(err) {
                    if (err && err.status === 400) {
                        deferred.reject("Invalid claim code");
                    } else {
                        deferred.reject("Unknown error, please try again later");
                    }
                });

            return deferred.promise;
        }

        function getUnclaimedEGiftCardDetails(claimCode) {
            return $http.get(`/api/legacy-egift-card/unclaimed-card/${claimCode}/details`);
        }

        return {
            applyEgiftCardToAccount,
            getUnclaimedEGiftCardDetails
        };
    }
})();
;
(function () {
    "use strict";

    var serviceId = "paymentService";

    angular.module("app-hd").factory(serviceId, [paymentService]);

    function paymentService() {
        var paymentServiceFactory = {};

        function handlePaymentErrors(data) {
            //alert("postMessage function handlePaymentErrors is called. \nError: " + Object.values(data));
            //alert("postMessage function handlePaymentErrors is called. \nError: ", Object.values(data))
            var $form = $("#paymentForm form");
            var $validator = $form.validate();
            //310 Credit card number left blank or did not pass Mod10. 
            //370 Expiration date invalid.
            //530 ZIP / postal code field required but left blank.
            data.errorCode.forEach(function (code) {
                if (code == 310)
                    $validator.errorList.push({ "message": "Credit Card Number is Required." });

                if (code == 370)
                    $validator.errorList.push({ "message": "Expiration date is not valid." });

                if (code == 530)
                    $validator.errorList.push({ "message": "Zip Code is Required." });
            });


            if (data.gatewayMessage) {
                $validator.errorList.push({ "message": decodeURI(data.gatewayMessage).replace(/\+/g, ' ') });
            }
            else {
                $validator.errorList.push({ "message": "Please complete all fields and try again." });
            }

            $form.trigger('invalid-form.validate', $validator);
        }
        var completePayment = function(data) {
            alert("postMessage function completePayment is called. \nError: " + Object.values(data));
            var urlParams = new URLSearchParams(window.location.search);

            urlParams.set('order_Id', data.uID);
            urlParams.set('response_code', data.code);//data.code
            urlParams.set('response_code_text', data.message);

            window.location.search = urlParams;
        }
        function hpfReady() {
            //alert("HPF Form finished loading.");
        }
        function scrollRelay(scrollX, scrollY) {
            console.log("Scroll X: " + scrollX + "\nScroll Y: " + scrollY);
        }
        function startPayment() {
            var validator = $("#paymentForm form").validate();

            validator.resetForm();
            console.log("Payment processing start.");
        }
        function cancelPayment() {
            //alert("postMessage function cancelPayment is called. \n You have canceled the payment.");
            window.history.back();
        }
        // For Credit card and ECP payment
        function whatsThis(data) {
            if (data == "cvv") {
                alert("The 3 numbers on the back of your card.");
            }
            if (data == "routing") {
                alert("Routing number can be up to 9 digits.");
            }
            if (data == "account") {
                alert("Account number can be between 3 and 17 digits.");
            }
        }
        // For Credit Card Payment
        function whatCVV2() {
            alert("The 3 numbers on the back of your card");
        }

        return paymentServiceFactory;
    }
})();;
(function () {
    "use strict";

    var serviceId = "repositories";
    angular.module("app-hd").factory(serviceId, ["$injector", repositories]);

    function repositories($injector) {
        var manager;
        var service = {
            getRepo: getRepo,
            init: init
        };
        return service;

        function init(mgr) {
            manager = mgr;
        }

        function getRepo(repoName) {
            var fullRepoName = "repository." + repoName.toLowerCase();
            var Repo = $injector.get(fullRepoName);
            var newrepo = new Repo();
            return newrepo;
        }
    }
})();;
(function () {
    var serviceId = 'repository.abstract';
    angular.module('app-hd').factory(serviceId, ['$cookies', '$http', '$timeout', 'datacontext', 'CacheFactory', 'config', 'authService', 'common', '$rootScope', abstractRepository]);

    function abstractRepository($cookies, $http, $timeout, datacontext, DSCacheFactory, config, authService, common, $rootScope) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var logError = common.logger.getLogFn(this.serviceId, 'Error');
        var $q = config.$q;

        function _getuserId() { return "" + authService.authentication.userName; }

        function _getBasePath() { return $rootScope.imageBasePath; }

        function Ctor() {
            this.$q = common.$q;
            this.$http = $http;
            this.$cookies = $cookies;
            this.$timeout = $timeout;
            this.datacontext = datacontext;
            this.baseUrl = config.baseUrl;
            this.isLoaded = false;
            this.detaiIsLoaded = false;
            this.partialsMappedLoaded = false;
            this.getorderPartialsMappedLoaded = false;
            this.localStorageCacheOff = config.localStorageCacheOff;
            this.removeCacheItem = _removeCacheItem;
            this.getQParm = _getQParm;
            this.getuserId = _getuserId;
            this.saveThisDC_In_myCache = _saveThisDC_In_myCache;
            this.LoadThisDC_from_myCache = _LoadThisDC_from_myCache;

            this.saveData_In_myCache = _saveData_In_myCache;
            this.LoadThisDC_from_myCache = _LoadThisDC_from_myCache;
            this.getLatestUpdateStats = getLatestUpdateStats;
            this.isTableUptoDate = isTableUptoDate;
            this.serverDateTimes = [];
        }

        var allCache = DSCacheFactory.get("AllCache");

        DSCacheFactory("AllCache", {
            storageMode: "localStorage",
            //maxAge: 60 * 60 * 1000, // 1 hour,
            maxAge: 60 * 60 * 72000, // 72 hour,

            deleteOnExpire: 'aggressive',
            onExpire: function (key, value) {
                switch (key) {
                    case "productgetPartialsMapped":
                        datacontext.products.getProductPartialsForPriceCode(datacontext.cust.mycust.price_schedule, datacontext.cust.mycust.nextDeliveryDate);

                        break;
                    case "categorygetPartials":
                        datacontext.products.getProductPartialsForPriceCode(datacontext.cust.mycust.price_schedule, datacontext.cust.mycust.nextDeliveryDate);
                        break;
                    case "productgetPartialsMappedFromUrl":
                        datacontext.products.getPartialsMappedFromUrl("api/products/GetDetailProducts", true);
                        break;
                    default:
                        break;
                }
            }
        });

        //,  maxAge: 10*60 * 60 * 1000, deleteOnExpire: 'aggressive' }); /// this needs to be implemented but reload needs to be addressed
        allCache = DSCacheFactory.get("AllCache");

        var myCache = DSCacheFactory.get("myCache");
        //if (allCache == null) {
        DSCacheFactory("myCache", {
            storageMode: "localStorage"
        });

        myCache = DSCacheFactory.get("myCache");

        Ctor.extend = function (repoCtor) {
            repoCtor.prototype = new Ctor();
            repoCtor.prototype.constructor = repoCtor;
        };
        Ctor.prototype.getBasePath = _getBasePath;
        Ctor.prototype.isAuth = authService.authentication.isAuth;
        Ctor.prototype._isItemCached = _isItemCached;
        Ctor.prototype.getItemsLoaded = _getItemsLoaded;
        Ctor.prototype.putItemsLoaded = _putItemsLoaded;
        Ctor.prototype.getPartials = getPartials;
        Ctor.prototype.getPartialsFromUrl = getPartialsFromUrl;
        Ctor.prototype.getPartialsMappedFromUrl = getPartialsMappedFromUrl;
        Ctor.prototype._areItemsCached = _areItemsCached;
        Ctor.prototype._areItemsLoaded = _areItemsLoaded;
        Ctor.prototype.getUserId = _getuserId;
        Ctor.prototype.$q = common.$q;
        Ctor.prototype.getQParm = _getQParm;
        Ctor.prototype.LoadThisDC_from_myCache = _LoadThisDC_from_myCache;
        Ctor.prototype.saveThisDC_In_myCache = _saveThisDC_In_myCache;
        Ctor.prototype.LoadData_from_myCache = _LoadData_from_myCache;
        Ctor.prototype.saveData_In_myCache = _saveData_In_myCache;

        return Ctor;

        function _getQParm(key) {
            var vars = [], hash;
            var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
            for (var i = 0; i < hashes.length; i++) {
                hash = hashes[i].split('=');
                vars.push(hash[0]);
                vars[hash[0]] = hash[1];
            }
            return vars[key];
        }

        function isTableUptoDate(tableNames, cachePrefix) {
            //
            //  returns a promise and when it can be determined the promise
            //  is resolved with the answer to if the table data is up to date
            //  if a false is returned the calling function should update its data

            var self = this;

            if (tableNames == '') return self.$q.when(true);
            var parmName = tableNames.replace(',', "");

            var dependPromise = datacontext.tableCachePromises[parmName];
            if (dependPromise) {
                return dependPromise.promise;
            }

            //if (self.isTableUptoDatePromise) return self.isTableUptoDatePromise.promise;
            datacontext.tableCachePromises[parmName] = self.$q.defer();

            self.getLatestUpdateStats(cachePrefix).then(function () {
                // latest stats are in memory now check dates
                // for table name passed in

                var rtrn = false;
                var tempRtrn = true;
                var tblNames = tableNames.split(",");
                tblNames.forEach(function (tblName) {
                    var lastUpdate = self._areItemsCached(cachePrefix + '-LastUpdate:' + tblName);
                    lastUpdate = (lastUpdate) ? lastUpdate : new Date(1900, 0, 1, 2, 3, 4, 567);
                    var mydate = moment(lastUpdate);
                    var tblItem = self.serverDateTimes.filter(function (item) {
                        if (item.databaseName == tblName) {
                            return true;
                        }
                        return false;
                    });

                    if (tblItem.length > 0) {
                        var tblUpdated = tblItem[0].last_update;

                        var localDate = moment(lastUpdate);
                        var serverDate = moment(tblUpdated);

                        var ServerIsNewer = moment(tblUpdated).isAfter(lastUpdate);
                        if (tempRtrn) {
                            if (ServerIsNewer) {
                                // once you get a false do not set to true
                                tempRtrn = false;
                                rtrn = false;
                            } else {
                                rtrn = true;
                            }
                        }
                    }
                });
                datacontext.tableCachePromises[parmName].resolve(rtrn);
            });
            return datacontext.tableCachePromises[parmName].promise;
        }

        function getLatestUpdateStats(cachePrefix) {
            //
            //  this returns the datatime array that was last obtained from the server
            //  it is stored on the client only if it has not been previously read
            //   otherwise not maintained on the client but is stored in the instance memory
            //

            //  the server stats are used by the data look up functions.  They check to see
            //  if the table was updated since the last read.

            var self = this;
            if (datacontext.lastUpdateStatsPromise) {
                return datacontext.lastUpdateStatsPromise.promise;
            }
            datacontext.lastUpdateStatsPromise = self.$q.defer();

            if (self.serverDateTimes.length > 0)
                return self.$q.when(self.serverDateTimes);

            $http.get("api/Products/GetLastUpdateStats")
            .then(querySucceeded, function () {
                datacontext.lastUpdateStatsPromise.reject();
            })
            return datacontext.lastUpdateStatsPromise.promise;

            function querySucceeded(response) {

                var cacheKey = cachePrefix + '-GetLastUpdateStats';
                var cacheData = self._areItemsCached(cacheKey);
                if (!(angular.isDefined(cacheData) && angular.isArray(cacheData))) {
                    // last update information not found in previous cache
                    // save these results in the cache.
                    self.putItemsLoaded(cacheKey, response.data);
                }
                self.serverDateTimes = response.data;
                datacontext.lastUpdateStatsPromise.resolve(self.serverDateTimes);
            };
        }

        function getPartials(forceRefresh) {
            //
            //
            //
            var self = this;
            if (self.isLoaded) {
                return self.$q.when(self.entityItems);
            }
            var cacheKey = self.entityName + 'getPartials';

            if (!forceRefresh) {
                var items = self._areItemsCached(cacheKey);
                if (angular.isDefined(items) && angular.isArray(items)) {
                    self.isLoaded = true;
                    self.entityItems = items;
                    return self.$q.when(items);
                }
            }

            return $http.get(self.getPartialsUrl).success(querySucceeded);

            function querySucceeded(data) {
                self.isLoaded = true;

                self.putItemsLoaded(cacheKey, data);
                self.entityItems = data;
                return self.entityItems;
            }
        }

        function getPartialsFromUrl(url, forceRefresh) {
            var self = this;
            var cacheKey = self.entityName + 'getPartialsFromUrl' + url;
            if (!forceRefresh) {
                var items = self._areItemsCached(cacheKey);
                if (angular.isDefined(items)) {
                    self.entityItems = items;
                    return self.$q.when(items);
                }
            }

            return $http.get(url).success(querySucceeded);

            function querySucceeded(data) {
                self.putItemsLoaded(cacheKey, data);
                self.entityItems = data;
            }
        }

        function getPartialsMappedFromUrl(addObjectUrl, forceRefresh) {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;
            var defer = self.$q.defer();
            var cacheKey = self.entityName + 'getPartialsMappedFromUrl';
            if (!forceRefresh) {
                if (self.detaiIsLoaded) {
                    return self.$q.when(self.entityItems);
                }

                var data = self._areItemsCached(cacheKey);

                if (angular.isDefined(data) && angular.isArray(data)) {
                    {
                        var dataObj = _.object(data[0], data[1]);

                        angular.forEach(dataObj, function (value) {
                            if (angular.isDefined(self.entityItems[value.id]))
                                _.extend(self.entityItems[value.id], value);
                            else {
                                self.entityItems[value.id] = value;
                                self.entityData.push(value);
                            }
                        });

                        self.detaiIsLoaded = true;
                        return self.$q.when(self.entityItems);
                    }
                }
            }

            $http.get(addObjectUrl)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //
                // this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects

                var dataObj = _.object(data[0], data[1]);

                angular.forEach(dataObj, function (value) {
                    if (angular.isDefined(self.entityItems[value.id]))
                        _.extend(self.entityItems[value.id], value);
                    else {
                        self.entityItems[value.id] = value;
                        self.entityData.push(value);
                    }
                });

                self.detaiIsLoaded = true;
                self.putItemsLoaded(cacheKey, data);
                defer.resolve(data);
            }
        }

        function _putItemsLoaded(index, data) {
            index = this.getuserId() + index;
            var value = allCache.put(index, data);
            return value;
        }

        function _getItemsLoaded(index) {
            var value = allCache.get(index);

            return value;
        }

        function _areItemsLoaded(value) {
            var self = this;

            if (value === undefined) {
                if (!self.isLoaded) {
                    if (self.entityItems.length > 0) {
                        self.isLoaded = true;
                    }
                }
                return self.isLoaded;
            }
            return self.isLoaded = value;
        }

        //
        //  this was updated to return true false and not items
        //

        function _areItemsCached(index) {
            var self = this;
            index = this.getuserId() + index;
            if (self.localStorageCacheOff) return undefined; // jmg disable cache

            if (angular.isDefined(index))
                return allCache.get(index);

            return undefined;
        }

        function _removeCacheItem(index) {
            var self = this;
            index = this.getuserId() + index;
            if (angular.isDefined(index))
                return allCache.remove(index);

            return undefined;
        }

        function _isItemCached(index) {
            index = this.getuserId() + index;
            var value = allCache.get(index);

            if (value === undefined) {
                {
                    this.isLoaded = false;
                    return undefined;
                }
            } else {
                this.isLoaded = true;

                return value;
            }
        }

        function _saveThisDC_In_myCache() {
            var self = this;
            myCache.put(this.getuserId() + self.entityName, self.mycust);
        }

        function _LoadThisDC_from_myCache() {
            var self = this;
            var tmp = myCache.get(this.getuserId() + self.entityName);

            angular.copy(tmp, self.mycust);
        }

        function _saveData_In_myCache(key, value) {
            myCache.put(this.getuserId() + key, value);
        }

        function _LoadData_from_myCache(key) {
            return myCache.get(this.getuserId() + key);
        }
    }
})();;
(function () {
    var serviceId = 'repository.category';
    angular.module('app-hd').factory(serviceId,
    ['common', 'repository.abstract', 'datacontext', RepositoryCategories]);

    function RepositoryCategories(common, abstractRepository, datacontext) {
        var vm = this;
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var $q = common.$q;

        function Ctor() {
            this.entityName = 'category';
            this.getCatTree = _getCatTree;
            this.getCatTreelocal = _getCatTreelocal;
            this.entityItems = [];
            this.AdminCategoryItems = [];
            this.getPartialsUrl = 'api/products/GetProdIdCatTree';
            this.selectedParentName = ""; //  this is the top parentName of any selection
            this.selectedName = "";
            this.selectedCategory = {};
            this.categories = [];
            this.NameSelectedCategory = '';
            this.selectcategory = selectcategory;
            this.checkChildrenForCategory = checkChildrenForCategory;
            this.isLoaded = false;

            this.productViewName = undefined;
            this.productViewCategory = undefined;
            this.productViewCategorys = undefined; // these are the category s at the header level
            this.setProductViewName = setProductViewName;
            this.categoryListing = [];
            this.selectcategoryFromElement = selectcategoryFromElement;
            // administrative functions
            this.getCatTreeAdmin = _getCatTreeAdmin;
            this.putCatTreeAdmin = _putCatTreeAdmin;
            this.deleteCatTreeAdmin = _deleteCatTreeAdmin;
            this.isTableUptoDatePromise = undefined;
            this.reset = reset;
        }

        abstractRepository.extend(Ctor);

        return Ctor;
        function checkChildrenForCategory(seekingCatName, category) {
            var self = this;
            var result = null
            category.sortedChildren.forEach(function (childCategory) {
                // first check the top categories:
                if (childCategory.name == seekingCatName) {
                    // since this is a child for it to list correctly create an blank parent for the select
                    result = childCategory;
                } else {
                    result = self.checkChildrenForCategory(seekingCatName, childCategory);
                }
            });
            return result;
        }

        function reset() {
            this.entityItems = [];
            this.AdminCategoryItems = [];
            this.selectedParentName = ""; //  this is the top parentName of any selection
            this.selectedName = "";
            this.isLoaded = false;
            this.selectedCategory = {};
            this.categories = [];
            this.NameSelectedCategory = '';
            this.isLoaded = false;
            this.productViewName = undefined;
            this.productViewCategory = undefined;
            this.productViewCategorys = undefined; // these are the category s at the header level

            this.categoryListing = [];
        }

        function selectcategoryFromElement(elem) {
            //this is used when an element needs to call for a category change
            var self = this;
            self.selectcategory(elem.cat2.name);
        }

        function selectcategory(categoryName) {
            var self = this;
            categoryName = categoryName.toLowerCase();
            if (self.NameSelectedCategory == categoryName) return;
            if (categoryName.length == 0)
                self.selectedCategory = null;
            self.NameSelectedCategory = null;
            self.categories = [];

            // check the first level because it should be there
            if (this.productViewCategorys)
                this.productViewCategorys.forEach(
                    function (category) {
                        if (category.name == categoryName) {
                            self.selectedCategory = category;
                            self.NameSelectedCategory = category.name;
                            self.categories = category.sortedChildren;
                        }
                    });

            // if it was not found in the first level check all of them
            if (self.NameSelectedCategory == null)
                self.entityItems.forEach(
                    function (category) {
                        if (category.name == categoryName) {
                            self.categories = category.sortedChildren;
                            self.selectedCategory = category;
                            self.NameSelectedCategory = category.name;
                        } else {
                            self.checkChildrenForCategory(categoryName, category);
                        }
                    });
        };

        function setProductViewName(searchCat, forceSelect) {
            var self = this;
            if (searchCat === 'lookbook') {
                self.productViewName = searchCat;
                return;
            }
            if (searchCat === 'preorder') {
                self.productViewName = searchCat;
                return;
            }
            if (searchCat === 'collections') {
                self.productViewName = searchCat;
                return;
            }
            if (searchCat === 'produce') {
                //bc produce is still handeld like a regular category nested under "Products" it needs to still assign the children 
                self.productViewName = searchCat;
                self.productViewCategory = null;
                self.entityItems.forEach(function (catitem) {
                    var rslt = self.checkChildrenForCategory(searchCat, catitem);
                    if (rslt != null) {
                        self.productViewCategory = rslt;
                        self.productViewName = searchCat;
                    }
                });
                if (self.productViewCategory) {
                    this.NameSelectedCategory = this.productViewCategory.name;
                    this.categories = self.productViewCategorys = this.productViewCategory.sortedChildren;
                }
                return;
            }

            searchCat = searchCat.toLowerCase();
            if (!forceSelect) {
                if ((self.entityItems.length <= 0) || (self.NameSelectedCategory == searchCat)) return;

                if (self.productViewName == searchCat) return;
            }
            self.productViewCategory = null;
            self.productViewName = null;
            if (searchCat != 'all')
                self.datacontext.products.clearSearch();
            // first check the top categories:

            self.entityItems.forEach(function (topcat) {
                if (topcat.name == searchCat) {
                    self.productViewCategory = topcat;
                    self.productViewName = topcat.name;
                }
            });
            // now check the children and whole cat

            if (self.productViewName == null) {
                self.entityItems.forEach(function (catitem) {
                    var rslt = self.checkChildrenForCategory(searchCat, catitem);
                    if (rslt != null) {
                        self.productViewCategory = rslt;
                        self.productViewName = catitem.name;
                    }
                });
            }

            if (self.productViewCategory) {
                this.NameSelectedCategory = this.productViewCategory.name;
                this.categories = self.productViewCategorys = this.productViewCategory.sortedChildren;
            }
        }

        function _getCatTreelocal() {
            //
            // the purpose of this method is to
            // give the users faster access to market
            // it loads the products from previous
            // session while another process validates
            //
            var self = this;
            var cacheKey = self.entityName + 'getPartials';

            var items = self._areItemsCached(cacheKey);
            if (angular.isDefined(items) && angular.isArray(items)) {
                // self.isLoaded = true;
                self.entityItems = items;
            }
        }

        function _getCatTree(branchNumber, forceRefresh) {
            //
            //

            //
            //forceRefresh = true;
            var self = this;
            //if ((datacontext.currentInstanceIds.branchNumber == branchNumber) && (self.isLoaded) && (self.entityItems.length > 0))
            //    return self.$q.when(self.entityItems);

            //var tableNames = 'Category,ProductCategory';

            //if (self.isLoaded) {
            //    return self.$q.when(self.entityItems);
            //}
            var defer = $q.defer();
            //var cacheKey = self.entityName + 'getPartials';

            ////  this is where a method is wrapped in a promise.  This method can now
            ////  now just return a promise that will be resolved later and async processing
            ////  will take over
            //var cachePrefix = 'shop';
            //self.isTableUptoDate(tableNames, cachePrefix).then(function (isTableUptoDate_result) {
            //    if (!forceRefresh) {
            //        // if not force refresh do the refresh if our data is out of date
            //        forceRefresh = !isTableUptoDate_result;
            //    }

            //    if (!forceRefresh) {
            //        var items = self._areItemsCached(cacheKey);
            //        if (angular.isDefined(items) && angular.isArray(items)) {
            //            self.isLoaded = true;
            //            self.entityItems = items;
            //            defer.resolve(items);
            //        }
            //    } else {
                    var url = self.getPartialsUrl;
                    if (branchNumber != null)
                url += "?branchNumber=" + branchNumber;
                    self.$http.get(url)
                        .success(function querySucceeded(data) {
                            self.isLoaded = true;

                            //self.putItemsLoaded(cacheKey, data);
                            self.entityItems = data;
                            //var tblNames = tableNames.split(",");

                            //tblNames.forEach(function (tblName) {
                            //    self.putItemsLoaded(cachePrefix + '-LastUpdate:' + tblName, Date.now());
                            //});
                            defer.resolve(data);
                        })
                    .error(function () {
                        defer.reject();
                    });

                    //function querySucceeded(data) {
                    //    self.isLoaded = true;

                    //    self.putItemsLoaded(cacheKey, data);
                    //    self.entityItems = data;
                    //    var tblNames = tableNames.split(",");

                    //    tblNames.forEach(function (tblName) {
                    //        self.putItemsLoaded(cachePrefix + '-LastUpdate:' + tblName, Date.now());
                    //    });
                    //    defer.resolve(data);
                    //}
                //}
            //});
            return defer.promise;
        }

        function _getCatTreeAdmin(forceRefresh) {
            //
            //
            //
            var self = this;
            var defer = $q.defer();

            var url = 'api/products/GetAdminProdIdCatTree';

            self.$http.get(url).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                self.isLoaded = true;

                self.AdminCategoryItems = data;
                defer.resolve(data);
            }
        }

        function _putCatTreeAdmin() {
            //
            //
            //
            var self = this;
            var defer = $q.defer();
            var url = 'api/products/PutAdminProdIdCatTree';

            self.$http.put(url, self.selectedCategory).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                var prods = [];

                if (!self.selectedCategory.prods) self.selectedCategory.prods = prods;

                self.selectedCategory.prods.forEach(function (myProd) {
                    var newprod = myProd;
                    prods.push(newprod);
                });
                defer.resolve(data);
            }
        }

        function _deleteCatTreeAdmin(id) {
            //
            //
            //
            var self = this;
            var defer = $q.defer();
            var url = 'api/products/DeleteAdminProdIdCatTree?Id=' + id;

            self.$http.delete(url).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //Todo: need to delete item from tree data
                //localStorage.clear();
                // self.entityItems = {};
                // self.AdminCategoryItems = {};
                // self.getCatTreeAdmin();
                // self.datacontext.productcategory.loadAllData();

                defer.resolve(data);
            }
        }
    }
})();;
(function () {
    // "use strict";

    var serviceId = "repository.cust";
    angular.module("app-hd").factory(serviceId,
        ["$state", "$cookies", "$q", "datacontext", "common", "repository.abstract", "authService", "config", Repositorycust]);

    function Repositorycust($state, $cookies, $q, datacontext, common, abstractRepository, authService, config) {
        var getLogFn = common.logger.getLogFn;

        function Ctor() {
            this.AuthInfo = authService.authentication;
            this.NewCustomerInProcess = false;

            this.as400Refresh = false;
            this.custId = null;
            this.custStep = "1";

            this.entityName = "cust";
            this.getCustId = _getCustId;
            this.customerInitialized = null;
            this.promoCode = '';
            this.int_custStep = 1;
            this.isLoaded = false;
            this.mycust = null;
            this.selectedName = "";
            this.user = undefined;
            this.salesId = '';
            this.salesAdding = '';

            this.doesUserNameExist = _doesUserNameExist;
            this.paymentsummary = undefined;
            this.getPaymentSummary = getPaymentSummary;
            this.getselectedName = getselectedName;
            this.ApplyOrderData = _ApplyOrderData;
            this.getCustomerWithOrder = getCustomerWithOrder;

            this.lookupCustomer = _lookupCustomer;
            this.lookupCustomerById = _lookupCustomerById;
            this.lookupCustomerByEmail = _lookupCustomerByEmail;
            this.getCustomerData = _getCustomerData;
            this.TestMyCustomerAddress = _TestMyCustomerAddress;
            this.ProcessAddress = _processAddress;
            this.LoadDataLocal = LoadDataLocal;
            this.getEmptyCust = getEmptyCust;
            this.lastPaymentSummary = {
                mdate: new moment('04/25/1971', 'MM-DD-YYYY')
            };
            this.getAccountBalanceSummary = getAccountBalanceSummary;
            this.accountBalanceSummary = null;
            this.InsSignupNoComplete = InsSignupNoComplete;
            this.updateStepNumber = updateStepNumber;
            this.InsSignupNoDelivery = InsSignupNoDelivery;
            this.postCustomerFeedback = postCustomerFeedback;
            this.postProductFeedback = postProductFeedback;
            this.getProductFeedback = getProductFeedback;
            this.updateSelectedProductCollection = UpdateSelectedProductCollection;

            this.aptQuestions = [null, null, null, null, null, null];

            this.getLastcategory = getLastcategory;
            this.putLastcategory = putLastcategory;

            this.getLastcategoryParam = getLastcategoryParam;
            this.putLastcategoryParam = putLastcategoryParam;

            this.getStaySignedIn = getStaySignedIn;
            this.setStaySignedIn = setStaySignedIn;

            this.getShowOneTimePopup = getShowOneTimePopup;
            this.setShowOneTimePopup = setShowOneTimePopup;

            this.getShowOneTimePopupHouse = getShowOneTimePopupHouse;
            this.setShowOneTimePopupHouse = setShowOneTimePopupHouse;

            this.getShowOneTimePopupApartment = getShowOneTimePopupApartment;
            this.setShowOneTimePopupApartment = setShowOneTimePopupApartment;

            this.updateReferralRewardsAvailable = updateReferralRewardsAvailable;

            this.initialDatadefered = true;
            this.loadOrderData = loadOrderData;
            this.reset = reset;
            this.getAuthenticationUrl = getAuthenticationUrl;
            this.getTransactionUrl = getTransactionUrl;
            this.getPaymentData = getPaymentData;
            this.getNameList = _getNameList;
            this.confirmCustomerName = confirmCustomerName;
            this.getSalesPerson = _getSalesPerson;

            this.$state = $state;
            this.$cookies = $cookies;
        }

        abstractRepository.extend(Ctor);
        return Ctor;
        function getLastcategory() {
            var self = this;
            var data = self._areItemsCached('LastcategoryURL');
            return data;
        }

        function getAuthenticationUrl(returnUrl, userId, newStart) {

            var self = this;

            var defer = $q.defer();

            common.$broadcast(config.events.spinnerToggle, { show: true });

            returnUrl = window.location.origin + returnUrl;

            var postObj = {
                returnUrl: returnUrl,
                customerId: self.custId,
                orderUserId: userId ? userId : self.mycust.customerNumber,
                invoiceNumber: "",
                purchaseOrderNumber: self.mycust.userName,
                requireCCV: true, //!self.salesAdding,
                customerNumber: self.mycust.customerNumber
            }
            //console.log(postObj);
            //return paymentSummaryPromise =
            self.$http.post('api/payments/GetAuthenticationUrl/' + newStart, postObj).then(function (response) {
                //console.log(response.data);
                common.$broadcast(config.events.spinnerToggle, { show: false });

                defer.resolve(response.data);
                return;
            }, function () {
                common.$broadcast(config.events.spinnerToggle, { show: false });
                defer.reject();
            });
            return defer.promise;
        }

        function getTransactionUrl(amount, returnUrl) {
            var self = this;
            var defer = $q.defer();

            returnUrl = window.location.origin + returnUrl;

            common.$broadcast(config.events.spinnerToggle, { show: true });


            var postObj = {
                returnUrl: returnUrl,
                customerId: self.custId,
                orderUserId: self.mycust.customerNumber,
                invoiceNumber: "",
                purchaseOrderNumber: self.mycust.userName,
                amount: amount,
                customerNumber: self.mycust.customerNumber
            }

            self.$http.post('api/payments/GetTransactionUrl/', postObj).then(function (response) {
                common.$broadcast(config.events.spinnerToggle, { show: false });
                defer.resolve(response.data);
                return;
            }, function () {
                common.$broadcast(config.events.spinnerToggle, { show: false });
                defer.reject();
            });
            return defer.promise;
        }

        function getPaymentData(orderId, isNewCustomer) {

            var self = this;
            var defer = $q.defer();

            //console.log(self)
            var id = self.getCustId();

            //return paymentSummaryPromise =
            self.$http.get('api/payments/getPaymentData/' + id + '/' + orderId + "/" + isNewCustomer).then(function (response) {
                //console.log(response.data);
                defer.resolve(response.data);
                return;
            }, function () {
                defer.reject();
            });
            return defer.promise;
        }

        function updateReferralRewardsAvailable() {
            var self = this;
            return self.$http.get('/api/referral/TotalRewardAvailable')
                .then(function(result) {
                    if (result && result.data && typeof result.data.amount === "number")
                        self.mycust.referralProgram.rewardsAvailable = result.data.amount;
                });
        }

        function reset() {
            var self = this;
            self.NewCustomerInProcess = false;

            self.as400Refresh = false;
            self.custId = null;
            self.custStep = "1";
            self.$cookies.remove("custId");
            self.removeCacheItem("custId");
            self.int_custStep = 1;
            self.customerInitialized = null;

            self.isLoaded = false;
            self.mycust = this.getEmptyCust();
            self.selectedName = "";
            self.user = undefined;
        }

        function setShowOneTimePopup(value) {
            var self = this;
            self.putItemsLoaded('ShowOneTimePopup', value);
        }

        function setShowOneTimePopupHouse(value) {
            var self = this;
            self.putItemsLoaded('ShowOneTimePopupHouse', value);
        }

        function setShowOneTimePopupApartment(value) {
            var self = this;
            self.putItemsLoaded('ShowOneTimePopupApartment', value);
        }

        function getShowOneTimePopupHouse() {
            var self = this;
            var data = self._areItemsCached('ShowOneTimePopupHouse');
            data = (data) ? data : false; // this may not be necessary but it turns a undefined into a false
            return data;
        }

        function getShowOneTimePopupApartment() {
            var self = this;
            var data = self._areItemsCached('ShowOneTimePopupApartment');
            data = (data) ? data : false; // this may not be necessary but it turns a undefined into a false
            return data;
        }

        function getShowOneTimePopup() {
            var self = this;
            var data = self._areItemsCached('ShowOneTimePopup');
            data = (data) ? data : false; // this may not be necessary but it turns a undefined into a false
            return data;
        }

        function setStaySignedIn(value) {
            var self = this;
            self.putItemsLoaded('StaySignedIn', value);
        }

        function getStaySignedIn() {
            var self = this;
            var data = self._areItemsCached('StaySignedIn');
            return data;
        }

        function putLastcategory(categoryUrl) {
            var self = this;
            self.putItemsLoaded('LastcategoryURL', categoryUrl);
        }

        function getLastcategoryParam(productViewId) {
            var self = this;
            var data = self._areItemsCached('LastcategoryURL' + productViewId);
            return data;
        }

        function putLastcategoryParam(productViewId, subviewId) {
            var self = this;
            self.putItemsLoaded('LastcategoryURL' + productViewId, subviewId);
        }

        function _ApplyOrderData(productEntities) {
            var self = this;
            angular.forEach(self.mycust.orders, function (item, key) {
                self.loadOrderData(item, productEntities);
            });
            return productEntities;
        }

        function getAccountBalanceSummary(forceRefresh) {

            var self = this;
            var defer = $q.defer();

            if (self.accountBalanceSummary && !forceRefresh) {
                return self.$q.when(self.accountBalanceSummary);
            }

            self.$http.get('api/payments/GetPaymentBalanceSummary').then(function (response) {
                self.accountBalanceSummary = response.data;

                defer.resolve(self.accountsummary);
                return;
            });
            return defer.promise;
        }

        function getPaymentSummary(forceRefresh) {
            //
            //
            //
            //

            var self = this;
            var defer = $q.defer();


            if (self.paymentsummary && !forceRefresh) {
                return self.$q.when(self.paymentsummary);
            }

            //return paymentSummaryPromise =
            self.$http.get('api/payments/getPaymentsHistory').then(function (response) {
                self.paymentsummary = response.data;

                var lastdate = new Date('1/1/1970');
                var paymentTotal = 0;
                var chargeTotal = 0;
                if (self.paymentsummary.length > 0) {
                    self.paymentsummary.forEach(function (item) {
                        if (item.type == 'Payment') {
                            var mdate = new moment(item.transaction_date);
                            if (mdate.isAfter(self.lastPaymentSummary.mdate)) {
                                this.lastPaymentSummary = item;
                            }

                            paymentTotal += item.amount;
                        } else chargeTotal += item.amount;
                    });
                }
                self.paymentsummary.lastPaymentDate = new moment(self.lastPaymentSummary.transaction_date).toDate();
                self.paymentsummary.chargeTotal = chargeTotal;
                self.paymentsummary.currentBalance = chargeTotal + paymentTotal;
                defer.resolve(self.paymentsummary);
                return;
            });

            return defer.promise;
        }

        function _doesUserNameExist(userName) {
            var self = this;

            return self.$http.get("/api/account/DoesUserNameExist?userName=" + userName).then(function (response) {
                return response;
            });
        }

        function _lookupCustomer() {
            var self = this;
            var deferred = self.$q.defer();

            self.$http.post("api/customers/LookupAccount", this.mycust)
                .then(function (response) {
                    self.mycust = response.data;
                    deferred.resolve(response.data);
                    return;
                },
                    function (response) {
                        deferred.reject(response);
                        return;
                    });
            return deferred.promise;
        }

        function _lookupCustomerByEmail() {
            var self = this;
            var deferred = self.$q.defer();

            self.$http.post("api/customers/LookupAccountByEmail", this.mycust)
                .then(function (response) {
                    self.mycust = response.data;
                    deferred.resolve(response.data);
                    return;
                },
                    function (response) {
                        deferred.reject(response);
                        return;
                    });
            return deferred.promise;
        }

        function _lookupCustomerById(cid) {
            var self = this;
            var deferred = self.$q.defer();

            self.$http.post("api/customers/LookupAccountByCID", cid).then(function (response) {
                self.mycust = response.data;
                deferred.resolve(response.data);
                return;
            }, function (response) {
                deferred.reject(response);
                return;
            });
            return deferred.promise;
        }

        function getEmptyCust() {
            return {
                "orders": [],
                "StandardizedAddress": {},
                "tblCustomers": [],
                "id": null,
                "userId": null,
                "customer_number": null,
                "firstname": null,
                "lastname": "",
                "address1": null,
                "address2": null,
                "city": null,
                "state": "",
                "zip": "",
                "phone": null,
                'EOW': '0',
                "email": "",
                "priceCode": 0,
                "buyEligible": null,
                "porchBox": null,
                "startupStep": null,
                "createDate": null,
                "firstDeliveryDate": null,
                "aspNetUserId": null,
                "routeId": null,
                "routeNumber": null,
                "incompleteCustomerSignup": false,
                "localCutoff": "",
                "newStartCollectionId": null,
                "referralProgram": {
                    "rewardsAvailable": 0
                }
            };
        }

        function LoadDataLocal() {
            var self = this;
            self.mycust = data;
            self.custId = data.id;

            if (data.order && data.order[0] && angular.isDefined(data.order[0].orderTotal)) {
                self.datacontext.order.setOrderTotals(data.order[0].orderTotal);
            }
            self.custId = data.id;
            self.isWorking = false;
            self.mycust = data;
            self.custStep = self.mycust.startupStep;
            self.int_custStep = parseInt(self.custStep);
            self._areItemsLoaded(true);
            self.isLoggedIn = true;
            self.customerInitialized = false;
            return data;
        }

        function _getCustId() {
            var self = this;
            if (angular.isDefined(self.custId)) {
                if (self.custId !== null) {
                    return self.custId;
                }
            }

            var custId = self.$cookies.get("custId");

            if (custId && custId != "undefined" && custId > 0) {
                self.custId = custId;
                return self.custId;
            }

            //tid = "" + angular.isObject(self.$cookies.get("custId")) ? self.$cookies.get("custId") : "";
            //if (angular.isObject(self.$cookies.get("custId"))) {
            //    self.custId = self.$cookies.get("custId");
            //    return self.custId;
            //}

            //tid = "" + self.getItemsLoaded("custId");
            //if (angular.isDefined(self.getItemsLoaded("custId"))) {
            //    self.custId = self.getItemsLoaded("custId");
            //    return self.custId;
            //}

            //tid = "" + self.getQParm("custId");
            //if (tid.length !== 0) {
            //    self.custId = tid;
            //    return self.custId;
            //}

            return null;
        }

        function _getCustomerData() {
            var self = this;

            var tempdc = undefined;
            if (!angular.isDefined(tempdc))
                self.mycust = "";
            else
                self.mycust = tempdc;
            return;
        }
    }

    var saving = false;

    function getCustomerWithOrder(IsAuth) {
        var self = this;

        var defer = self.$q.defer();
        var retry = 0;
        var url = "api/customers/PostGetMyCustomerInfo";

        var custId = self.getCustId();// self.$cookies.get("custId");

        if (!IsAuth) {
            if (self.datacontext.isNewCustomer || custId) {
                url += "?id=" + custId;
            }
            else {
                self.customerInitialized = null;
                self.$cookies.remove('custId');
                self.mycust = self.getEmptyCust();
                self.mycust.startupStep = 0;
                self.custStep = 0;
                self.int_custStep = 0;
            }
        }

        self.$http.post(url, self.as400Refresh)
            .success(function (data) {
                self.as400Refresh = false;
                this.isLoaded = true;
                if (data === null) {
                    self.customerInitialized = null;
                    self.$cookies.remove('custId');
                    self.mycust = self.getEmptyCust();
                    self.mycust.startupStep = 1;
                    self.custStep = self.mycust.startupStep;
                    self.int_custStep = parseInt(self.custStep);
                } else {
                    //
                    //	this is where the initial load is returned.
                    //

                    self.mycust = data;
                    //The time for their cutoff on the day of their order cutoff
                    self.mycust.localCutoff = moment.tz(self.mycust.branchCutoff, "America/Chicago").tz(moment.tz.guess()).format('LT z');
                    
                    var newCustomerProductPreference = {}
                    for (let i = 0; i < self.mycust.customerProductPreference.length; i++) {
                        newCustomerProductPreference[self.mycust.customerProductPreference[i].productNumber] =
                            self.mycust.customerProductPreference[i].allowSubstitutions
                    }
                    
                    self.mycust.customerProductPreference = newCustomerProductPreference;

                    if (custId && self.mycust.incompleteCustomerSignup) {
                        self.datacontext.isNewCustomer = true;
                        //??self.datacontext.isReturning = ??;
                    }

                    if (self.datacontext.products.entityItems.length <= 0) {
                        // the product data is not ready so this can wait
                        self.selfinitialDatadefered = true;
                    }
                    else {
                        self.loadOrderData();
                    }
                    self.custId = data.id;
                }
                defer.resolve(self.mycust);
                return;
            })
            .error(function (error) {
                //console.log(error)
                self.isWorking = false;
                defer.reject(error);
                return;
            });
        return defer.promise;
    }

    function InsSignupNoComplete() {
        var self = this;
        var retry = 0;
        var url = "api/customers/InsSignupNoComplete";

        return self.$http.post(url, self.mycust)
            .success(function (data) {
                data = angular.isArray(data) ? data[0] : data;
                data = data.data ? data.data : data;
                self.mycust.serviceStartDate = data.serviceStartDate;
                self.mycust.newCustomerTrackingId = data.newCustomerTrackingId;
                return;
            })
            .error(function (data, status, headers, config) {
                self = null;
                location.href = location.protocol + '//' + window.location.host + '/error/checkouterror.html';
                return;
            });
    }

    function postCustomerFeedback(feedback) {
        var self = this;
        var retry = 0;
        var url = "api/UserFeedback/UserFeedback";


        return self.$http.post(url, feedback)
            .success(function (data) {
                return true;
            })
            .error(function (data, status, headers, config) {
                return false;
            });
    }

    function postProductFeedback(productId, rating) {
        var self = this;
        var retry = 0;
        var url = "api/UserFeedback/AddCustomerProductLike";

        var feedback = {
            productId: productId,
            customerId: self.mycust.id,
            rating: rating
        }
        return self.$http.post(url, feedback)
            .success(function (data) {
                return true;
            })
            .error(function (data, status, headers, config) {
                return false;
            });
    }

    function getProductFeedback(productId) {
        var self = this;
        var defer = self.$q.defer();

        var url = "api/UserFeedback/GetCustomerProductLike/" + productId + "/" + self.mycust.id;

        self.$http.get(url)
            .success(function (data) {
                defer.resolve(data);
                return;
            })
            .error(function (error) {
                defer.reject(error);
                return;
            });
        return defer.promise;
    }

    function updateStepNumber() {
        this.InsSignupNoComplete();
    }


    function InsSignupNoDelivery() {
        var self = this;
        self.selfinitialDatadefered = false;
        var deferred = self.$q.defer();
        var retry = 0;
        var url = "api/customers/InsSignupNoDelivery";

        return self.$http.post(url, self.mycust)
            .success(function (data) {
                data = angular.isArray(data) ? data[0] : data;
                data = data.data ? data.data : data;
                self.mycust.newCustomerTrackingId = data.newCustomerTrackingId;
                deferred.resolve(self.mycust);
            })
            .error(function (data, status, headers, config) {
                deferred.reject("Test customer address error.");
            });
    }

    function UpdateSelectedProductCollection(customerId, selectedProductCollection) {
        var self = this;
        var retry = 0;
        var url = "api/customers/UpdateCustomerProductCollection";

        return self.$http.post(url, selectedProductCollection)
            .success(function (data) {
                return true;
            })
            .error(function (data, status, headers, config) {
                return false;
            });
    }

    function loadOrderData() {
        var self = this;
        var data = self.mycust;

        if (self.mycust)
            if (!(self.mycust.order)) self.mycust.order = [];

        if (data.order.length == 0) return;
        if (angular.isDefined(data.order[0].orderTotal)) {
            //
            //
            //
            self.datacontext.order.setOrderTotals(data.order[0].orderTotal);
        }

        self.isWorking = false;
        self.custStep = self.mycust.startupStep;
        self.int_custStep = parseInt(self.custStep);
        self._areItemsLoaded(true);
        self.isLoggedIn = true;
        self.customerInitialized = false;
        self.selfinitialDatadefered = false;
    }

    function _TestMyCustomerAddress() {
        //
        //	This sends the new customer first page data to the server for
        //	verification and first persistence point.
        //

        var self = this;
        var defer = self.$q.defer();

        //console.log(self.mycust);

        var retCustomer =
        {
            address1: self.mycust.address1,
            address2: self.mycust.address2,
            eMail: self.mycust.eMail,
            zip: self.mycust.zip,
            customerNumber: self.mycust.customerNumber,
            isReturning: self.mycust.isReturning,
            stepNumber: "1",
            isCurator: self.mycust.isCurator,
            salesId: self.$cookies.get("salesId"),
            referralCode: self.mycust.referralCode
        };

        //
        //  this will test and save the initial customer data
        //	to the customer table
        //
        if (self.salesAdding) {
            retCustomer.isSalesAdding = true;
        }

        self.$http.post("api/customers/AddressCheck", retCustomer)
            .success(function (data) {
                data = angular.isArray(data) ? data[0] : data;
                data = data.data ? data.data : data;

                if (data.message != "") {
                    defer.resolve(data);

                    if (data.message == "noService") {
                        // GOOGLE ANALYTICS (Force page send for the sign-up process)
                        var url = 'home-delivery/sign-up/noService';
                        ga('set', 'page', url);
                        ga('send', 'pageview');
                    }

                    return;
                }
                //initializeCustomer(data.newCustomerUi); //todo: check this
                //////////////////////////////////////////////////////////////////////////////////
                data = data.newCustomerUi;
                self.mycust = data;
                //self.setShowOneTimePopup(true);

                self.custStep = angular.isDefined(self.mycust.startupStep) ? self.mycust.startupStep : '1';

                self.mycust.stepNumber = self.custStep;
                if ((self.mycust) && (self.mycust.order)) {
                    self.datacontext.order.processOrderUpdateFromServer(self.mycust.order);
                }

                self.int_custStep = parseInt(self.custStep);
                self.customerInitialized = true;

                self.$cookies.put('custId', data.id);
                //////////////////////////////////////////////////////////////////////////////////

                defer.resolve(self.mycust);
            })
            .error(function (data, status, headers, config) {
                defer.reject(data);
            });
        // });
        return defer.promise;
    }

    function _processAddress(addressResponse) {
        var self = this;
        var defer = self.$q.defer();

        //console.log(self.mycust)

        var retCustomer =
        {
            address1: self.mycust.address1,
            address2: self.mycust.address2,
            zip: self.mycust.zip,
            eMail: self.mycust.eMail,
            stepNumber: "1",
            serviceStartDate: (addressResponse && addressResponse.route) ? addressResponse.route.serviceStartDate : null,
            addressResponse: addressResponse,
            porchBoxNumber: (addressResponse && addressResponse.route) ? addressResponse.route.productNumber : null,
            porchBoxDiscountNumber: (addressResponse && addressResponse.route) ? addressResponse.route.discountProductNumber : null,
            porchBoxPrice: (addressResponse && addressResponse.route) ? addressResponse.route.productPrice : null,
            porchBoxDiscountPrice: (addressResponse && addressResponse.route) ? addressResponse.route.discountProductPrice : null,
            customerNumber: (self.mycust.customerNumber) ? self.mycust.customerNumber : null,
            isReturning: self.mycust.isReturning,
            isCurator: self.mycust.isCurator,
            referralCode: self.mycust.referralCode
        };

        if (self.salesAdding) {
            retCustomer.isSalesAdding = true;
        }

        if (self.customerNumber) {
            retCustomer.customerNumber = self.customerNumber;
        }

        //retCustomer.isReturning = self.isReturning;

        self.$http.post("api/customers/NewCustomer_LookUp", retCustomer)
            .success(function (data) {
                data = angular.isArray(data) ? data[0] : data;
                data = data.data ? data.data : data;

                if (data.message != "") {
                    defer.resolve(data);
                    return;
                }
                //initializeCustomer(data);
                //console.log(data);

                /////////////////////////////////////////////////////////////////////////////////////////////////////////
                self.mycust = data;
                //self.setShowOneTimePopup(true);

                self.custStep = angular.isDefined(self.mycust.startupStep) ? self.mycust.startupStep : 1;

                self.mycust.stepNumber = self.custStep;
                if ((self.mycust) && (self.mycust.order)) {
                    self.datacontext.order.processOrderUpdateFromServer(self.mycust.order);
                }

                self.int_custStep = parseInt(self.custStep);
                self.customerInitialized = true;

                self.$cookies.put('custId', data.id);

                ////////////////////////////////////////////////////////////////////////////////////////////////////

                defer.resolve(self.mycust);
            })
            .error(function (data, status, headers, config) {
                defer.reject(data);
            });
        // });
        return defer.promise;
    }

    function initializeCustomer(data) {
        var self = this;
        self.mycust = data;
        //self.setShowOneTimePopup(true);

        self.custStep = angular.isDefined(self.mycust.startupStep) ? self.mycust.startupStep : '1';

        self.mycust.stepNumber = self.custStep;
        if ((self.mycust) && (self.mycust.order)) {
            self.datacontext.order.processOrderUpdateFromServer(self.mycust.order);
        }

        self.int_custStep = parseInt(self.custStep);
        self.customerInitialized = true;

        self.$cookies.put('custId', data.id);
    }

    function getselectedName() {
        var self = this;
        if (self.prodSelected.length > 0) {
            var obj = self.prodSelected[0].title;
            return obj;
        }
        return "not found";
    }

    function _getNameList(id) {
        var self = this;
        var defer = self.$q.defer();

        var data = {
            id: parseInt(id)
        };

        self.$http.post("api/customers/GetNameList", data)
            .success(function (response) {
                if (response.success) {
                    defer.resolve(response.names);
                } else {
                    defer.reject(response.message);
                }
            })
            .error(function (response, status, headers, config) {
                console.log(response);
                defer.reject(response);
            });

        return defer.promise;
    }

    function confirmCustomerName(id, name) {
        var self = this;
        var defer = self.$q.defer();

        var data = {
            id: id,
            name: name
        };

        self.$http.post("api/customers/ConfirmCustomerName", data)
            .success(function (response) {
                defer.resolve(response.match);
            })
            .error(function (response, status, headers, config) {
                console.log(response);
                defer.reject(response);
            });

        return defer.promise;
    }

    function _getSalesPerson(id) {
        var self = this;
        var defer = self.$q.defer();

        if (!id) {
            var expireDate = new Date();
            expireDate.setDate(expireDate.getDate() + 14);

            if (self.$state.params.salesId && self.$state.params.salesId > 0) {
                id = $state.params.salesId;
                self.$cookies.put("salesId", self.salesId, { 'expires': expireDate });
            }
            else if (self.$state.params.sid && self.$state.params.sid > 0) {
                id = self.$state.params.sid;
                self.$cookies.put("salesId", self.salesId, { 'expires': expireDate });
            }
            else {
                id = self.$cookies.get("salesId");
            }
        }
        var sp = { id: null, name: null, message: null, invalid: false };

        if (id) {
            self.$http.get("api/customers/getSalesPersonById/" + id)
                .success(function (response) {
                    if (response) {
                        sp.id = response.id;
                        sp.name = response.name;
                        sp.message = '';
                        sp.invalid = false;
                        sp.tempId = sp.id;

                        var expireDate = new Date();
                        expireDate.setDate(expireDate.getDate() + 14);
                        self.$cookies.put("salesId", sp.id, { 'expires': expireDate });
                    }
                    else {
                        sp.id = null;
                        sp.name = '';
                        sp.message = id + ' is not a valid Sales Person ID.';
                        sp.invalid = true;
                        sp.tempId = id;
                    }
                    defer.resolve(sp);
                })
                .error(function (response, status, headers, config) {
                    console.log(response);
                    defer.reject(response);
                });
        } else {
            defer.resolve(sp);
        }
        return defer.promise;
    }

})();
;
(function () {
    var serviceId = 'repository.customer_source';
    angular.module('app-hd').factory(serviceId,
        ['common', 'repository.abstract', RepositoryCustomerSource]);

    function RepositoryCustomerSource(common, abstractRepository) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var self = this;
        function Ctor() {
            this.entityName = 'customersourcetype';
            this.entityItems = [];
            this.getPartialsUrl = 'api/Customers/GetCustomerSourceTypes';
            this.primeCustomerSourceTypes = primeCustomerSourceTypes;
            //this.getCustomerSourceTypes = getCustomerSourceTypes;
        }

        abstractRepository.extend(Ctor);

        return Ctor;

        function primeCustomerSourceTypes() {
            return this.getPartials();
        }
    };
})();;
(function () {
    "use strict";

    var serviceId = "repository.order";
    angular.module("app-hd").factory(serviceId, ["$filter", "common", "repository.abstract", "authService", repositoryOrder]);

    function repositoryOrder($filter, common, abstractRepository, authService) {
        var vm = this;
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var IsAuth = authService.authentication.isAuth;

        function Ctor() {
            this.entityName = "order";
            this.isDirty = false;
            this.isRunning = false;
            this.firstCall = true;
            this.ordersLoaded = false;
            this.orderHistoryData = null;
            this.orderTotals = {};
            this.isPostingOrder = false;
            this.orderItemsSendingToServer = [];

            this.GetNextOrderItemsCount = _getNextOrderItemsCount;
            this.GetStandingOrderItemsCount = _getStandingOrderItemsCount;
            this.GetStandingDeliveryTotals = getStandingDeliveryTotals;
            this.GetNextDeliveryTotals = getNextDeliveryTotals;

            this.PostOrderDetailUpdate = _PostOrderDetailUpdate;
            this.PushOrderToAS400 = _PushOrderToAS400;
            this.AuthInfo = authService.authentication;
            this.ResetOrderItems = _ResetOrderItems;
            this.getOrderHistory = _getOrderHistory;
            this.AddOrderDetailUpdate = _AddOrderDetailUpdate;
            this.setOrderTotals = _setOrderTotals;
            this.getOrderItems = _getOrderItems;
            this.getProduceItems = _getProduceItems;
            this.processOrderUpdateFromServer = processOrderUpdateFromServer;
            this.reloadOrder = _reloadOrder;
            this.updateSuspension = _updateSuspension;
            this.removeSuspension = _removeSuspension;
            this.updateDeliveryDate = _updateDeliveryDate;
            this.setCustomerProductPreferences = setCustomerProductPreferences;
            this.editsMadeAfterLastCheckout = _editsMadeAfterLastCheckout;
        }

        abstractRepository.extend(Ctor);

        var $q = common.$q;
        var $http = common.$http;

        return Ctor;
        var emptyTotal = {
            "discount": 0,
            "deliveryCharge": 0,
            "deliveryChargeCredit": 0,
            "referralReward": 0,
            "subtotal": 0,
            "total": 0
        }
        function getNextDeliveryTotals() {
            var self = this;
            return (self.orderTotals)
                && (self.orderTotals.nextTotals)
                ? self.orderTotals.nextTotals :
                emptyTotal;
        }

        function getStandingDeliveryTotals() {
            var self = this;
            return (self.orderTotals)
                && (self.orderTotals.standingTotals)
                ? self.orderTotals.standingTotals
                : emptyTotal;
        }
        function _getOrderHistory(forceRefresh) {
            var self = this;
            var defer = $q.defer();
            if (self.orderHistoryData != null) {
                return self.$q.when(self.orderHistoryData);
            }

            self.$http.get('api/order/GetOrderHistory')
               .success(processHistory);
            return defer.promise;
            function processHistory(data) {
                //
                self.orderHistoryData = data;
                defer.resolve(data);
                return;
            }
        }

        function _getNextOrderItemsCount() {
            var self = this;

            var items = self.datacontext.products.entityData;

            if (angular.isArray(items[1])) items = items[1];

            var total = 0;
            var itms = items.filter(function (value) {
                return (value && value.nextQuantity && value.nextQuantity > 0);
            });
            var rtrn = [];

            itms.forEach(function (value) {
                if (value && value.price > 0)
                    total += value.nextQuantity;
            });
            return total;
        }

        function _getStandingOrderItemsCount() {
            var self = this;

            var items = self.datacontext.products.entityData;

            if (angular.isArray(items[1])) items = items[1];

            var total = 0;
            var itms = items.filter(function (value) {
                return (value && value.standingQuantity && value.standingQuantity > 0);
            });
            var rtrn = [];

            itms.forEach(function (value) {
                if (value && value.price > 0)
                    total += value.standingQuantity;
            });
            return total;
        }

        function _getOrderItems(showRemoved) {
            var self = this;

            var items = self.datacontext.products.entityData;
            if (angular.isArray(items[1])) items = items[1];

            var itms = items.filter(function (value) { return ((value && value.nextQuantity && value.nextQuantity > 0) || (value && value.standingQuantity && value.standingQuantity > 0) || (showRemoved && value && value.isRemoved) ); });

            var rtrn = [];
            itms.forEach(function (value) {
                if (value && value.price > 0)
                    rtrn.push(value);
            });

            return rtrn;
        }
        function _getProduceItems(showRemoved) {
            var self = this;

            var items = self.datacontext.products.entityData;
            if (angular.isArray(items[1])) items = items[1];

            var itms = items.filter(function (value) { return ((value && value.nextQuantity && value.nextQuantity > 0) || (value && value.standingQuantity && value.standingQuantity > 0) || (showRemoved && value && value.isRemoved)) && value.produceProd; });

            var rtrn = [];
            itms.forEach(function (value) {
                if (value && value.price > 0)
                    rtrn.push(value);
            });
            return rtrn;

        }
        function _setOrderTotals(totalsObj) {
            this.orderTotals = totalsObj;
        }

        function _ResetOrderItems() {
            var self = this;

            var odrItems = self.datacontext.products.entityData;
            //self.getOrderItems();
            odrItems.forEach(function (value) {
                if (value) {
                    value.standingQuantity = 0;
                    value.nextQuantity = 0;
                    value['changed'] = false;
                }
            });

            var items = self.getOrderItems();
            var x = items.length;
        }

        function _AddOrderDetailUpdate(productId, standingQuantity, nextQuantity) {
            //
            //  this is executed anytime customer changes an order line item amount.
            //
            var self = this;

            var detailitems = [{
                productId: productId,
                standingQuantity: angular.isUndefined(standingQuantity) ? 0 : standingQuantity,
                nextQuantity: angular.isUndefined(nextQuantity) ? 0 : nextQuantity
            }];

            self.PostOrderDetailUpdate(detailitems);
        }

        function _PostOrderDetailUpdate(orderDetailItems) {
            //
            //  this is executed anytime customer changes an order line item amount.
            //  it is also used to refresh the order data  it does this with empty array
            //
            var deferred = $q.defer();

            var self = this;
            if (!orderDetailItems) orderDetailItems = [];
            if (!angular.isArray(orderDetailItems)) orderDetailItems = [orderDetailItems];
            var itms = self.datacontext.products.entityItems;
            var dataitems = self.datacontext.products.entityData;
            orderDetailItems.forEach(function (item) {
                //TODO: check for product not found locally
                var existingItem = itms[item.productId];

                if (!existingItem) {
                    // next check the nonindexed data for the item manually entered
                    existingItem = dataitems.filter(function (value) { return (value.productId == item.productId); });
                    existingItem['changed'] = true;
                }
                existingItem.isRemoved = item.isRemoved;
            });
            // //  }

            if (self.isPostingOrder) {

                deferred.resolve();
                return deferred.promise;
            }
            var orderDetailBeforeSend = self.getOrderItems();

            //
            //  make before array with only the prodids
            //

            self.orderItemsSendingToServer = [];
            orderDetailBeforeSend.forEach(function (product) {
                self.orderItemsSendingToServer.push(product.productId);
            });
            var detailitems = [];
            if (angular.isArray(orderDetailItems))
                orderDetailItems.forEach(function (value) {
                    var detailitem = value ? {
                        productId: angular.isUndefined(value.productId) ? value.id : value.productId,
                        standingQuantity: value.standingQuantity,
                        nextQuantity: angular.isUndefined(value.nextQuantity) ? 0 : value.nextQuantity,
                        updatedOn: angular.isUndefined(value.updatedOn) ? new Date() : value.updatedOn,
                        updateType: angular.isUndefined(value.updateType) ? 4 : value.updateType
                    } : null;
                    if (detailitem) detailitems.push(detailitem);
                });
            else {
                detailitems = [
                    orderDetailItems ? { 
                        productId: angular.isUndefined(orderDetailItems.productId) ? orderDetailItems.id : orderDetailItems.productId,
                        standingQuantity: orderDetailItems.standingQuantity,
                        nextQuantity: angular.isUndefined(orderDetailItems.nextQuantity) ? 0 : orderDetailItems.nextQuantity,
                        updatedOn: angular.isUndefined(value.updatedOn) ? new Date() : value.updatedOn,
                        updateType: angular.isUndefined(value.updateType) ? 4 : value.updateType
                    } : null
                ]
            }
            var url = "api/orderDetail/UpdateOrderDetails?pc=" + self.datacontext.cust.mycust.price_schedule;
            if (!self.datacontext.cust.mycust || !self.datacontext.cust.mycust.id || !self.datacontext.cust.mycust.price_schedule) {
                deferred.resolve();
                return deferred.promise;
            }
            if (!authService.authentication.isAuth && !self.datacontext.isNewCustomer) {
                deferred.resolve();
                return deferred.promise;
            }
            this.isPostingOrder = true;

            if (self.datacontext.isNewCustomer) {
                var method = (detailitems[0]) ? 'UpdateOrderDetailsAsNewCustomer' : 'RefreshOrderDetailsAsNewCustomer';
                url = "api/orderDetail/" + method + "?pc=" + self.datacontext.cust.mycust.price_schedule + "&id=" + self.datacontext.cust.mycust.id + "&step=" + self.datacontext.cust.mycust.startupStep;
            }
            
            if (self.datacontext.cust.mycust.scheduledDeliveryOffer)
            {
                url += "&scheduled-offer=" + self.datacontext.cust.mycust.scheduledDeliveryOffer;
            }

            // set the changed flag on the items being sent to the server to false
            // this will allow tracking for items that are changed while existing
            // order is being processed on the server
            detailitems.forEach(function (item) {
                if (itms[item.productId]) itms[item.productId]['changed'] = false;
            });


            self.$http.post(url, detailitems).then(
                function (result) {
                    var nextReferralReward = result.data[0].orderTotal.nextTotals.referralReward;

                    // when true refreshes the referral rewards available using API call
                    var refreshRewardAvailable = false;
                    if (self.orderTotals && !self.datacontext.isNewCustomer) {
                        var currentReferralReward = self.orderTotals.nextTotals.referralReward;
                        refreshRewardAvailable = nextReferralReward !== currentReferralReward;
                    }

                    self.processOrderUpdateFromServer(result, self);

                    if (refreshRewardAvailable) {
                        return self.datacontext.cust.updateReferralRewardsAvailable();
                    }

                    adjustCurrentLastModifiedTime(self);

                }, function (result) {
                    self.isPostingOrder = false;
                    reloadOrder(self);
                    deferred.reject(result);
                    return "error"
                }
            ).then(function (result) {
                if (result !== "error")
                    deferred.resolve(result);
            });

            return deferred.promise;
        }
        function adjustCurrentLastModifiedTime(self) {
            var url = "api/order/UpdateLastUpdatedTime"; 
            $http.get(url).then(function (result) {
                self.datacontext.cust.mycust.orderHeaderUpdatedOn = result.data;
            });
        }
        function _editsMadeAfterLastCheckout() {
            var self = this;
            var url = "api/order/EditsMadeAfterLastCheckout";
            return $http.get(url).then(function (result) {
               self.datacontext.cust.mycust.editsMadeAfterLastCheckout = result.data;
            });
        }
        function _reloadOrder() {
            reloadOrder(this);
        }

        function reloadOrder(self) {
            var url = "api/orderDetail/GetOrder?pc=" + self.datacontext.cust.mycust.price_schedule;
            if (self.datacontext.isNewCustomer) {
                url += "&id=" + self.datacontext.cust.mycust.id;
            }

            self.$http.post(url).then(
                function (result) {
                    self.datacontext.cust.mycust.orderHeaderUpdatedOn = result.data[0].updatedOn;
                    self.processOrderUpdateFromServer(result, self);
                    return result.data[0];
                }, function (result) {
                }
            );
        }

        function processOrderUpdateFromServer(data, self) {
            if (!(self)) self = this;
            if (data.length == 0) {
                self.ResetOrderItems();
                return;
            };

            data = (data.data) ? data.data : data;
            data = angular.isArray(data) ? data[0] : data;
            //
            //  this method is executed when the server has returned order information
            var indexedProducts = self.datacontext.products.entityItems;
            var noIndexedProducts = self.datacontext.products.entityData;
            if (angular.isDefined(data.orderTotal)) {
                self.setOrderTotals(data.orderTotal);
            }
            self.isDirty = true;

            //  if the data being returned was not from
            // _PostOrderDetailUpdate all the local order information should be reset
            if (self.orderItemsSendingToServer.length == 0) {
                self.ResetOrderItems();
            }

            var pd = data.orderDetail;

            //  the next statement checks to see if products that currently have quantities
            //  were not returned from the server (i.e. server side rules removed item)
            self.orderItemsSendingToServer.forEach(function (bfrProdId, key) {
                if (data.orderDetail != null) {
                    var foundId = data.orderDetail.filter(function (item) { return (bfrProdId == item.productId); });
                    if (foundId.length == 0) { // not found in products returned
                        // set the local quantities to 0 but only if the changed flag is not set
                        if (!(indexedProducts[bfrProdId]['changed'])) {
                            indexedProducts[bfrProdId].nextQuantity = 0;
                            indexedProducts[bfrProdId].standingQuantity = 0;
                            indexedProducts[bfrProdId].nextTotal = 0;
                        }
                    }
                }
            });

            //
            //	the next section adds or updates order detail
            //	items

            var orderdetail = data.orderDetail;
            if (orderdetail != null) {
                orderdetail.forEach(function (orderLineItem) {
                    var existingItem = indexedProducts[orderLineItem.productId];
                    if (existingItem) {
                        // if the items has not been changed since it was sent to the server
                        // update the quantity to the quantity returned from server
                        if (!(existingItem['changed'])) {
                            existingItem.nextQuantity = orderLineItem.nextQuantity;
                            existingItem.standingQuantity = orderLineItem.standingQuantity;
                            existingItem.nextTotal = orderLineItem.nextTotal;
                        }
                    }
                });
            }

            //  the next section checks for items that have been changed while processing
            //  the order items.  If any have a changed flag then restart this method from the top
            var ChangedItems = noIndexedProducts.filter(function (value) { return (value && value.changed); });

            self.isPostingOrder = false;
            if (ChangedItems.length > 0) {
                self.PostOrderDetailUpdate(ChangedItems);
            }
        }

        function setCustomerProductPreferences(data, customerNumber) {
            var url = "api/Order/SetCustomerProductPreferences"
            var data = { customerNumber: customerNumber, AllowSubstitutionsByProductNumber: data }
            this.$http.post(url, data).then(function (result) {
            })
        }

        function _PushOrderToAS400() {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //
            var deferred = $q.defer();

            var self = this;
            if (self.isRunning) return;
            self.entityItems = self.datacontext.products.entityItems;
            self.isRunning = true;

            var orderTotals = self.datacontext.order.orderTotals.nextTotals
            var customer = self.datacontext.cust.mycust;

            var gaTransaction = null;
            if (customer.customerNumber && customer.nextDeliveryDate) {
                var date = new Date(customer.nextDeliveryDate);
                gaTransaction = {
                    id: "" + customer.customerNumber + "-" + date.getFullYear() + (date.getMonth() + 1) + date.getDate(),
                    affiliation: "Oberweis Dairy",
                    revenue: orderTotals.subtotal,
                    shipping: orderTotals.deliveryCharge,
                    tax: orderTotals.tax
                };
            }
            
            var url = "api/order/CommitOrder";
            
            if (self.datacontext.cust.mycust.scheduledDeliveryOffer)
            {
                url += "?scheduled-offer=" + self.datacontext.cust.mycust.scheduledDeliveryOffer;
            }

            return self.$http.post(url, self.datacontext.cust.mycust)
                .success(_PushOrderToAS400Success)
                .error(AS400UpdateError);

            function _PushOrderToAS400Success(data) {
                self.isRunning = false;
                self.isDirty = false;
                self.getorderPartialsMappedLoaded = true;

                if (gaTransaction) {
                    ga('require', 'ecommerce');
                    ga('ecommerce:addTransaction', gaTransaction);
                    ga('ecommerce:send');
                }

                deferred.resolve(data);
            }
            function AS400UpdateError(data) {
                self.isRunning = false;
                deferred.reject(data);
            }
            return deferred.promise;
        }

        function _removeSuspension() {

            var self = this;

            self.datacontext.cust.mycust.numberOfDeliveriesToSuspend = 0;
            self.datacontext.cust.mycust.deliveriesBeforeSuspension = 0;

            return self.updateSuspension();

        }

        function _updateSuspension() {

            var self = this;

            var deferred = $q.defer();

            var request = {
                Skip: self.datacontext.cust.mycust.numberOfDeliveriesToSuspend,
                Make: self.datacontext.cust.mycust.deliveriesBeforeSuspension
            };

            $http.post("api/order/skip", request)
                .then(function (result) {

                    self.datacontext.cust.mycust.nextDeliveryDate = $filter('date')(moment(result.data.nextDelivery).toDate(), 'EEEE, MMMM d, y');
                    self.datacontext.cust.mycust.futureDeliveryDate = $filter('date')(moment(result.data.futureDeliveryDate).toDate(), 'EEEE, MMMM d, y');
                    self.datacontext.cust.mycust.userSuspended = self.datacontext.cust.mycust.numberOfDeliveriesToSuspend > 0
                        && self.datacontext.cust.mycust.deliveriesBeforeSuspension == 0;

                    if (self.datacontext.cust.mycust.userSuspended) {
                        if (self.datacontext.cust.mycust != null && self.datacontext.cust.mycust.lockUser == false) {
                            // I only want to change the reason if a more important reason doesn't prevail (e.g. delivery date lockout)
                            if (self.datacontext.cust.mycust.cartItemDisabledReason == null || self.datacontext.cust.mycust.cartItemDisabledReason == '') {
                                self.datacontext.cust.mycust.cartItemDisabledReason = "Disabled due to suspended delivery.";
                            }
                        }
                    }
                    else {
                        self.datacontext.cust.mycust.cartItemDisabledReason = '';
                    }

                    common.$broadcast('updateDeliveryDate', "test");

                    deferred.resolve(result);
                }, function (result) {
                    deferred.reject(result);
                });

            return deferred.promise;
        }

        function _updateDeliveryDate() {
            var self = this;
            var defer = $q.defer();
            var url = "api/order/updateDeliveryDate";
            $http.post(url, self.datacontext.cust.mycust).then(function () { defer.resolve(); }, function () { defer.reject(); });
            return defer.promise;
        }
    }
})();
;
(function () {

    //TODO: Blago check to see if we can delete this file.

    var serviceId = 'repository.productcategory';
    angular.module('app-hd').factory(serviceId,
        ['common', 'datacontext', 'repository.abstract', repositoryproductcategory]);

    function repositoryproductcategory(common, datacontext, abstractRepository) {
        var vm = this;
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var $q = common.$q;

        function Ctor() {
            this.entityName = 'productcategory';
            this.productCategoryRawArray = [];
        //TODO: figure out which one is used
            this.productCategoryIndexedByCategoryId = [];
            this.productCategoryIndexedByProductId = [];

            this.buildCatalogProductInxed = _buildCatalogProductIndexed;
            this.getProductCategoryByCategoryId = getProductCategoryByCategoryId;
            //
            this.haveAllDataPromise = undefined;
            this.loadAllData = _loadAllData;
            this.UpdateSaveCategoryProductData = UpdateSaveCategoryProductData;
            this.getProductCategoryByCategoryId = getProductCategoryByCategoryId;
            this.getRetailCategoryTree = _getRetailCategoryTree;
            this.getDairyStoreCategoryTree = _getDairyStoreCategoryTree;
        }


        abstractRepository.extend(Ctor);
        return Ctor;

        function deletePCEntery(data) {
            // the returned array has 3 elements the first is indexed by category each index contains an  array of products linked
            var self = this;
            var array_of_product = [];
            data[1].forEach(function (dv) {

                array_of_product.push(_.object(dv[0], dv[1]));
            });

            self.productCategoryIndexedByProductId = _.object(data[0], array_of_product);
        }

        function _buildCatalogProductIndexed(data) {
            // the returned array has 3 elements the first is indexed by category each index contains an  array of products linked
            var self = this;
            var array_of_product = [];
            data[1].forEach(function (dv) {

                array_of_product.push(_.object(dv[0], dv[1]));
            });

            self.productCategoryIndexedByProductId = _.object(data[0], array_of_product);
        }

        function UpdateSaveCategoryProductData() {

            var self = this;
            var defer = $q.defer();
            var url = 'api/products/putproductCategorys';
            var cpdata = self.productCategoryIndexedByProductId[datacontext.category.selectedCategory.id];

            var updateAry = [];
            _.each(cpdata, function (item) {

                var newObj = {
                    "productNumber": item.productNumber,
                    "categoryId": item.categoryId,
                    "endDate":item.endDate,
                    "startDate":item.startDate
                }
                updateAry.push(newObj);
            });

            self.$http.put(url, updateAry).success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            }
        }

        function getProductCategoryByCategoryId(catId) {
            var self = this;
            return self.productCategoryIndexedByProductId[catId];
        }


        function _loadAllData() {
            //  This function obtains all category product links from the server and builds indexed arrays

            var self = this;
            if (self.haveAllDataPromise) return;
            self.haveAllDataPromise = $q.defer();


            var cacheKey = 'RepositoryProductCategoryData';

            var url = "api/products/getproductCategorys";
            self.$http.get(url).success(querySucceeded);
            return self.haveAllDataPromise.promise;

            function querySucceeded(data) {
                self.productCategoryRawArray = data;
                $q.all([
                    self.buildCatalogProductInxed(data)
                ]).then(function () { self.haveAllDataPromise.resolve("Success"); });
            }
        }


        function _getRetailCategoryTree() {
            var self = this;
            var defer = $q.defer();

            var url = 'api/retail/GetRetailCategoryTree';

            self.$http.get(url).then(function (data) {
                defer.resolve(data);
            }, function () {
                defer.reject();
            });
            return defer.promise;

        }
        function _getDairyStoreCategoryTree() {
            var self = this;
            var defer = $q.defer();

            var url = 'api/retail/GetDairyStoreCategoryTree';

            self.$http.get(url).then(function (data) {
                defer.resolve(data);
            }, function () {
                defer.reject();
            });
            return defer.promise;

        }
    }



})();;
(function () {
    "use strict";

    var serviceId = "repository.products";
    angular.module("app-hd").factory(serviceId, ["$http", "common", "repository.abstract", "datacontext", "authService", RepositoryProducts]);

    function RepositoryProducts($http, common, abstractRepository, datacontext, authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);

        function Ctor() {
            this.entityName = "product";

            this.entityData = [];
            this.entityItems = [];
            this.URLCatName = "";
            this.selectedName = "";
            this.selectedProduct = {};
            this.dataLoaded = false;
            this.isLoaded = false;

            this.productsAll = [];
            this.prodSelected = [];
            this.getProductPartialsForLocalInitialization = getProductPartialsForLocalInitialization;
            this.getProductPartialsForPriceCode = getProductPartialsForPriceCode;
            this.getselectedName = getselectedName;
            this.saveitems = saveitems;
            this.showOutOfStock = showOutOfStock;
            this.showOverlayBanner = showOverlayBanner;
            this.allowOrderEdits = allowOrderEdits;
            this.getProductsInStandardCart = getProductsInStandardCart;
            this.getProductsInNextOrderCart = getProductsInNextOrderCart;
            this.searchText = '';
            this.clearSearch = clearSearch;
            this.loadProductData = loadProductData;
            this.AdminProducts = [];
            this.getAdminDataShortList = getAdminDataShortList;

            this.getAdminData = getAdminData;
            this.putAdminData = putAdminData;

            this.getAdminNutData = getAdminNutData;
            this.putAdminNutData = putAdminNutData;

            this.getAdminNutDailyPctProduct = getAdminNutDailyPctProduct;
            this.getAdminNutDailyPctComponents = getAdminNutDailyPctComponents;
            this.DailyPctComponents = [];

            this.getAdminNutDailyPct = getAdminNutDailyPct;
            this.putAdminNutDailyPct = putAdminNutDailyPct;

            this.cacheDateTime = null;
            this.getProductDetails = getProductDetails;
            this.addRetailProductDetails = addRetailProductDetails;
            this.addDairyStoreProductDetails = addDairyStoreProductDetails;

            this.getFountainMenuProducts = getFountainMenuProducts;
            this.getFountainMenuProductNutrition = getFountainMenuProductNutrition;
            this.reset = reset;
            this.loadProductAttributes = loadProductAttributes;
            this.pairProductAttributes = pairProductAttributes;
        }

        var $q = common.$q;
        abstractRepository.extend(Ctor);
        return Ctor;
        function reset() {
            this.entityData = [];
            this.entityItems = [];
            this.URLCatName = "";
            this.selectedName = "";
            this.selectedProduct = {};
            this.dataLoaded = false;
            this.isLoaded = false;

            this.productsAll = [];
            this.prodSelected = [];

            this.searchText = '';

            this.AdminProducts = [];

            this.DailyPctComponents = [];

            this.cacheDateTime = null;
            this.partialsMappedLoaded = false;
        }


        function getAdminNutDailyPctComponents() {
            //
            //  this obtains the selection options for nutrition components from the server
            //  it is a large list and caching in local storage is necessary dew to page loading time
            //
            var self = this;
            var defer = $q.defer();

            if (self.DailyPctComponents.length > 0) {
                return self.$q.when(self.DailyPctComponents);
            }
            var cacheKey = 'getAdminNutDailyPctComponents';
            var data = self._areItemsCached(cacheKey);
            //if (angular.isDefined(data) && angular.isArray(data)) {
            //    self.DailyPctComponents = _.object(data[0], data[1]);
            //    return self.$q.when(self.DailyPctComponents);
            //}

            $http.get("api/Products/GetAdminNutDailyPctComponents")
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //  this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects

                self.putItemsLoaded(cacheKey, data);
                self.DailyPctComponents = data;
                defer.resolve(self.DailyPctComponents);
            };
        }

        function putAdminNutDailyPct(productData) {
            var self = this;
            var defer = $q.defer();
            $http.put("api/Products/PutAdminNutDailyPct", productData)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve();
            };
        }

        function getAdminNutDailyPctProduct(productNumber) {
            var self = this;
            var defer = $q.defer();

            $http.get("api/Products/GetAdminNutDailyPctItem?productNumber=" + productNumber)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //  this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects

                if (self.entityItems.length == 0 || self.entityData.length == 0) {
                    self.entityItems = _.object(data[0], data[1]);
                    self.entityData = data[1];

                    if (self.datacontext.cust.selfinitialDatadefered) {
                        self.datacontext.cust.loadOrderData();
                    }
                } else {
                    for (var inx = 0; inx < data[0].length; inx++) {
                        var key = data[0][inx];
                        var value = data[1][inx];
                        if (angular.isDefined(self.entityItems[key]))
                            self.entityItems[key].pnds = value.pnds;
                        // _.extend(self.entityItems[key], value.pnds);
                        else
                            self.entityItems[key] = value;
                    }
                }

                self.partialsMappedLoaded = true;
                self.dataLoaded = true;
                gettingProductpartials = false;
                defer.resolve(data);
            };
        }

        function getAdminNutDailyPct() {
            var self = this;
            var defer = $q.defer();

            $http.get("api/Products/GetAdminNutDailyPct")
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //  this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects
                self.loadProductData(data);
                defer.resolve(data);
            };
        }

        function getFountainMenuProducts() {
            var self = this;
            var defer = $q.defer();

            $http.get("api/Products/GetFountainMenuProducts")
                .success(querySucceeded)
                .error(queryError);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            };
            function queryError(e) {
                defer.reject(e);
            };
        }

        function getFountainMenuProductNutrition(productId) {
            var self = this;
            var defer = $q.defer();

            $http.get("api/Products/GetFountainMenuProductNutrition/" + productId)
                .success(querySucceeded)
                .error(queryError);
            return defer.promise;

            function querySucceeded(data) {
                defer.resolve(data);
            };
            function queryError(e) {
                defer.reject(e);
            };
        }

        function putAdminNutData(productData) {
            var self = this;
            var defer = $q.defer();
            $http.put("api/Products/PutAdminNutInfo", productData)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                self.getAdminNutData(true);
                return defer.resolve();
            };
        }

        function getAdminNutData(noCache) {
            var self = this;
            var defer = $q.defer();
            if (!noCache) {
                var cacheKey = 'getAdminNutData';
                var data = self._areItemsCached(cacheKey);
                if (angular.isDefined(data)) {
                    self.loadProductData(data);
                    return self.$q.when(self.DailyPctComponents);
                }
            }
            $http.get("api/Products/GetAdminNutInfo")
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //  this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects
                // self.putItemsLoaded(cacheKey, data);

                self.loadProductData(data);
                defer.resolve(data);
            };
        }

        function putAdminData(productData) {
            var self = this;
            var defer = $q.defer();
            $http.put("api/Products/putAdminProduct", productData)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //  this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects
                self.getAdminData(true);
                return defer.resolve();
            };
        }

        function getAdminData(forceRefresh) {
            var self = this;
            var defer = $q.defer();
            var cacheKey = 'getAdminData';

            var tableNames = 'tblPromas,ProNutritionDetails,ProductCategory,ProNutrition';
            var cachePrefix = 'admin';
            self.isTableUptoDate(tableNames, cachePrefix).then(function (isTableUptoDate_result) {
                if (!forceRefresh) {
                    // if not force refresh do the refresh if our data is out of date
                    forceRefresh = !isTableUptoDate_result;
                }
                if (!forceRefresh) {
                    var data = self._areItemsCached(cacheKey);
                    if (angular.isDefined(data)) {
                        self.loadProductData(data);
                        defer.resolve(self.entities);
                    }
                }
                $http.get("api/Products/GetAdminProducts")
                    .success(querySucceeded);

                function querySucceeded(data) {
                    //  this query worked we want to extend the indexed local object with the new data
                    //
                    // need to check if entity data is a copy of linked to actual objects

                    self.putItemsLoaded(cacheKey, data);
                    self.loadProductData(data);
                    self.AdminProducts = data[1];
                    var tblNames = tableNames.split(",");
                    tblNames.forEach(function (tblName) {
                        self.putItemsLoaded(cachePrefix + '-LastUpdate:' + tblName, Date.now());
                    });
                    defer.resolve(data);
                };
            });

            return defer.promise;
        }

        function getAdminDataShortList() {
            var self = this;
            var defer = $q.defer();
            self.getPartialsMappedFromUrl("api/Products/GetAdminProductsShortList", true)
                .then(
                    function (data) {
                        self.loadProductData(data);
                        //
                        // this query worked we want to extend the indexed local object with the new data
                        //
                        // need to check if entity data is a copy of linked to actual objects

                        self.AdminProducts = data[1];
                        defer.resolve(data);
                    });
            return defer.promise;
        }

        function getProductsInStandardCart() {
            return this.entityItems.filter(function (value) { return (value && value.standingQuantity && value.standingQuantity > 0); });
        }

        function getProductsInNextOrderCart() {
            return this.entityItems.filter(function (value) { return (value && value.nextQuantity && value.nextQuantity > 0); });
        }

        function getselectedName() {
            var self = this;
            if (self.prodSelected.length > 0) {
                var obj = self.prodSelected[0].title;
                return obj;
            }
            return "notfound";
        }

        function getProductPartialsForLocalInitialization() {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;
            if (self.partialsMappedLoaded) {
                return self.$q.when(self.entityItems);
            }
            var cacheKey = self.entityName + 'getPartialsMapped';
            var data = self._areItemsCached(cacheKey);
            if (angular.isDefined(data) && angular.isArray(data)) {
                self.entityItems = _.object(data[0], data[1]);
                self.entityData = data[1];
                //testMyArrays(self.entityItems, self.entityData);

                self.partialsMappedLoaded = true;
                self.dataLoaded = true;
            }
        }

        function addRetailProductDetails(products) {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;
            var addObjectUrl = 'api/retail/GetDetailRetailProducts';

            var defer = self.$q.defer();
            $http.get(addObjectUrl)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                var dataObj = _.object(data[0], data[1]);

                angular.forEach(dataObj, function (value) {
                    if (angular.isDefined(products[value.id]))
                        _.extend(products[value.id], value);
                    else {
                        products[value.id] = value;
                    }
                });

                defer.resolve(data);
            }
        }

        function addDairyStoreProductDetails(products) {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;
            var addObjectUrl = 'api/retail/GetDetailDairyStoreProducts';

            var defer = self.$q.defer();
            $http.get(addObjectUrl)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                var dataObj = _.object(data[0], data[1]);

                angular.forEach(dataObj, function (value) {
                    if (angular.isDefined(products[value.id]))
                        _.extend(products[value.id], value);
                    else {
                        products[value.id] = value;
                    }
                });

                defer.resolve(data);
            }
        }
        function getProductDetails(forceRefresh) {
            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;
            var addObjectUrl = 'api/products/GetDetailProducts';

            var defer = self.$q.defer();
            //var cacheKey = self.entityName + 'getPartialsMappedFromUrl';

            //var tableNames = 'tblPromas,ProNutritionDetails,ProductCategory,ProNutrition';
            //var cachePrefix = 'shop';
            //self.isTableUptoDate(tableNames, cachePrefix).then(function (isTableUptoDate_result) {
            //    if (!forceRefresh) {
            //        // if not force refresh do the refresh if our data is out of date
            //        forceRefresh = !isTableUptoDate_result;
            //    }

            //    if (!forceRefresh) {
            //        if (self.detaiIsLoaded) {
            //            return self.$q.when(self.entityItems);
            //        }

            //        var data = self._areItemsCached(cacheKey);

            //        if (angular.isDefined(data) && angular.isArray(data)) {
            //            {
            //                var dataObj = _.object(data[0], data[1]);

            //                angular.forEach(dataObj, function (value) {
            //                    if (angular.isDefined(self.entityItems[value.id]))
            //                        _.extend(self.entityItems[value.id], value);
            //                    else {
            //                        self.entityItems[value.id] = value;
            //                        self.entityData.push(value);
            //                    }
            //                });

            //                self.detaiIsLoaded = true;
            //                return self.$q.when(self.entityItems);
            //            }
            //        }
            //    }

            $http.get(addObjectUrl)
                .success(querySucceeded);
            return defer.promise;

            function querySucceeded(data) {
                //
                // this query worked we want to extend the indexed local object with the new data
                //
                // need to check if entity data is a copy of linked to actual objects

                var dataObj = _.object(data[0], data[1]);

                angular.forEach(dataObj, function (value) {
                    if (angular.isDefined(self.entityItems[value.id]))
                        _.extend(self.entityItems[value.id], value);
                    else {
                        self.entityItems[value.id] = value;
                        self.entityData.push(value);
                    }
                });

                self.detaiIsLoaded = true;
                //self.putItemsLoaded(cacheKey, data);
                //var tblNames = tableNames.split(",");
                //tblNames.forEach(function (tblName) {
                //    self.putItemsLoaded(cachePrefix + '-LastUpdate:' + tblName, Date.now());
                //});

                defer.resolve(data);
            }
            //});
        }
        var gettingProductpartials = false;
        function getProductPartialsForPriceCode(priceCode, deliveryDate, branch) {
            // var tableNames = 'tblPromas,ProductCategory';

            //
            //	the url provided must return two arrays
            //	the first is a list of keys and the second is the objects
            //	to map each to.
            //

            var self = this;

            var defer = $q.defer();
            //gettingProductpartials = true;
            //var cacheKey = self.entityName + 'getPartialsMapped';

            //var cachePrefix = 'shop';
            //self.isTableUptoDate(tableNames, cachePrefix).then(function (isTableUptoDate_result) {
            //    if (!forceRefresh) {
            //        // if not force refresh do the refresh if our data is out of date
            //        forceRefresh = !isTableUptoDate_result;
            //    }

            //    if (!forceRefresh) {
            //        var data = self._areItemsCached(cacheKey);
            //        if (angular.isDefined(data) && angular.isArray(data)) {
            //            self.loadProductData(data);
            //            self.isLoaded = true;
            //            defer.resolve("Success");
            //            return;
            //        }
            //    }

            var url = "api/Products/GetProductInformation";

            var params = [];

            if (priceCode != null) {
                params.push("priceCode=" + priceCode);
            }

            if (deliveryDate && authService.authentication.isAuth) {
                params.push("deliveryDate=" + deliveryDate);
            }

            if (branch) {
                params.push("branch=" + branch);
            }

            if (params.length > 0) {
                url += "?";
            }

            var added = false;
            params.forEach(function (value, index) {
                if (added) {
                    url += "&";
                }
                url += value;
                added = true;
            });

            $http.get(url).success(querySucceeded);

            function querySucceeded(data) {
                self.loadProductData(data);
                // self.putItemsLoaded(cacheKey, data);

                //var tblNames = tableNames.split(",");
                //tblNames.forEach(function (tblName) {
                //    self.putItemsLoaded(cachePrefix + '-LastUpdate:' + tblName, Date.now());
                //});
                self.isLoaded = true;
                defer.resolve("Success");
            }
            //});
            return defer.promise;
        }

        function loadProductAttributes() {
            var self = this;
            var defer = $q.defer();
            var url = "api/Products/GetProductAttributes";
            $http.get(url).success(function (data) {
                self.attributes = [];
                angular.forEach(data, function (at) {
                    self.attributes[at.id] = at;
                });
                defer.resolve("Success");
            }).error(function (response) {
                console.log(response);
            });

            return defer.promise;
        }
                


        function pairProductAttributes() {
            var self = this;
            angular.forEach(self.entityItems, function (value) {
                var p = value;
                if (p != null) {
                    p.attributes = [];
                    angular.forEach(p.attributeIds, function (i) {
                        p.attributes.push(self.attributes[i]);
                    });
                }
            });
        }

        function loadProductData(data) {
            var self = this;

            if (self.entityItems.length == 0 || self.entityData.length == 0) {
                self.entityItems = _.object(data[0], data[1]);
                self.entityData = data[1];

                if (self.datacontext.cust.selfinitialDatadefered) {
                    self.datacontext.cust.loadOrderData();
                }
            } else {
                for (var inx = 0; inx <= data[0].length; inx++) {
                    var key = data[0][inx];
                    var value = data[1][inx];
                    if (angular.isDefined(self.entityItems[key]))

                        _.extend(self.entityItems[key], value);
                    else
                        self.entityItems[key] = value;
                }
            }

            self.partialsMappedLoaded = true;
            self.dataLoaded = true;
            gettingProductpartials = false;
        }

        //function testMyArrays(indexArray, dataArray) {
        //    var ip1 = indexArray[1010];
        //    var da1 = dataArray[0];

        //    ip1.testProp = "newProp";
        //    if (angular.isDefined(da1.testProp)) {
        //        console.log("The arrays are good");
        //    } else {
        //        console.log("The arrays BAD!@#$%^&");
        //    }
        //}

        function saveitems(data) {
            this.putItemsLoaded("partials", data);
        }

        function allowOrderEdits(prd) {
            var self = this;

            if (!prd) return false;
            if (!self.datacontext.cust.mycust) return false;
            return (self.datacontext.products.entityItems[prd]) &&
                !(
                    (self.datacontext.products.entityItems[prd].disableOnVendorHoliday && self.datacontext.cust.mycust.vendorLock)
                    || (angular.isDefined(self.datacontext.cust.mycust.lockUser) && self.datacontext.cust.mycust.lockUser)
                    || (self.datacontext.cust.mycust.twoDayCutoff && self.datacontext.products.entityItems[prd].twoDayLeadRequired)
                    || self.datacontext.products.entityItems[prd].outOfStock
                    || (self.datacontext.cust.mycust.vendorLock && self.datacontext.products.entityItems[prd].disableOnVendorHoliday)
                    || self.datacontext.cust.mycust.userSuspended
                    || (self.datacontext.cust.mycust && self.datacontext.cust.mycust.adminLockout && !datacontext.isReturning)
                    || !self.datacontext.products.entityItems[prd].showOnWeb
                    || !self.datacontext.products.entityItems[prd].allowAdd === false
                    || !self.datacontext.products.entityItems[prd].allowRemove === false                   
                );
        }

        function showOutOfStock(prd) {
            var self = this;
            if (!prd) return false;
            var p = self.datacontext.products.entityItems[prd];
            return p.outOfStock && p.nextQuantity == 0;
        }
        function showOverlayBanner(prd) {
            var self = this;
            if (!prd) return null;
            var p = self.datacontext.products.entityItems[prd];
            return p.productOverlayText;
        }
        function clearSearch() {
            var self = this;

            if (self.searchText.length == 0) return;
            self.searchText = '';
            self.entityData.forEach(function (prod) { prod.noMatch = false; });
        }
    };
})();
;
(function () {
    "use strict";

    var serviceId = "repository.promotion";
    angular.module("app-hd").factory(serviceId, ["$http", "common", "repository.abstract", "datacontext", "authService", RepositoryPromotion]);

    function RepositoryPromotion($http, common, abstractRepository, datacontext, authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);

        var AuthInfo = authService.authentication;

        function Ctor() {
            this.entityName = "promotion";
            this.promotion = null;
            this.applyPromotion = applyPromotion;
        }

        var $q = common.$q;
        abstractRepository.extend(Ctor);
        return Ctor;

        function applyPromotion(promotionCode) {
            var self = this;
            var defer = $q.defer();

            var existingPromo = datacontext.cust.mycust.promoCode ? datacontext.cust.mycust.promoCode.name : "";
            var parameters = "couponId=" + promotionCode + "&existingPromo=" + existingPromo + "&isSalesAdding=" + datacontext.cust.mycust.isSalesAdding;

            var url = "api/order/getAddCouponAuth" + "?" + parameters;

            if (!AuthInfo.isAuth || datacontext.cust.mycust.incompleteCustomerSignup) {
                if (datacontext.cust.mycust.id != null) {
                    url = "api/order/getAddCouponNoAuth" + "?id=" + datacontext.cust.mycust.id + "&" + parameters;
                } else {
                    url = null;
                    defer.resolve();
                }
            }

            if (url != null) {
                $http.get(url)
                    .success(function (data) {
                        if (data) {
                            if (!data.message) {
                                self.promotion = {
                                    name: data.promo_Code,
                                    promo_Code: data.promo_Code,
                                    description: data.description,
                                    allowCoolerFree: data.allowCoolerFree,
                                    allowCoolerWeeklyDrip: data.allowCoolerWeeklyDrip,
                                    ramsPromoCode: data.ramsPromoCode,
                                    hasDeliveryDiscount: data.hasDeliveryDiscount,
                                    hasDollarsOffDiscount: data.hasDollarsOffDiscount,
                                    hasFirstTasteDiscount: data.hasFirstTasteDiscount,
                                    hasGraduatedDiscount: data.hasGraduatedDiscount,
                                    slidingDeliveryDiscountTarget: data.slidingDeliveryDiscountTarget,
                                    slidingDollarsOffDiscountTarget: data.slidingDollarsOffDiscountTarget,
                                    slidingGraduatedDiscountTarget: data.slidingGraduatedDiscountTarget,
                                    dollarOffAmountFormatted: data.dollarOffAmountFormatted,
                                    hideTicklePopup: true
                                }
                                defer.resolve(self.promotion);
                            } else {
                                defer.reject(data.message);
                            }
                        }
                        else {
                            defer.resolve(null);
                        }
                    })
                    .error(function (data, status, headers, config) {
                        defer.reject(data);
                    });
            }

            return defer.promise;
        }

    };
})();;
(function () {
    var serviceId = 'repository.promo_banners';
    angular.module('app-hd').factory(serviceId,
	['common', 'repository.abstract', RepositoryPromoBanners]);

    function RepositoryPromoBanners(common, abstractRepository) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);

        function Ctor() {
            this.entityName = 'promo_banner';
            this.entityItems = [];
            this.bannerData = [];
            this.getBanners = getBanners;
            this.getPromoProducts = getPromoProducts;
        }

        abstractRepository.extend(Ctor);

        return Ctor;

        function getPromoProducts(id) {
            return this.getPartialsFromUrl('api/Products/GetProductsForPromotion?id=' + id, false);
        }

        function getBanners(forceRefresh) {
            //
            //
            //
            var self = this;
            if (self.isLoaded) {
                return self.$q.when(self.bannerData);
            }
            var cacheKey = self.entityName + 'getPartials';

            if (!forceRefresh) {
                var items = self._areItemsCached(cacheKey);
                if (angular.isDefined(items) && angular.isArray(items)) {
                    log("getBanners ItemsLoadingFromCache:" + cacheKey);
                    self.isLoaded = true;
                    self.bannerData = items;
                    return self.$q.when(items);
                }
            }

            return self.$http.get('api/PromotionBanner/GetFeaturedItems').success(querySucceeded);

            function querySucceeded(data) {
                self.isLoaded = true;

                self.putItemsLoaded(cacheKey, data);
                self.bannerData = data;
            }
        }
    };
})();;
(function () {
    "use strict";

    var serviceId = "repository.store";
    angular.module("app-hd").factory(serviceId, ["$http", "common", "repository.abstract", "datacontext", "authService", RepositoryStore]);

    function RepositoryStore($http, common, abstractRepository, datacontext, authService) {
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);

        var data = {
            selectedStore: {}
        }

        function Ctor() {
            this.entityName = "store";
            this.getStores = getStores;
            this.setSelectedStore = _setSelectedStore;
            this.getSelectedStore = _getSelectedStore;
        }

        function _getSelectedStore() {
            return data.selectedStore;
        }
        function _setSelectedStore(store) {
            data.selectedStore = store;
        }        

        var $q = common.$q;
        abstractRepository.extend(Ctor);
        return Ctor;

        function getStores() {
            //var self = this;
            //var defer = $q.defer();

            return $http.get('api/StoreFinderFeedback/GetStores'); //.success(
                //function (response) {
                //    defer.resolve(response);
                //}).error(function (data, status) {
                //    console.error('get stores Repos error', status, data);
                //});

            //return defer.promise;
        }
        
    };
})();;
(function () {
    "use strict";

    var serviceId = "repository.subscription";
    angular.module("app-hd").factory(serviceId, ["$filter", "common", "repository.abstract", "authService", repositorySubscription]);

    function repositorySubscription($filter, common, abstractRepository, authService) {
        var vm = this;
        var getLogFn = common.logger.getLogFn;
        var log = getLogFn(serviceId);
        var IsAuth = authService.authentication.isAuth;

        function Ctor() {
            this.entityName = "subscription";
            this.isDirty = false;
            this.isRunning = false;
            this.firstCall = true;
            this.subscriptionHistoryData = null;
            this.getSubscriptionHistory = _getSubscriptionHistory;
            this.defaultSubscriptionOfferId = 0;
            this.getDefaultSubscriptionOfferId = _getDefaultSubscriptionOfferId;
            this.hasActiveSubscription = null;
            this.getHasActiveSubscription = _getHasActiveSubscription;
        }

        abstractRepository.extend(Ctor);

        var $q = common.$q;
        var $http = common.$http;

        return Ctor;

        function _getSubscriptionHistory(forceRefresh) {
            var self = this;
            var defer = $q.defer();
            if (self.subscriptionHistoryData != null && !forceRefresh) {
                return self.$q.when(self.subscriptionHistoryData);
            }

            self.$http.get('api/subscription/GetCustomerSubscriptionHistory')
                .success(processHistory);
            return defer.promise;
            function processHistory(data) {
                self.subscriptionHistoryData = data;
                defer.resolve(data);
                return;
            }
        };

        function _getDefaultSubscriptionOfferId(forceRefresh) {
            var self = this;
            var defer = $q.defer();
            if (self.defaultSubscriptionOfferId != 0 && !forceRefresh) {
                return self.$q.when(self.defaultSubscriptionOfferId);
            }

            self.$http.get('api/subscription/GetDefaultSubscriptionOfferId')
                .success(processResult);
            return defer.promise;
            function processResult(data) {
                self.defaultSubscriptionOfferId = data;
                defer.resolve(data);
                return;
            }
        };

        function _getHasActiveSubscription(forceRefresh) {
            var self = this;
            var defer = $q.defer();
            if (self.hasActiveSubscription && !forceRefresh) {
                return self.$q.when(self.hasActiveSubscription == 1 ? true : false);
            }

            self.$http.get('api/subscription/GetCustomerHasActiveSubscription')
                .success(processResult);
            return defer.promise;
            function processResult(data) {
                self.hasActiveSubscription = data === true ? 1 : 0;
                defer.resolve(data);
                return;
            }
        };

    }
})();
;
(function () {
    const app = angular.module("app-hd");
    
    app.factory('smcCustomerRedirectInterceptor', ['$q', '$window', '$cookies', function ($q, $window, $cookies) {
        return {
            'response': function (response) {
                if (response.headers('X-Transferred')) {
                    $cookies.remove('loginData');
                    $cookies.remove('authorizationData');
                    $cookies.remove('custId');
                    $window.location.href = response.headers('X-Transferred');
                }
                return response;
            }
        };
    }]);
})();

;
angular.module("app-hd").factory('tokensManagerService', ['$http', 'ngAuthSettings', function ($http, ngAuthSettings) {
    var serviceBase = ngAuthSettings.apiServiceBaseUri;

    var tokenManagerServiceFactory = {};

    var _getRefreshTokens = function () {
        return $http.get('api/refreshtokens').then(function (results) {
            return results;
        });
    };

    var _deleteRefreshTokens = function (tokenid) {
        return $http.delete('api/refreshtokens/?tokenid=' + tokenid).then(function (results) {
            return results;
        });
    };

    tokenManagerServiceFactory.deleteRefreshTokens = _deleteRefreshTokens;
    tokenManagerServiceFactory.getRefreshTokens = _getRefreshTokens;

    return tokenManagerServiceFactory;
}]);;
(function () {
    "use strict";
    angular.module("app-hd").factory("unauthenticatedBranch", ["$http", "$state", "$cookies", "authService", service]);

    function service($http, $state, $cookies, authService) {
        var serviceState = {
            selectedLocationBranch: null,
            loadingCatalogUpdate: false,
            loadingCatalogUpdateError: null,
            fromRecipeState: ($state.current.name === "browsing.recipes" || $state.current.name === "browsing.recipes.recipe"),
            locationBranches: [
                {
                    name: "Illinois",
                    branchNumber: 1,
                    priceSchedule: 1000
                },
                {
                    name: "Indiana",
                    branchNumber: 10,
                    priceSchedule: 1000
                },
                {
                    name: "Michigan",
                    branchNumber: 12,
                    priceSchedule: 1000
                },
                {
                    name: "Missouri",
                    branchNumber: 9,
                    priceSchedule: 1000
                },
                {
                    name: "Wisconsin",
                    branchNumber: 11,
                    priceSchedule: 1000
                },
                {
                    name: "North Carolina (South Mountain)",
                    branchNumber: 18,
                    priceSchedule: 15,
                    redirectUrl: "https://southmountaincreamery.com/oberweis-home-delivery/"
                },
                {
                    name: "Virginia (South Mountain)",
                    branchNumber: 15,
                    priceSchedule: 15,
                    redirectUrl: "https://southmountaincreamery.com/oberweis-home-delivery/"
                }
            ]
        }

        var newStartId = $cookies.get("custId");

        function showInitialLocationSelect() {
            return (
                $state.current.name.startsWith("browsing") &&
                !authService.authentication.isAuth &&
                serviceState.selectedLocationBranch === null &&
                newStartId === undefined
            )
        }

        function showChangeLocationSelect() {
            return (
                serviceState.selectedLocationBranch !== null &&
                !authService.authentication.isAuth
            )
        }

        return {
            state: serviceState,
            showInitialLocationSelect,
            showChangeLocationSelect,
        }
    }
})();
;
var underscore = angular.module('underscore', []);
underscore.factory('_', function () {
    return window._; // assumes underscore has already been loaded on the page
});;
angular.module('app-hd').filter('dayOfWeek', function () {
    return function (input, from, to) {
        var date;
        if (input === undefined || input === null)
            return;
        
        if (typeof input === 'string') {
            date = new Date(input);
        }
        
        if (typeof input === 'object' && input.getDay !== undefined && typeof input.getDay() === 'function') {
            date = input;
        }
        
        if (date !== undefined) {
            return date.getDay();
        } 
    };
});
;
