/* Minification failed. Returning unminified contents.
(2467,37-45): run-time error JS1006: Expected ')': function
(2467,56): run-time error JS1004: Expected ';'
(2474,38): run-time error JS1004: Expected ';'
(2500,26-27): run-time error JS1195: Expected expression: )
(2551,37-45): run-time error JS1006: Expected ')': function
(2551,56): run-time error JS1004: Expected ';'
(2556,34): run-time error JS1004: Expected ';'
(2561,26-27): run-time error JS1195: Expected expression: )
(2570,41-49): run-time error JS1006: Expected ')': function
(2570,60): run-time error JS1004: Expected ';'
(2577,38): run-time error JS1004: Expected ';'
(2581,30-31): run-time error JS1195: Expected expression: )
(2586,41-49): run-time error JS1006: Expected ')': function
(2586,60): run-time error JS1004: Expected ';'
(2591,38): run-time error JS1004: Expected ';'
(2595,30-31): run-time error JS1195: Expected expression: )
(2669,37-45): run-time error JS1006: Expected ')': function
(2669,56): run-time error JS1004: Expected ';'
(2674,34): run-time error JS1004: Expected ';'
(2678,26-27): run-time error JS1195: Expected expression: )
(2687,41-49): run-time error JS1006: Expected ')': function
(2687,60): run-time error JS1004: Expected ';'
(2698,42): run-time error JS1004: Expected ';'
(2702,30-31): run-time error JS1195: Expected expression: )
(2707,41-49): run-time error JS1006: Expected ')': function
(2707,60): run-time error JS1004: Expected ';'
(2716,42): run-time error JS1004: Expected ';'
(2720,30-31): run-time error JS1195: Expected expression: )
(2733,33-41): run-time error JS1006: Expected ')': function
(2733,52): run-time error JS1004: Expected ';'
(2738,30): run-time error JS1004: Expected ';'
(2760,22-23): run-time error JS1195: Expected expression: )
(2827,45-53): run-time error JS1006: Expected ')': function
(2827,64): run-time error JS1004: Expected ';'
(2832,42): run-time error JS1004: Expected ';'
(2834,34-35): run-time error JS1195: Expected expression: )
(2840,49-57): run-time error JS1006: Expected ')': function
(2840,68): run-time error JS1004: Expected ';'
(2845,46): run-time error JS1004: Expected ';'
(2847,38-39): run-time error JS1195: Expected expression: )
(2858,53-61): run-time error JS1006: Expected ')': function
(2858,72): run-time error JS1004: Expected ';'
(2863,50): run-time error JS1004: Expected ';'
(2865,42-43): run-time error JS1195: Expected expression: )
(2865,43-44): run-time error JS1195: Expected expression: .
(2879,45-53): run-time error JS1006: Expected ')': function
(2879,64): run-time error JS1004: Expected ';'
(2882,42): run-time error JS1004: Expected ';'
(2884,34-35): run-time error JS1195: Expected expression: )
(2911,42): run-time error JS1004: Expected ';'
(2911,52-53): run-time error JS1010: Expected identifier: (
(2914,22): run-time error JS1004: Expected ';'
(10207,33-36): run-time error JS1009: Expected '}': ...
(10208,58): run-time error JS1004: Expected ';'
(10208,58-59): run-time error JS1195: Expected expression: :
(10209,30-31): run-time error JS1006: Expected ')': ;
(10211,26-27): run-time error JS1195: Expected expression: )
(10212,22): run-time error JS1004: Expected ';'
(10212,23-27): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(11130,18-19): run-time error JS1194: Expected ',' or ']': ;
(11130,18-19): run-time error JS1006: Expected ')': ;
(11219,9-10): run-time error JS1002: Syntax error: }
(11219,10-11): run-time error JS1195: Expected expression: ]
(11219,11-12): run-time error JS1195: Expected expression: )
(11220,5-6): run-time error JS1195: Expected expression: .
(16565,46-49): run-time error JS1009: Expected '}': ...
(16565,45): run-time error JS1004: Expected ';'
(16565,60): run-time error JS1004: Expected ';'
(16565,60-61): run-time error JS1195: Expected expression: :
(16566,35-39): run-time error JS1006: Expected ')': else
(16566,34): run-time error JS1004: Expected ';'
(16567,46-49): run-time error JS1009: Expected '}': ...
(16567,45): run-time error JS1004: Expected ';'
(16569,30-31): run-time error JS1195: Expected expression: )
(16570,26): run-time error JS1004: Expected ';'
(16570,27-31): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(16576,23-27): run-time error JS1194: Expected ',' or ']': else
(16576,23-27): run-time error JS1006: Expected ')': else
(16430,34): run-time error JS1004: Expected ';'
(16579,17-18): run-time error JS1002: Syntax error: }
(16579,18-19): run-time error JS1195: Expected expression: ,
(16634,3-4): run-time error JS1002: Syntax error: }
(16634,4-5): run-time error JS1195: Expected expression: ]
(16634,5-6): run-time error JS1195: Expected expression: )
(23488,40): run-time error JS1004: Expected ';'
(23488,50-51): run-time error JS1010: Expected identifier: (
(23523,26): run-time error JS1004: Expected ';'
(23541,14-15): run-time error JS1195: Expected expression: ,
(29179,46-49): run-time error JS1009: Expected '}': ...
(29179,45): run-time error JS1004: Expected ';'
(29179,60): run-time error JS1004: Expected ';'
(29179,60-61): run-time error JS1195: Expected expression: :
(29180,35-39): run-time error JS1006: Expected ')': else
(29180,34): run-time error JS1004: Expected ';'
(29181,46-49): run-time error JS1009: Expected '}': ...
(29181,45): run-time error JS1004: Expected ';'
(29184,30-31): run-time error JS1195: Expected expression: )
(29185,26): run-time error JS1004: Expected ';'
(29185,27-31): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(29190,23-27): run-time error JS1194: Expected ',' or ']': else
(29190,23-27): run-time error JS1006: Expected ')': else
(29043,45): run-time error JS1004: Expected ';'
(29193,17-18): run-time error JS1002: Syntax error: }
(29193,18-19): run-time error JS1195: Expected expression: ,
(29247,3-4): run-time error JS1002: Syntax error: }
(29247,4-5): run-time error JS1195: Expected expression: ]
(29247,5-6): run-time error JS1195: Expected expression: )
 */
/*'use strict';*/

angular
    .module('ecs', [
        'ngCookies',
        'ngAnimate',
        'ngSanitize',
        'ngTouch',
        'ngRoute',
        'angularFileUpload',
        'ui.bootstrap',
        'ecs.ctrl.main',
        'ecs.ctrl.cookieMessage',
        'ecs.ctrl.doorbusters',
        'ecs.ctrl.product.detail',
        'ecs.ctrl.product.instock',
        'ecs.ctrl.sendToFriendCtrl',
        'ecs.ctrl.emailCartCtrl',
        'ecs.ctrl.cartSummary',
        'ecs.ctrl.catalog',
        'ecs.ctrl.securecatalog',
        'ecs.ctrl.register',
        'ecs.ctrl.ssoRegister',
        'ecs.ctrl.billing',
        'ecs.ctrl.payment',
        'ecs.ctrl.shipping',
        'ecs.ctrl.selectAddress',
        'ecs.ctrl.review',
        'ecs.ctrl.complete',
        'ecs.ctrl.select-pack',
        'ecs.ctrl.award-exceptions',
        'ecs.ctrl.rewards',
        'ecs.ctrl.createReward',
        'ecs.ctrl.recipient',
        'ecs.ctrl.supervisor',
        'ecs.ctrl.favorites',
        'ecs.ctrl.billingAddress',
        'ecs.ctrl.shippingAddresses',
        'ecs.ctrl.addOrEditAddress',
        'ecs.ctrl.purchaseBalance',
        'ecs.ctrl.orderHistory',
        'ecs.ctrl.pointHistory',
        'ecs.ctrl.giftCertificates',
        'ecs.ctrl.digitalLocker',
        'ecs.ctrl.paymentCards',
        'ecs.ctrl.userInfo',
        'ecs.ctrl.removeAccount',
        'ecs.ctrl.header',
        'ecs.ctrl.cart',
        'ecs.ctrl.terms',
        'ecs.ctrl.contact-us',
        'ecs.ctrl.dataConsentRequest',
        'ecs.ctrl.scrolltotop',
        'ecs.ctrl.storeLocation',
        'ecs.ctrl.refreshheader',
        'ecs.ctrl.orderDetails',
        'ecs.ctrl.cartDetails',
        'ecs.ctrl.microsoftLanding',
        'ecs.ctrl.msLinkedIn',
        'ecs.ctrl.product.search',
        'ecs.ctrl.review-catalog-order',
        'ecs.ctrl.review-gift-code-catalog-order',
        'ecs.ctrl.review-order',
        'ecs.ctrl.select-award',
        'ecs.ctrl.select-catalog-award',
        'ecs.ctrl.giftCode',
        'ecs.ctrl.selectGiftCodeCatalogAward',
        'ecs.ctrl.selectGiftCodeAward',
        'ecs.ctrl.review-gift-code-order',
        'ecs.ctrl.search-rewards',
        'ecs.ctrl.dashboard-rewards',
        'ecs.service.chili',
        'ecs.ctrl.select-points',
        'ecs.ctrl.select-charity',
        'ecs.ctrl.select-group',
        'ecs.ctrl.shop-points',
        'ecs.ctrl.cmsImageCtrl',
        'ecs.ctrl.cmsCarouselCtrl',
        'ecs.ctrl.cmsGrid3WidelCtrl',
        'ecs.ctrl.validation',
        'ecs.ctrl.gcBilling',
        'ecs.ctrl.chili',
        'ecs.ctrl.petvetcustomfield',
        'ecs.service.impl.objects',
        'ecs.service.impl.stores',
        'ecs.service.impl.orders',
        'ecs.service.impl.customers',
        'ecs.service.impl.promoCodes',
        'ecs.service.impl.shoppingCarts',
        'ecs.service.impl.employees',
        'ecs.service.impl.storePasses',
        'ecs.service.impl.electronicPurchases',
        'ecs.service.impl.notifications',
        'ecs.service.impl.rewards',
        'ecs.service.cart',
        'ecs.service.checkout',
        'ecs.service.reward',
        'ecs.service.budgets',
        'ecs.service.app-timeout',
        'ecs.service.impl.catalogs',
        'ecs.service.impl.products',
        'ecs.service.impl.rewardsAddress',
        'ecs.service.impl.campaigns',
        'ecs.service.address',
        'ecs.service.store',
        'ecs.service.user',
        'ecs.service.impl.orders',
        'ecs.service.ecsResource',
        'ecs.service.ecsResource.config',
        'ecs.service.ecsResource.utils',
        'ecs.service.ecs-locale',
        'ecs.service.messaging',
        'ecs.service.constants',
        'ecs.service.common',
        'ecs.service.security',
        'ecs.service.campaign',
        'ecs.service.campaignwizard',
        'ecs.service.storePassesStateManager',
        'ecs.service.gcCheckout',
        'ecs.service.impl.petVetService',
        'ecs.directives.fieldMatch',
        'ecs.directives.codiceFicale',
        'ecs.directives.contenteditable',
        'ecs.directives.accessibleForm',
        'ecs.directives.localeDateFormatter',
        'ecs.directives.numbersOnly',
        'ecs.directives.noSpecialChar',
        'ecs.directives.limitedSpecialChar',
        'ecs.directives.emailSpecialCharOnly',
        'ecs.directives.datesOnly',
        'ecs.directives.futureDate',
        'ecs.directives.fallbackSrc',
        'ecs.directives.numbersHypen',
        'ecs.directives.loader',
        'ecs.directives.affix',
        'ecs.service.importfileprogress',
        'ecs.reward-campaigns',
        'ecs.ctrl.storePass',
        'ecs.ctrl.storePassEventDetails',
        'ecs.ctrl.vipStorePassesCreate',
        'ecs.ctrl.fafStorePassCreate',
        'ecs.ctrl.storePassGuestList',
        'ecs.ctrl.gc-recipients',
        'ecs.services.impl.giftCertificates',
        'ecs.ctrl.gcOrderDetails',
        'chart.js',
        'wipImageZoom',
        'ecs.ctrl.selectThirdPartyShipping',
        'ecs.service.postalCodeOptionalCountries',
        'ecs.ctrl.guestBillingAddress',
        'ecs.ctrl.guestShippingAddress',
        'ecs.core.components',
        'ecs.ctrl.creditCardTokenizer'
    ])
    .config(['$routeProvider', '$locationProvider', '$logProvider', 'Config', 'wipImageZoomConfigProvider', function ($routeProvider, $locationProvider, $logProvider, Config, wipImageZoomConfigProvider) {

        wipImageZoomConfigProvider.setDefaults({
            style: 'box',
            cursor: "zoom-in"

        })
        $routeProvider.when('/', {
            templateUrl: App.Configuration.RootPath + 'Shop/Home',
            controller: ''
        });
        $routeProvider.when('/cart', {
            templateUrl: App.Configuration.RootPath + 'Shop/Cart',
            controller: ''
        });
        $routeProvider.when('/contactus', {
            templateUrl: App.Configuration.RootPath + 'Shop/ContactUs',
            controller: ''
        });
        $routeProvider.when('/help', {
            templateUrl: App.Configuration.RootPath + 'Shop/Help',
            controller: ''
        });
        $routeProvider.when('/privacy', {
            templateUrl: App.Configuration.RootPath + 'Shop/Privacy',
            controller: ''
        });
        $routeProvider.when('/terms', {
            templateUrl: App.Configuration.RootPath + 'Shop/Terms',
            controller: ''
        });
        $routeProvider.when('/dataprotection', {
            templateUrl: App.Configuration.RootPath + 'Shop/DataProtection',
            controller: ''
        });
        $routeProvider.when('/dataconsent', {
            templateUrl: App.Configuration.RootPath + 'Shop/DataConsentRequest',
            controller: ''
        });
        $routeProvider.when('/catalog/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Catalog/' + params.id; },
            controller: ''
        });
        $routeProvider.when('/catalog/:prev/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Catalog/' + params.id + '?b=' + params.prev; },
            controller: ''
        });
        $routeProvider.when('/catalog/:id/rf/:refinement', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Catalog/' + params.id + '?rf=' + params.refinement; },
            controller: ''
        });
        $routeProvider.when('/catalog/:prev/:id/rf/:refinement', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Catalog/' + params.id + '?b=' + params.prev + '&rf=' + params.refinement; },
            controller: ''
        });
        $routeProvider.when('/product/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Product/' + params.id; },
            controller: ''
        });
        $routeProvider.when('/product/:prev/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Product/' + params.id + '?b=' + params.prev; },
            controller: ''
        });
        $routeProvider.when('/product/:catprev/:prev/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Product/' + params.id + '?b=' + params.prev + '&cb=' + params.catprev; },
            controller: ''
        });
        $routeProvider.when('/product-search/:uid/:term', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/ProductSearch/' + params.uid + '?t=' + params.term; },
            controller: ''
        });
        $routeProvider.when('/price-search/:cat/:level', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/ProductSearch/Price?t=' + params.cat + '&l=' + params.level; },
            controller: ''
        });

        $routeProvider.when('/rewardcampaigns/', {
            templateUrl: App.Configuration.RootPath + 'Campaigns/',
            controller: ''
        });

        $routeProvider.when('/rewardcampaigns/create/:step', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Campaigns/Create/' + params.step; },
            controller: ''
        });

        $routeProvider.when('/rewardcampaigns/create/:step/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Campaigns/Create/' + params.step; },
            controller: ''
        });

        $routeProvider.when('/rewardcampaigns/create/', {
            templateUrl: App.Configuration.RootPath + 'Campaigns/Create/Templates',
            controller: ''
        });

        $routeProvider.when('/awards/', {
            templateUrl: App.Configuration.RootPath + 'Awards/',
            controller: ''
        });

        $routeProvider.when('/awards/search-rewards/', {
            templateUrl: App.Configuration.RootPath + 'Awards/SearchRewards',
            controller: ''
        });

        $routeProvider.when('/awards/dashboard-rewards/', {
            templateUrl: App.Configuration.RootPath + 'Awards/DashboardRewards',
            controller: ''
        });

        $routeProvider.when('/awards/create-rewards/', {
            templateUrl: App.Configuration.RootPath + 'Awards/Create',
            controller: ''
        });

        $routeProvider.when('/awards/opt-out/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/OptOut/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-pack/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectPack/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-charity/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectCharity/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-points/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectPoints/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/review-order/:id/:packId/:productId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/ReviewOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/review-order/:id/:packId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/ReviewOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/review-catalog-order/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/ReviewCatalogOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/review-catalog-order/:id/:productId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/ReviewCatalogOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-award/:id/:packId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectAward/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-catalog-award/:id/', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectCatalogAward/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/select-group/:id/:packId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/SelectGroup/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/awards/exceptions/', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/Exceptions/'; },
            controller: ''
        });

        $routeProvider.when('/awards/error/', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/Error/'; },
            controller: ''
        });

        $routeProvider.when('/awards/shop-points/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Awards/ShopPoints/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/redeemcode', {
            templateUrl: `${App.Configuration.RootPath}RedeemCode/Home`,
            controller: ''
        });

        $routeProvider.when('/select-catalog-award/:id', {
            templateUrl: function (params) { return `${App.Configuration.RootPath}RedeemCode/SelectCatalogAward/${params.id}`; },
            controller: ''
        });

        $routeProvider.when('/review-catalog-order/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'RedeemCode/ReviewCatalogOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/select-award/:id/:packId', {
            templateUrl: function (params) { return `${App.Configuration.RootPath}RedeemCode/SelectAward/${params.id}`; },
            controller: ''
        });

        $routeProvider.when('/review-order/:id/:packId', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'RedeemCode/ReviewOrder/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/checkout/register/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Register/' + params.id; },
            controller: '' //registerCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/payment/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Payment/' + params.id; },
            controller: '' //registerCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/billing/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Billing/' + params.id; },
            controller: '', //billingCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/billing/billing-address/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/BillingAddress/' + params.id },
            controller: '' //billingAddressCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/shipping/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Shipping/' + params.id; },
            controller: '', //shippingCtrl is bound on the container in the View itself
            reloadOnSearch: false //this is disabled so that when the logic clears the querystring of the address id the angular controller is not instantiated again. 
        });
        $routeProvider.when('/checkout/shipping/select-shipping-address/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/SelectAddress/' + params.id; },
            controller: '', //selectAddressCtrl is bound on the container in the View itself
            reloadOnSearch: false //this is disabled so that when the logic clears the querystring of the address id the angular controller is not instantiated again. 
        });
        $routeProvider.when('/checkout/shipping/shipping-address/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/AddOrEditAddress/' + params.id + '/?addressId=' + params.addressId },
            controller: '' //addOrEditAddressCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/review/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Review/' + params.id; },
            controller: '' //reviewCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/complete/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Complete/' + params.id; },
            controller: '' //reviewCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/purchase-agreement/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/PurchaseAgreement/' + params.id; },
            controller: '' //termsCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/checkout/validation/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Validation/' + params.id; },
            controller: '', //validation is bound on the container in the View itself
            reloadOnSearch: false //this is disabled so that when the logic clears the querystring of the address id the angular controller is not instantiated again. 
        });
        $routeProvider.when('/gccheckout/recipients/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/GCRecipients/' + params.id; },
            controller: '', //billingCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/gccheckout/billing/billing-address/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/BillingAddress/' + params.id + '/?com=gc' },
            controller: '' //billingAddressCtrl is bound on the container in the View itself
        });
        $routeProvider.when('/gccheckout/billing/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/GCBilling/' + params.id },
            controller: '' //billingAddressCtrl is bound on the container in the View itself
        });

        $routeProvider.when('/guestcheckout/billingaddress', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/GuestBillingAddress'; }
        });

        $routeProvider.when('/guestcheckout/shippingaddress', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/GuestShippingAddress'; }
        });

        $routeProvider.when('/MyAccount/UserInfo', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/UserInfo',
            controller: ''
        });
        $routeProvider.when('/MyAccount/RemoveAccount', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/RemoveAccount',
            controller: ''
        });
        $routeProvider.when('/MyAccount/SelectLocation', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/SelectLocation',
            controller: ''
        });

        $routeProvider.when('/MyAccount/MyFavorites', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/MyFavorites',
            controller: ''
        });

        $routeProvider.when('/MyAccount/ShippingAddresses', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/ShippingAddresses',
            controller: ''
        });

        $routeProvider.when('/MyAccount/OrderHistory', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/OrderHistory',
            controller: ''
        });

        $routeProvider.when('/MyAccount/OrderDetails/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'MyAccount/OrderDetails/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/MyAccount/GCOrderDetails/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'MyAccount/GCOrderDetails/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/MyAccount/CartDetails/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'MyAccount/CartDetails/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/MyAccount/PointHistory', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/PointHistory',
            controller: ''
        });

        $routeProvider.when('/MyAccount/EmployeePurchases', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/EmployeePurchases',
            controller: ''
        });

        $routeProvider.when('/MyAccount/GiftCertificates', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/GiftCertificates',
            controller: ''
        });

        $routeProvider.when('/MyAccount/DigitalLocker', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/DigitalLocker',
            controller: ''
        });

        $routeProvider.when('/MyAccount/DownloadDetails', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/DownloadDetails',
            controller: ''
        });

        $routeProvider.when('/MyAccount/OrderHistory/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + '/MyAccount/OrderHistory/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/MyAccount/PaymentCards', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/PaymentCards',
            controller: ''
        });

        $routeProvider.when('/MyAccount/storepasses', {
            templateUrl: App.Configuration.RootPath + 'MyAccount/StorePasses',
            controller: ''
        });

        $routeProvider.when('/MyAccount/storepassevents/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + '/MyAccount/StorePassEvents/' + params.id; },
            controller: ''
        });


        $routeProvider.when('/MyAccount/storepassescreate/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + '/MyAccount/StorePassesCreate/' + params.id; },
            controller: ''
        });

        $routeProvider.when('/page/:id', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Shop/Page/' + params.id; },
            controller: ''
        });


        $routeProvider.when('/unauthorized', {
            templateUrl: '/Unauthorized',
            controller: ''
        });

        $routeProvider.when('/checkout/landing', {
            templateUrl: function (params) { return App.Configuration.RootPath + 'Checkout/Landing'; },
            controller: ''
        });

        //$routeProvider.when('/rewardcampaigns/create/general/', {
        //    templateUrl: 'Campaigns/',
        //    controller: ''
        //});

        $routeProvider.otherwise({
            redirectTo: '/'
        });


        // Specify HTML5 mode (using the History APIs) or HashBang syntax.
        $locationProvider.html5Mode(false);
        //$logProvider.debugEnabled = Config.debugEnabled;

    }])
    .run(['$rootScope', function ($rootScope) {
        //$rootScope.store = ECSStores.currentUser;
        //$rootScope.user = ECSStores.currentUser;
        //StoreService.getStore().success(function (data) {
        //    $rootScope.store = data.Store;
        //});

        var storeInfo = JSON.parse($.ajax({
            type: "GET",
            url: App.Configuration.RootPath + 'Store/Info',
            cache: false,
            async: false
        }).responseText);

        $rootScope.store = storeInfo.Store;
        $rootScope.store.PaymentMethods = storeInfo.RestrictedPaymentMethods;

        $rootScope.user = JSON.parse($.ajax({
            type: "GET",
            url: App.Configuration.RootPath + 'User/Info',
            cache: false,
            async: false
        }).responseText).User;

        //console.log($rootScope.store);
        //console.log($rootScope.user);

    }])
    .run(['$rootScope', '$templateCache', function ($rootScope, $templateCache) {
        $rootScope.$on('$routeChangeStart', function (event, next, current) {
            if (typeof (current) !== 'undefined') {
                $templateCache.remove(current.templateUrl);
            }
        });
    }])
    .run(function (AuthenticationStateCheck) { });


;
//Source: http://andrewdupont.net/2009/08/28/deep-extending-objects-in-javascript/
//TODO: Move into separate file
angular.deepExtend = function (destination, source) {
    for (var property in source) {
        if (source[property] && source[property].constructor && source[property].constructor === Object) {
            destination[property] = destination[property] || {};
            arguments.callee(destination[property], source[property]);
        } else {
            destination[property] = source[property];
        }
    }
    return destination;
};


angular
    .module('ecs.service.ecsResource.config', [])
    .constant('Config', angular.deepExtend({
        environment: 'production', //development or production
        language: 'en-US',

        API: {
            host: (App.Configuration.UseCORS === 'true') ? 'https://api.ecompanystore.com' : App.Configuration.Host,
            port: '',
            path: (App.Configuration.UseCORS === 'true') ? '/V2/rest/' : '/api/rest/'
        },
        Webhooks: {
            host: 'https://api.ecompanystore.com',
            path: /webhooks/
        },
        ProductImageBaseURL: ' https://store.ecompanystore.com/ECS_ProductImages/'
    }, angular._localConfig || {}))
    .factory('BaseUrl', function (Config) {
        return (Config.API.host + ':' + Config.API.port + '/');
    })
    .factory('APIBaseUrl', function (Config) {
        return (Config.API.host + ':' + Config.API.port + Config.API.path + '/');
    });





;//This file is included in .gitignore and should hold your local configuration overrides
angular._localConfig = {
    environment: 'development', //show debug messages
    API: {
        useMocks: false,
        debugEnabled: true,
        fakeDelay: 800
    }
};;/*
CryptoJS v3.1.2
code.google.com/p/crypto-js
(c) 2009-2013 by Jeff Mott. All rights reserved.
code.google.com/p/crypto-js/wiki/License
*/
var CryptoJS=CryptoJS||function(q,r){var k={},g=k.lib={},p=function(){},t=g.Base={extend:function(b){p.prototype=this;var j=new p;b&&j.mixIn(b);j.hasOwnProperty("init")||(j.init=function(){j.$super.init.apply(this,arguments)});j.init.prototype=j;j.$super=this;return j},create:function(){var b=this.extend();b.init.apply(b,arguments);return b},init:function(){},mixIn:function(b){for(var j in b)b.hasOwnProperty(j)&&(this[j]=b[j]);b.hasOwnProperty("toString")&&(this.toString=b.toString)},clone:function(){return this.init.prototype.extend(this)}},
n=g.WordArray=t.extend({init:function(b,j){b=this.words=b||[];this.sigBytes=j!=r?j:4*b.length},toString:function(b){return(b||u).stringify(this)},concat:function(b){var j=this.words,a=b.words,l=this.sigBytes;b=b.sigBytes;this.clamp();if(l%4)for(var h=0;h<b;h++)j[l+h>>>2]|=(a[h>>>2]>>>24-8*(h%4)&255)<<24-8*((l+h)%4);else if(65535<a.length)for(h=0;h<b;h+=4)j[l+h>>>2]=a[h>>>2];else j.push.apply(j,a);this.sigBytes+=b;return this},clamp:function(){var b=this.words,j=this.sigBytes;b[j>>>2]&=4294967295<<
32-8*(j%4);b.length=q.ceil(j/4)},clone:function(){var b=t.clone.call(this);b.words=this.words.slice(0);return b},random:function(b){for(var j=[],a=0;a<b;a+=4)j.push(4294967296*q.random()|0);return new n.init(j,b)}}),v=k.enc={},u=v.Hex={stringify:function(b){var a=b.words;b=b.sigBytes;for(var h=[],l=0;l<b;l++){var m=a[l>>>2]>>>24-8*(l%4)&255;h.push((m>>>4).toString(16));h.push((m&15).toString(16))}return h.join("")},parse:function(b){for(var a=b.length,h=[],l=0;l<a;l+=2)h[l>>>3]|=parseInt(b.substr(l,
2),16)<<24-4*(l%8);return new n.init(h,a/2)}},a=v.Latin1={stringify:function(b){var a=b.words;b=b.sigBytes;for(var h=[],l=0;l<b;l++)h.push(String.fromCharCode(a[l>>>2]>>>24-8*(l%4)&255));return h.join("")},parse:function(b){for(var a=b.length,h=[],l=0;l<a;l++)h[l>>>2]|=(b.charCodeAt(l)&255)<<24-8*(l%4);return new n.init(h,a)}},s=v.Utf8={stringify:function(b){try{return decodeURIComponent(escape(a.stringify(b)))}catch(h){throw Error("Malformed UTF-8 data");}},parse:function(b){return a.parse(unescape(encodeURIComponent(b)))}},
h=g.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new n.init;this._nDataBytes=0},_append:function(b){"string"==typeof b&&(b=s.parse(b));this._data.concat(b);this._nDataBytes+=b.sigBytes},_process:function(b){var a=this._data,h=a.words,l=a.sigBytes,m=this.blockSize,k=l/(4*m),k=b?q.ceil(k):q.max((k|0)-this._minBufferSize,0);b=k*m;l=q.min(4*b,l);if(b){for(var g=0;g<b;g+=m)this._doProcessBlock(h,g);g=h.splice(0,b);a.sigBytes-=l}return new n.init(g,l)},clone:function(){var b=t.clone.call(this);
b._data=this._data.clone();return b},_minBufferSize:0});g.Hasher=h.extend({cfg:t.extend(),init:function(b){this.cfg=this.cfg.extend(b);this.reset()},reset:function(){h.reset.call(this);this._doReset()},update:function(b){this._append(b);this._process();return this},finalize:function(b){b&&this._append(b);return this._doFinalize()},blockSize:16,_createHelper:function(b){return function(a,h){return(new b.init(h)).finalize(a)}},_createHmacHelper:function(b){return function(a,h){return(new m.HMAC.init(b,
h)).finalize(a)}}});var m=k.algo={};return k}(Math);
(function(q){function r(a,m,b,j,g,l,k){a=a+(m&b|~m&j)+g+k;return(a<<l|a>>>32-l)+m}function k(a,m,b,j,g,l,k){a=a+(m&j|b&~j)+g+k;return(a<<l|a>>>32-l)+m}function g(a,m,b,j,g,l,k){a=a+(m^b^j)+g+k;return(a<<l|a>>>32-l)+m}function p(a,g,b,j,k,l,p){a=a+(b^(g|~j))+k+p;return(a<<l|a>>>32-l)+g}for(var t=CryptoJS,n=t.lib,v=n.WordArray,u=n.Hasher,n=t.algo,a=[],s=0;64>s;s++)a[s]=4294967296*q.abs(q.sin(s+1))|0;n=n.MD5=u.extend({_doReset:function(){this._hash=new v.init([1732584193,4023233417,2562383102,271733878])},
_doProcessBlock:function(h,m){for(var b=0;16>b;b++){var j=m+b,n=h[j];h[j]=(n<<8|n>>>24)&16711935|(n<<24|n>>>8)&4278255360}var b=this._hash.words,j=h[m+0],n=h[m+1],l=h[m+2],q=h[m+3],t=h[m+4],s=h[m+5],u=h[m+6],v=h[m+7],w=h[m+8],x=h[m+9],y=h[m+10],z=h[m+11],A=h[m+12],B=h[m+13],C=h[m+14],D=h[m+15],c=b[0],d=b[1],e=b[2],f=b[3],c=r(c,d,e,f,j,7,a[0]),f=r(f,c,d,e,n,12,a[1]),e=r(e,f,c,d,l,17,a[2]),d=r(d,e,f,c,q,22,a[3]),c=r(c,d,e,f,t,7,a[4]),f=r(f,c,d,e,s,12,a[5]),e=r(e,f,c,d,u,17,a[6]),d=r(d,e,f,c,v,22,a[7]),
c=r(c,d,e,f,w,7,a[8]),f=r(f,c,d,e,x,12,a[9]),e=r(e,f,c,d,y,17,a[10]),d=r(d,e,f,c,z,22,a[11]),c=r(c,d,e,f,A,7,a[12]),f=r(f,c,d,e,B,12,a[13]),e=r(e,f,c,d,C,17,a[14]),d=r(d,e,f,c,D,22,a[15]),c=k(c,d,e,f,n,5,a[16]),f=k(f,c,d,e,u,9,a[17]),e=k(e,f,c,d,z,14,a[18]),d=k(d,e,f,c,j,20,a[19]),c=k(c,d,e,f,s,5,a[20]),f=k(f,c,d,e,y,9,a[21]),e=k(e,f,c,d,D,14,a[22]),d=k(d,e,f,c,t,20,a[23]),c=k(c,d,e,f,x,5,a[24]),f=k(f,c,d,e,C,9,a[25]),e=k(e,f,c,d,q,14,a[26]),d=k(d,e,f,c,w,20,a[27]),c=k(c,d,e,f,B,5,a[28]),f=k(f,c,
d,e,l,9,a[29]),e=k(e,f,c,d,v,14,a[30]),d=k(d,e,f,c,A,20,a[31]),c=g(c,d,e,f,s,4,a[32]),f=g(f,c,d,e,w,11,a[33]),e=g(e,f,c,d,z,16,a[34]),d=g(d,e,f,c,C,23,a[35]),c=g(c,d,e,f,n,4,a[36]),f=g(f,c,d,e,t,11,a[37]),e=g(e,f,c,d,v,16,a[38]),d=g(d,e,f,c,y,23,a[39]),c=g(c,d,e,f,B,4,a[40]),f=g(f,c,d,e,j,11,a[41]),e=g(e,f,c,d,q,16,a[42]),d=g(d,e,f,c,u,23,a[43]),c=g(c,d,e,f,x,4,a[44]),f=g(f,c,d,e,A,11,a[45]),e=g(e,f,c,d,D,16,a[46]),d=g(d,e,f,c,l,23,a[47]),c=p(c,d,e,f,j,6,a[48]),f=p(f,c,d,e,v,10,a[49]),e=p(e,f,c,d,
C,15,a[50]),d=p(d,e,f,c,s,21,a[51]),c=p(c,d,e,f,A,6,a[52]),f=p(f,c,d,e,q,10,a[53]),e=p(e,f,c,d,y,15,a[54]),d=p(d,e,f,c,n,21,a[55]),c=p(c,d,e,f,w,6,a[56]),f=p(f,c,d,e,D,10,a[57]),e=p(e,f,c,d,u,15,a[58]),d=p(d,e,f,c,B,21,a[59]),c=p(c,d,e,f,t,6,a[60]),f=p(f,c,d,e,z,10,a[61]),e=p(e,f,c,d,l,15,a[62]),d=p(d,e,f,c,x,21,a[63]);b[0]=b[0]+c|0;b[1]=b[1]+d|0;b[2]=b[2]+e|0;b[3]=b[3]+f|0},_doFinalize:function(){var a=this._data,g=a.words,b=8*this._nDataBytes,j=8*a.sigBytes;g[j>>>5]|=128<<24-j%32;var k=q.floor(b/
4294967296);g[(j+64>>>9<<4)+15]=(k<<8|k>>>24)&16711935|(k<<24|k>>>8)&4278255360;g[(j+64>>>9<<4)+14]=(b<<8|b>>>24)&16711935|(b<<24|b>>>8)&4278255360;a.sigBytes=4*(g.length+1);this._process();a=this._hash;g=a.words;for(b=0;4>b;b++)j=g[b],g[b]=(j<<8|j>>>24)&16711935|(j<<24|j>>>8)&4278255360;return a},clone:function(){var a=u.clone.call(this);a._hash=this._hash.clone();return a}});t.MD5=u._createHelper(n);t.HmacMD5=u._createHmacHelper(n)})(Math);
(function(){var q=CryptoJS,r=q.enc.Utf8;q.algo.HMAC=q.lib.Base.extend({init:function(k,g){k=this._hasher=new k.init;"string"==typeof g&&(g=r.parse(g));var p=k.blockSize,q=4*p;g.sigBytes>q&&(g=k.finalize(g));g.clamp();for(var n=this._oKey=g.clone(),v=this._iKey=g.clone(),u=n.words,a=v.words,s=0;s<p;s++)u[s]^=1549556828,a[s]^=909522486;n.sigBytes=v.sigBytes=q;this.reset()},reset:function(){var k=this._hasher;k.reset();k.update(this._iKey)},update:function(k){this._hasher.update(k);return this},finalize:function(k){var g=
this._hasher;k=g.finalize(k);g.reset();return g.finalize(this._oKey.clone().concat(k))}})})();
;'use strict';
angular.module('ecs.directives.fieldMatch', [])
.directive('fieldMatch', function () {
    return {
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            var checkMatch, firstElement, theElement, _i, _len, _ref, _results,
                nameOfFieldToMatch = attrs.fieldToMatch;
            firstElement = angular.element(document.getElementById(nameOfFieldToMatch));
            checkMatch = function () {
                return scope.$apply(function () {
                    var valid = true,
                        firstElemVal = firstElement.val();
                    if (firstElement.hasClass('ng-dirty') && firstElemVal !== '') {
                        valid = elem.val() === firstElement.val();
                    }
                    ctrl.$setValidity(elem.attr('name'), valid);
                    return ctrl.$setValidity(nameOfFieldToMatch, valid);
                });
            };
            _ref = [firstElement, elem];
            _results = [];
            for (_i = 0, _len = _ref.length; _i < _len; _i++) {
                theElement = _ref[_i];
                _results.push(theElement.bind('keyup', function () {
                    return checkMatch();
                }));
            }
            return _results;
        }
    };
});
;
angular
    .module('ecs.service.constants', [])
    .constant('Constants', {
        BUSY_MESSAGES: {
            'en-US': {
                '100': 'Processing your order',
                '102': 'Searching for products...',
                '103': 'Loading more results...',
                '104': 'Loading product options',
                '106': 'Creating new user...',
                '108': 'Cancelling ordered item',
                '110': 'Processing your request',
                '112': 'Creating the ' + App.Session.RewardCampaignNamingConvention.toLowerCase() + 's. One moment please...',
                '113': 'Creating new ' + App.Session.RewardCampaignNamingConvention + ' Pack...',
                '114': 'Updating ' + App.Session.RewardCampaignNamingConvention + ' Pack...',
                '115': 'Submitting ' + App.Session.RewardCampaignNamingConvention + ' Pack...',
                '116': 'Approving ' + App.Session.RewardCampaignNamingConvention + ' Pack...',
                '118': 'Updating supervisor billing address...',
                '119': 'Redeeming your ' + App.Session.RewardCampaignNamingConvention.toLowerCase() + '...',
                '120': 'Updating supervisor shipping address...',
                '121': 'Loading products...',
                '122': 'Verifying credit card...',
                '123': 'Confirming user information...',
                '124': 'Updating Payment Method...',
                '125': 'Verifying payment details...',
                '126': 'Resending Gift Certificate...',
                '127': 'Refining results...',
                '128': 'Linking user account...',
                '129': 'Creating Store Pass Event...',
                '130': 'Updating cart...',
                '131': 'Updating...',
                '132': 'Searching...',
                '133': 'Resending...',
                '134': 'Adding additional recipient....',
                '135': 'Saving...',
                '136': 'Finalizing Personalized Artwork...',
                '137': 'Loading...'
            }
        },

        LABELS: {
            'en-US': {
                'P': 'Quarterly SWAG Balance',
                'U': 'Annual Uniforms Balance',
                'REWARD': 'Reward Balance',
                'AH': 'Animal Health Limit',
                'CC': 'Consumer Care Balance'
            }
        },

        CURRENCY_SYMBOLS: {
            'AED': ['\u062F', '\u002E', '\u0625', '\u002E', '\u200F'],
            'AFN': ['\u060B'],
            'ALL': ['\u004C', '\u0065', '\u006B'],
            'AMD': ['\u058F'],
            'ARS': ['\u0024'],
            'AUD': ['\u0024'],
            'AZN': ['\u043C', '\u0430', '\u043D', '\u002E'],
            'BAM': ['\u041A', '\u041C'],
            'BDT': ['\u09F3'],
            'BGN': ['\u043B', '\u0432', '\u002E'],
            'BHD': ['\u062F', '\u002E', '\u0628', '\u002E', '\u200F'],
            'BND': ['\u0024'],
            'BOB': ['\u0042', '\u0073', '\u002E'],
            'BRL': ['\u0052', '\u0024'],
            'BWP': ['\u0050'],
            'BYR': ['\u0042', '\u0072'],
            'BZD': ['\u0042', '\u005A', '\u0024'],
            'CAD': ['\u0024'],
            'CDF': ['\u0046', '\u0043'],
            'CHF': ['\u0046', '\u0072', '\u002E'],
            'CLP': ['\u0024'],
            'CNY': ['\u00A5'],
            'COP': ['\u0024'],
            'CRC': ['\u20A1'],
            'CZK': ['\u004B', '\u010D'],
            'DKK': ['\u006B', '\u0072', '\u002E'],
            'DOP': ['\u0052', '\u0044', '\u0024'],
            'DZD': ['\u062F', '\u002E', '\u062C', '\u002E', '\u200F'],
            'EGP': ['\u062C', '\u002E', '\u0645', '\u002E', '\u200F'],
            'ERN': ['\u0045', '\u0052', '\u004E'],
            'ETB': ['\u0045', '\u0054', '\u0042'],
            'EUR': ['\u20AC'],
            'GBP': ['\u00A3'],
            'GEL': ['\u10DA', '\u002E'],
            'GTQ': ['\u0051'],
            'HKD': ['\u0024'],
            'HNL': ['\u004C', '\u002E'],
            'HRK': ['\u006B', '\u006E'],
            'HTG': ['\u0047'],
            'HUF': ['\u0046', '\u0074'],
            'IDR': ['\u0052', '\u0070'],
            'ILS': ['\u20AA'],
            'INR': ['\u20B9'],
            'IQD': ['\u062F', '\u002E', '\u0639', '\u002E', '\u200F'],
            'IRR': ['\u0631', '\u064A', '\u0627', '\u0644'],
            'ISK': ['\u006B', '\u0072', '\u002E'],
            'JMD': ['\u004A', '\u0024'],
            'JOD': ['\u062F', '\u002E', '\u0627', '\u002E', '\u200F'],
            'JPY': ['\u00A5'],
            'KES': ['\u004B', '\u0053', '\u0068'],
            'KGS': ['\u0441', '\u043E', '\u043C'],
            'KHR': ['\u17DB'],
            'KRW': ['\u20A9'],
            'KWD': ['\u062F', '\u002E', '\u0643', '\u002E', '\u200F'],
            'KZT': ['\u20B8'],
            'LAK': ['\u20AD'],
            'LBP': ['\u0644', '\u002E', '\u0644', '\u002E', '\u200F', '\u200F'],
            'LKR': ['\u0DBB', '\u0DD4', '\u002E'],
            'LTL': ['\u004C', '\u0074'],
            'LYD': ['\u062F', '\u002E', '\u0644', '\u002E', '\u200F', '\u200F'],
            'MAD': ['\u062F', '\u002E', '\u0645', '\u002E', '\u200F', '\u200F'],
            'MDL': ['\u004C'],
            'MKD': ['\u0434', '\u0435', '\u043D', '\u002E'],
            'MMK': ['\u004B'],
            'MNT': ['\u20AE'],
            'MOP': ['\u004D', '\u004F', '\u0050'],
            'MVR': ['\u0783', '\u002E'],
            'MXN': ['\u0024'],
            'MYR': ['\u0052', '\u004D'],
            'NGN': ['\u20A6'],
            'NIO': ['\u0043', '\u0024'],
            'NOK': ['\u006B', '\u0072'],
            'NPR': ['\u0930', '\u0941'],
            'NZD': ['\u0024'],
            'OMR': ['\u0631', '\u002E', '\u0639', '\u002E', '\u200F', '\u200F'],
            'PAB': ['\u0042', '\u002F', '\u002E'],
            'PEN': ['\u0053', '\u002F', '\u002E'],
            'PHP': ['\u20B1'],
            'PKR': ['\u0052', '\u0073'],
            'PLN': ['\u007A', '\u0142'],
            'PYG': ['\u20B2'],
            'QAR': ['\u0631', '\u002E', '\u0642', '\u002E', '\u200F', '\u200F'],
            'RON': ['\u006C', '\u0065', '\u0069'],
            'RSD': ['\u0434', '\u0438', '\u043D', '\u002E'],
            'RUB': ['\u04BB', '\u002E'],
            'RWF': ['\u0052', '\u0057', '\u0046'],
            'SAR': ['\u0631', '\u002E', '\u0633', '\u002E', '\u200F'],
            'SEK': ['\u006B', '\u0072'],
            'SGD': ['\u0024'],
            'SOS': ['\u0053'],
            'SYP': ['\u0644', '\u002E', '\u0633', '\u002E', '\u200F', '\u200F'],
            'THB': ['\u0E3F'],
            'TJS': ['\u0441', '\u043C', '\u043D'],
            'TMT': ['\u006D', '\u002E'],
            'TND': ['\u062F', '\u002E', '\u062A', '\u002E', '\u200F', '\u200F'],
            'TRY': ['\u20BA'],
            'TTD': ['\u0054', '\u0054', '\u0024'],
            'TWD': ['\u004E', '\u0054', '\u0024'],
            'UAH': ['\u20B4'],
            'USD': ['\u0024'],
            'POINTS': [''],
            'UYU': ['\u0024', '\u0055'],
            'UZS': ['\u0441', '\u045E', '\u043C'],
            'VEF': ['\u0042', '\u0073', '\u002E', '\u0046', '\u002E'],
            'VND': ['\u20AB'],
            'XAF': ['\u0046', '\u0043', '\u0046', '\u0041'],
            'XCD': ['\u0045', '\u0043', '\u0024'],
            'XOF': ['\u0043', '\u0046', '\u0041'],
            'YER': ['\u0631', '\u002E', '\u064A', '\u002E', '\u200F', '\u200F'],
            'ZAR': ['\u0052']
        },


        ERROR_MESSAGES: {
            'en-US': {
                '-1': 'Not implemented yet.',

                '200': 'Looks like we had an issue completing your request. Please try again. If this continues to happen, Contact our Customer Care team.',

                '300': 'Unfortunately the resource you are looking for cannot be found.',
                '301': 'Oops! Important header data is missing.',
                '302': 'Hmm. The header date for some reason is invalid.',
                '303': 'My apologies, but we cannot verify the header in the submission.',
                '304': 'Not sure what happened but it looks like the key is not valid. ',
                '305': 'We apologize for the inconvenience, your session appears to have timed out. Please sign out and sign in again.',
                '306': 'We apologize for the inconvenience, but you do not have access to perform that operation.',
                '307': 'We apologize for the inconvenience, but you do not have access to perform that operation.',
                '308': 'What did you do?? The message format is incorrect.',

                //400 are for Business Rule Exception
                '400': 'We have looked for it, but that information cannot be found. Try again',
                '401': 'As it turns out there is already a similar record and we cannot have duplicates.',
                '402': 'It looks like there is some data missing from the submission.',
                '403': 'Hmm. The system is reporting that the data is invalid.',
                '404': 'Oh dear. You\'ve exceeded the purchase limit for this product.',
                '405': 'We\'re sorry, we could not verify your information. Please double check that you entered everything correctly.',
                '406': 'Oops. The employee id entered is not valid. ',
                '407': 'Please try again. The promo code you have entered is not valid. ',
                '408': 'My apologies but unfortunately the gift certificate entered is not valid. Clean your glasses and try again.',
                '409': 'For some reason the system is reporting you are an inactive employee.',
                '409b': 'The system is reporting this as an inactive account.',
                '410': 'Hey! It looks like the employee is already registered.',
                '411': 'This store pass is no longer active and cannot be registered. Either it has expired or the pass has already been used.',
                '412': 'Hey... welcome back! This Store Pass has already been registered.',
                '413': 'This is most unfortunate, but we could not complete the order. This is most likely because one of the item in your order is no longer available to be purchased. Please try to go through the entire checkout again.',
                '414': 'Unfortunately we can not back order your selected product.',
                '415': 'Sorry! You can\'t purchase more than we have available.',
                '416': 'The Employee Purchase policy rules require us to only allow 6 of any product per day.',
                '417': 'The Employee Purchase policy rules require us to only allow 6 of any product per day.',
                '418': 'Sorry! This exceeds your employee balance.  Please remove one or more items from the cart to be within your purchase limit.',
                '419': 'Oh dear! That gift certificate is not valid. Please check the numbers you have entered.',
                '420': 'Credit Card Payment Failed! The card was either declined or the Security Code and Billing Address does not match the information on file with your credit card. Please verify your information and try again.',
                '423': 'Sorry. The product is not valid.',
                '424': 'Sorry. We can\'t find the information for this cart. Please refresh your browser.',
                '425': 'Sorry. You do not appear to have access to a valid store.',
                '426': 'Sorry! This store pass cannot be used in the online stores.',
                '427': 'The user name you have entered already exists. Please try a different user name.',
                '428': 'Please enter a valid postal code.',
                '429': 'Hmmm. Please try entering your credit card information again. The bank is reporting that the card number is invalid.',
                '430': 'This credit card number has been previously saved for a customer account. For fraud prevention, we cannot allow the same credit card to be saved more than once. If you feel like this is a mistake, please contact our customer care department. Otherwise, please unselect the Save Card option to continue with your order.',
                '431': 'Cannot ship your order to this address. Please select a different Shipping Address.',
                '432': 'We\'re sorry. You are not eligible to purchase this item.',
                '433': 'The Employee Id entered could not be validated for the requested store.',
                '434': 'The SearchWordForm record could not be found.',
                '435': 'The SearchRedirect record could not be found.',
                '436': 'Oh dear. This store pass cannot be used. Check the effective and expiration dates of the pass.',
                '437': 'Hmmm. We can\'t find that store pass. Check the pass id and password you entered.',
                '441': 'Sorry! This exceeds your store balance for Uniforms.',
                '442': 'Sorry! This exceeds your store balance for SWAG.',
                '443': 'Sorry, you cannot purchase uniforms and SWAG or prepaid items on the same order. Please complete your current purchase before trying to add this item to your cart.',
                '445': 'The Employee Purchase policy rules require that you enter your Codice Fiscal to proceed with your order.  Please enter it into the field below.',
                '448': 'This product has a required minimum to order. Please add the minimum quantity or more to your cart.',
                '450': 'Hmmm. Something is not right with this address. Please check the city, state/region, and postal code again.',
                '451': 'Sorry, you cannot purchase prepaid items with non-prepaid items. Please complete your current purchase before trying to add this item to your cart.',
                '452': 'Looks like this supervisor already exists. Please enter a different name or cancel this to go back and search for the supervisor.',
                '453': 'Oops! This email is not eligible for a Friends and Family pass.',
                '454': 'Hmmm... it looks like this email address is already linked to an active Friends and Family pass.',
                '455': 'Sorry! You have already created the maximum number of Friends and Family passes allowed.',
                '458': 'Sorry! This credit card has already been saved to an existing account. A single credit card may not be used for more than one account.',
                '459': 'Oops. We can\'t load your shopping cart. Please sign out and sign in again. If this continues, try clearing your cookies.',
                '460': 'Sorry! You must provide the required payment details before continuing.',
                '461': 'Hmmm. Looks like that budget code is not valid. Please provide a valid budget code to continue.',
                '462': 'Sorry! We need a valid department number to continue with your order. ',
                '463': 'Sorry! We need a valid business unit to continue with your order. ',
                '464': 'Please select a purchase reason for each item in your purchase!',
                '465': 'Sorry, this is not a valid Gift Certificate order!',
                '466': 'Unfortunately, this Gift Certificate is already activated. We cannot update the recipient.',
                '467': 'Unfortunately, we cannot remove this promo code during checkout. Please go to your cart to remove this promo code first, then proceed through checkout again.',
                '468': 'Hmmm. It appears you\'ve already added this promo code to your cart.',
                '469': 'Sorry! Looks like you\'ve used this promo code before. It can only be used once!',
                '470': 'Hmmm. Looks like that cost center is not valid. Please provide a valid cost center to continue.',
                '471': 'Sorry! You must choose a different payment method to purchase all the items in your order.',
                '472': 'Sorry! That dealer already exist.',
                '473': 'What, are you raising a farm? This exceeds the limit of 6 Animal Health products per calendar year.',
                '474': 'Whoa there! This exceeds your available balance for Consumer Care products.',
                '475': 'Hmmm. Looks like that GL Account is not valid. Please provide a valid GL Account to continue.',
                '476': 'Oh dear! You\'ve fully redeemed your reward. Sorry, you can\'t redeem it again!',
                '477': 'Sorry, this product is not available for you to purchase.',
                '478': 'Hmm. We are not able to link this account to your SSO Identity. Please create a new account.',
                '479': 'You cannot purchase VWRCATALYST products and other items on the same order. To add this item to your cart, you must first complete your current order or you can remove the current items from your cart.',
                '480': 'Hmm. Let\'s try that again. That is not a valid email alias.',
                '481': 'Sorry. This person is not eligible to approve VIP Store Pass event requests.',
                '482': 'Sorry. The order you are accessing doesn\'t need approval.',
                '483': 'We\'re sorry. You must access the Company Store through Single Sign On (SSO) using your Microsoft Domain Credentials to register.',
                '484': 'Sorry. This promo code can only be used for an order with 1 single item. You\'ll need to remove the extra items from your cart.',
                '485': 'Oh dear. None of the items in your cart are eligible for this promo code.',
                '486': 'Sorry. You have applied a promo code to your cart that only allows 1 single item. Either complete your current order or remove the promo code.',
                '487': 'Uh oh. Looks like that Dealer User Id is not valid',
                '490': 'This product cannot be purchased without first applying your promo code to your order. Please view your cart details, apply your promo code, and then proceed to checkout.',
                '491': 'We could not load the budget amounts for your purchase. Please try again at a later time.',
                '492': 'You have exceeded the available amount of your budget. Please remove some items from your cart to be within the budget.',
                '493': 'You cannot purchase products for your budget with other items on the same order. Please review the items in your cart.',
                '494': 'Uh oh! We got an error getting the estimated shipping amounts from the Carrier. Please refresh your browser and try again.',
                '495': 'Sorry, we could not authorize your card for the amount of your order. Please try a different credit card. Contact your bank or financial institution if you feel this is incorrect.',
                '496': 'Sorry, your card was declined. Please try a different credit card. Contact your bank or financial institution if you feel this is incorrect.',
                '497': 'Oops. Check the expiration date for your credit card. Looks like it is no longer valid.',
                '498': 'Hmmm. Your card was declined due to an invalid CVV/CV2 security code. You may need to double check the security code you entered for your card.',
                '499': 'Sorry, Your card was not honored by the bank. Please try a different card.',
                '4000': 'Uh oh! We got an error connecting to the Service Provider to authorize your credit card. Please try again at a later time.',

                '4001': 'Sorry! The NVA number has to match the the Dealership where this order is being sent. Please enter the correct NVA number or go back and change where this order is shipping.',
                '4002': 'Sorry, the shipping carrier is reporting that your shipping address is invalid. Please check the address and try again.',
                '4003': 'Sorry, we cannot ship to a PO Box address.',
                '4004': 'Your shipping address was rejected by the Microsoft Distribution Center. Please edit your shipping address and verify that Address line 1, address line 2, and the city is not longer than 35 characters. Then you can proceed to checkout again.',
                '4005': 'Oh no. Sorry, we cannot complete your order. The inventory for these items could not be confirmed by the Microsoft Distribution centers. ',
                '4006': 'Unfortunately, we cannot accept your credit card. Your financial institution is reporing that your Billing Address does not match the information on file for your credit card. Please verify this information and try again. ',
                '4007': 'Sorry, this ' + App.Session.RewardCampaignNamingConvention.toLowerCase() + ' cannot be reset because it has already shipped or is currently being processed.',
                "4008": "Sorry, there is a problem with your %additionalInfo%.",
                '4009': 'Sorry, we could not authorize your card due to an incomplete billing address. Please verify your billing address in your profile.',

                // customer screening
                '4010': 'Sorry, there is an issue with your account preventing this action. If this problem persists, please contact customer service.',
                '4011': 'Your Customer account is under review. When/if the account clears, transactions for this customer will be allowed. Please verify the customer account information is correct.',
                '4012': 'Your customer account was not approved. Transactions for this customer are not allowed.',
                '4013': 'There seems to be an error in the information submitted. To proceed with next steps, please check the data submitted.',
                '4014': 'Service is currently unavailable. Please try again later.',
                '4015': 'User data cannot be modified',

                // address info
                '4100': 'Address name is required.',
                '4101': 'Address name contains invalid characters.',
                '4102': 'Address name is too short.',

                // for gift code reward messages
                "800": 'Hmmm, the gift code you are trying to redeem do not exist. Please enter a valid gift code and try again.',
                "801": 'Unfortunately the reward you are trying to redeem already expired.',

                //500 are for Security Exceptions
                "500": "The user account specified cannot be found.",
                "501": "Sorry! The username or password is invalid. Please try again.",
                "502": "The user is not authorized to perform such actions.",
                "503": "Password is not valid. Please see password rules.",
                //Website Error Codes (moved the "Added by Mike Section to here"
                "600": "We're sorry but an error has occurred.  Please try again.",
                "601": "Sorry, but you need to login, or create an account, to save an item to favorites.",
                "602": "We're sorry but an error has occurred.  Please try again.",
                "603": "%product% has been added to favorites.",
                "604": "Product sent to %SendToName%.",
                "605": "We're sorry! The requested quantity is more that our current quantity available for this item.",
                "606": "We're sorry but there are no %option% options available for order.",
                "607": "We're sorry but you cannot order more than the current quantity available for some of these items. We've adjusted the quantity below. Please try again.",
                "608": "You must specify the desired quantity for at least one item to add to your cart.",
                "609": "%product% has been added to favorites and you will receive an e-mail when this item is back in stock.",
                "610": "You can\'t checkout with 0? Please specify the desired quantity to add this item to your cart.",
                "611": "We're sorry but the card you supplied could not be authorized with the supplied information.",
                "615": "We could not process your request.  Please verify you have provided all required information and try again.",
                "616": "We cannot ship this order to your selected address. Please select or add a different address.",
                "617": "For your security, please re-enter your Payment information.",
                "618": "The credit card expiration date is not valid.  Please provide a valid date.",
                "619": "Your selected shipping address has changed. Please review your shipping information again.",
                '620': 'Hmmm. Please try entering your credit card information again. The bank is reporting that the card number is invalid.',
                '622': 'Your request has not been sent. Please complete the reCAPTCHA verification.',
                '624': 'Oops. Looks like we had an error. Please try again.',
                '625': 'You must agree to saving this credit card to your account before continuing.',
                '626': 'The access code could not be verified. Please provide the correct access code.',
                '627': 'Please add at least one recipient information.',
                '628': 'Your communication preferences have been updated!',
                '629': 'Just a sec! We need your personalized info for this product before we can add it to your cart.',
                '630': 'Hold up!! We need your email address in order to create the VIP Store Pass Event.',
                '631': 'Wait a sec! We need you to tell us why you are rejecting these passes. Please provide some comments.',
                '632': 'An email has been sent to the Store Pass Event sponsor for approval of your passes.',
                '633': 'To send your Data Subject Access Request, you must enter the details of your request and confirm you are the Data Subject.',
                '634': 'To send your Data Consent Withdrawal Request, you must sign the form by selecting at least one of the confirmation checkboxes.',
                '635': 'You must select the I Agree checkbox to update your Data Subject Consent preference.',
                '636': 'Thank you for updating your Data Consent preference, you may withdraw your consent at anytime with the DATA SUBJECT CONSENT WITHDRAWAL FORM.',
                '637': 'Sorry. You must select your country of residence before you can continue.',
                '638': 'Hold up there partner! We need you to complete the payment details.',
                '639': 'Avast matey. Ye will needs t\' pick yer free item. We didn\' add anythin\' t\' yer cart.',
                '640': 'Sorry, this is not an approved Third Party Shipper Account number for this store.',
                '641': 'Hold up there partner! We need you to complete the delivery options.',
                '642': 'Sorry, the date can not be over 60 days out from the current date',
                '643': 'Address name is too short.  Please provide a two word name.',
                '660': 'Added to your cart.',
                '661': 'Items added to cart.',
                '662': 'Removed from cart.',
                '664': 'Your cart has been cleared!',
                '666': 'Promo code has been applied!',
                '668': 'Promo code has been removed.',
                '670': 'Updated your cart.',
                '671': 'Your product personalization has been updated.',
                '672': App.Session.RewardCampaignNamingConvention + ' successfully reset.',
                '673': App.Session.RewardCampaignNamingConvention + ' successfully resent.',
                '674': 'End Date successfully updated.',
                '675': 'Recipient successfully added to ' + App.Session.RewardCampaignNamingConvention.toLowerCase() + '.',

                '678': 'Total length of first and last name cannot be more than 35 characters.',
                '679': 'Your gift certificate has been sent to the new recipient.',
                '680': 'Your billing address has been updated.',
                '682': 'Your new credit card has been added to your account.',
                '683': 'Shipping address was successfully added.',
                '684': 'Shipping address successfully updated.',
                '685': 'Customer information has been updated.',
                '686': 'Thank you! Your order has been placed.',
                '687': 'The Item has been removed.',
                '688': 'Your gift certificate was successfully activated and added to your balance.',
                '689': 'Shipping address has been successsfully removed.',
                '690': 'Thank you! You will receive an email shortly with your new link.',
                '691': 'The item has been successfully cancelled from your order.',
                '692': 'The credit card was successfully saved.',
                '693': 'Thank you. Your credit card has been deleted.',
                '694': 'Thank you. Your credit card expiration date has been updated',
                '695': 'Thank you. Your order confirmation e-mail should be on its way.',
                '696': 'Thank you. Your digital download e-mail should be on its way.',
                '698': 'Digital download successfully updated.',
                '699': 'Oops! Please only edit one memo at a time.',

                // 700 - admin messages
                "700": "The Search Translation was added.",
                "701": "The Search Translation was updated.",
                "702": "The Search Translation was deleted.",
                "700": "The Search Redirect was added.",
                "701": "The Search Redirect was updated.",
                "702": "The Search Redirect was deleted.",
                "703": "A request has been submitted to activate this product. The customer will receive an e-mail with the product key when the activation is complete.",
                "704": "The Digital Download notification has been resent.",
                "705": "Available Region successfully added."

            }
        },

        BLURBS: {
            'en-US': {
                'cartreview': {
                    default: {
                        default: '*before applicable taxes',
                        'BUNDLEDTAXES': '*includes duties and taxes if applicable'
                    },
                    'MSE': {
                        default: ''
                    }
                },
                'cartsummary': {
                    default: {
                        default: ''
                    },
                    'MSE': {
                        default: '',
                        'BUNDLEDTAXES': '(including VAT)'
                    }
                },
                'checkoutreview': {
                    default: {
                        default: '',
                        'BUNDLEDTAXES': '*includes duties and taxes if applicable'
                    },
                    'MSE': {
                        default: '',
                        'BUNDLEDTAXES': '(including VAT)'
                    }
                },
                'order': {
                    default: {
                        default: ''
                    },
                    'MSE': {
                        default: '',
                        'BUNDLEDTAXES': 'Includes VAT and applicable fees'
                    }
                }
            }
        }
    });;angular
    .module('ecs.service.common', [])
    .factory('Common', [
        '$log',
        '$rootScope',
        '$location',
        'Constants',
        '$timeout',
        'EcsLocale',
        function ($log, $rootScope, $location, Constants, $timeout, EcsLocale) {

            var genericErrorMessage = '600', //"We're sorry but an error has occurred.  Please try again.",
                cartInitialized = false,
                currentCatalog = '',
                isDst = undefined,
                storedShippingData = {},
                embargoedCountries = ["BY", "RU", "SY"],
                micstores = ["MIC", "MEC", "MSE", "MIP", "MDE", "MKT", "MSU", "MRE", "MRR", "MCM"],
                freeShippingStores = ["MIC"],
                freeShippingThreshold = 35.00,
                shippingChargeAmount = 9.99,
                //history = [],
                historyCounter = -1;


            return {

                showLoader: function (num, keepOpen) {

                    $rootScope.$broadcast('loader_show', num, keepOpen);
                },

                hideLoader: function () {

                    $rootScope.$broadcast('loader_hide', true);
                },

                getStoredShippingData: function () {
                    return storedShippingData;
                },

                storeShippingData: function (address) {
                    storedShippingData = address;
                },

                clearStoredShippingData: function () {
                    storedShippingData = {};
                },

                getMessage: function (num) {
                    return Constants.BUSY_MESSAGES['en-US'][num];
                },

                getLabel: function (id) {
                    return Constants.LABELS['en-US'][id];
                },

                linkTo: function (path) {

                    $location.path(path);
                },

                preventDefault: function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }
                },

                /*
                    Facet code
                */

                refineSearch: function (scope, facetToRemove, value) {

                    scope.noFacetsVisible = false;

                    if (value) {
                        value.IsSelected = !value.IsSelected;
                    }

                    this.setActiveFacets(scope, facetToRemove);

                    scope.getItems(null, null);


                },

                isFreeShippingStores: function (storeCode) {
                    return freeShippingStores.includes(storeCode);
                },

                getFreeShippingHelpMessage: function (scope, cartItems, shippingMethods) {
                    var isFreeShippingEligible = this.isFreeShippingStores(scope.store.StoreCode || '') && ((shippingMethods.length > 0 && !shippingMethods[0].IsInternational) || shippingMethods.length == 0);
                    if (isFreeShippingEligible) {
                        var remainingAmount = 0;
                        var isFreeShipping = true;
                        scope.showFreeShippingHelpMessage = true;
                        if (cartItems.length > 0 && cartItems.some(ci => this.isPromotionalProduct(ci.ProductNumber))) {
                            var promoAmount = 0;
                            cartItems.filter(ci => this.isPromotionalProduct(ci.ProductNumber)).forEach(ci => Number(promoAmount += (ci.Price * ci.Qty)));
                            isFreeShipping = Number(promoAmount > this.getFreeShippingThreshold());
                            remainingAmount = parseFloat(this.getFreeShippingThreshold() - promoAmount).toFixed(2);

                            if (!isFreeShipping && shippingMethods.length > 0 && shippingMethods[0].IsFree) {
                                scope.shippingMethods[0].IsFree = false;
                                scope.shippingMethods[0].EstimatedAmount = shippingChargeAmount;
                            }
                        }

                        scope.freeShippingHelpMessage = isFreeShipping ? `Best day ever! Your order qualifies for free shipping!` : `You’re almost there, just $${remainingAmount} more on Merch for free shipping on your order!`;
                    }
                },

                getFreeShippingThreshold: function () {
                    return freeShippingThreshold;
                },

                getShippingChargeAmount: function () {
                    return shippingChargeAmount;
                },

                isMsDcProduct: function (productNumber) {
                    return (productNumber.toLowerCase().startsWith('mic28t') || productNumber.toLowerCase().startsWith('mic29t'));
                },

                isPromotionalProduct: function (productNumber) {
                    return !this.isMsDcProduct(productNumber) && !productNumber.toLowerCase().startsWith('mic28e');
                },

                isMicrosoftStore: function (storeCode) {
                    return micstores.includes(storeCode);
                },

                getEmbargoedCountries: function () {
                    return embargoedCountries;
                },

                setActiveFacets: function (scope, facetToRemove) {
                    var arr = [],
                        facetsObj;

                    facetsObj = this.updateFacetsObj(scope, facetToRemove);

                    for (var facetName in facetsObj) {
                        var obj = {};
                        obj.Name = facetsObj[facetName].Name;
                        obj.Value = facetsObj[facetName].Value;
                        arr.push(obj);
                    }

                    scope.activeFacets = arr;
                },

                updateFacetsObj: function (scope, facetToRemove) {

                    var facets = scope.facets,
                        obj = {};

                    if (facetToRemove !== 'all') {
                        for (var i = 0, ilen = facets.length; i < ilen; i += 1) {
                            var facet = facets[i];

                            //If it is a price search, then do not include the Price Facet in the FacetObj
                            if (!(scope.isPriceSearch && facet.Name === "Price")) {

                                for (var j = 0, jlen = facet.Values.length; j < jlen; j += 1) {
                                    var value = facet.Values[j];

                                    if (value.IsSelected) {

                                        if (!facetToRemove || facetToRemove.Value !== value.Value) {
                                            obj[value.Value] = facet.Values[j];
                                            obj[value.Value].Name = facet.Name;
                                        }

                                    }
                                }
                            }
                        }
                    }

                    return obj;
                },


                getFacets: function (scope, omitStartingComma) {

                    var facets = !omitStartingComma ? [""] : [],
                        activeFacets = scope.activeFacets;

                    if (scope.isPriceSearch) {
                        facets.push('price=' + scope.priceFilter);
                        facets.push('catalog=' + scope.catalog);
                    }

                    for (var i = 0, len = activeFacets.length; i < len; i += 1) {
                        var facet = activeFacets[i];
                        facets.push(facet.Name + '=' + facet.Value);
                    }

                    return facets.join(',');

                },

                toggleFacet: function (scope, facetName) {
                    if (scope.facetHidden[facetName] !== undefined) {
                        scope.facetHidden[facetName] = !scope.facetHidden[facetName];
                    } else {
                        scope.facetHidden[facetName] = true;
                    }
                },



                /*
                    End Facet code
                */

                focusElement: function (el) {
                    $timeout(function () {
                        $(el).focus();
                    }, 100);
                },

                changeFocus: function (el) {
                    if (event.type == 'click') {
                        $(el).focus();
                    }
                },


                getLoadingMessage: function (url) {
                    var splitUrl = url.split('/'),
                        defaultMessage = 'Processing',
                        keyword = splitUrl[splitUrl.length - 2];

                    return Constants.BUSY_MESSAGES["en-US"][keyword] || defaultMessage;
                },

                handleGetCheckoutCartErrors: function (res) {
                    var errorCode = res.data.errorCode;

                    if (errorCode && errorCode === '404') {
                        Common.showMessage('danger', '418'); //This exceeds your employee balance.  Please remove ...
                        $location.path('#/cart');
                    }

                },

                toggleHelp: function ($event, selector) {
                    selector = selector || '.help-info';
                    var target = $($event.currentTarget);
                    target.next(selector).slideToggle();

                    var curText = target.text().toLowerCase().trim();
                    if (curText === 'click to expand')
                        $($event.currentTarget).html(' <i class="fa fa-minus"></i> Click to collapse');
                    else if (curText === 'click to collapse')
                        $($event.currentTarget).html(' <i class="fa fa-plus"></i> Click to expand');
                },

                //Bread crumbs now done via URL
                //setCurrentCatalogName: function(catalog) {

                //	if (currentCatalog !== catalog) {
                //		currentCatalog = catalog;
                //		this.resetHistoryCounter();
                //	}

                //},

                //getCurrentCatalogName: function () {

                //	return currentCatalog;
                //},

                //clearCurrentCatalogName: function() {

                //	currentCatalog = undefined;
                //},

                //addToHistory: function (data) {
                //	if (data !== history[history.length - 1]) {
                //		history.push(data);
                //	}

                //},

                getHistoryCounter: function () {

                    return historyCounter;
                },

                //resetHistoryCounter: function() {
                //	historyCounter = -1;
                //},

                incrementHistoryCounter: function (next, current) {
                    //History Counter will be -1 for all pages except the product detail page.
                    //if we are navigating from one PDP to another PDP, we decrement this counter
                    //this counter is then used on the maincontroller back function, so that we can properly go back the right number of
                    //pages. 

                    if (next === undefined || next === null || current === undefined || current === null) {
                        historyCounter = -1;
                        return;
                    }

                    var currentUriParts = current.split('#'),
                        nextUriParts = next.split('#');

                    if (currentUriParts.length < 1 || nextUriParts.length < 1) {
                        historyCounter = -1;
                        return;
                    }

                    //Get the angular path (after the #) and split the routes by /
                    var currentPath = currentUriParts && currentUriParts[1] ? currentUriParts[1].split('/') : [],
                        nextPath = currentUriParts && currentUriParts[1] ? currentUriParts[1].split('/') : [];

                    var currentRoute = currentPath[0], nextRoute = nextPath[0];
                    if (currentRoute === '' && currentPath.length >= 1)
                        currentRoute = currentPath[1];
                    if (nextRoute === '' && currentPath.length >= 1)
                        nextRoute = nextPath[1];

                    //If our next page is not the product detail, just set it to go back 1 page
                    if (nextRoute !== 'product')
                        historyCounter = -1;
                    else {
                        //If our current page is not the product detail, just set it to go back 1 page
                        if (currentRoute !== 'product')
                            historyCounter - 1;
                        else
                            //Both current and next page are product detail, increment the history counter
                            historyCounter -= 1;
                    }
                },

                //getPreviousLocationLabel: function () {
                //	var previousUrl = history[history.length - 2],
                //		splitPreviousUrl = previousUrl ? previousUrl.split('/') : [''],
                //		currentUrl = history[history.length - 1],
                //		splitCurrentUrl = currentUrl ? currentUrl.split('/') : [''],
                //		lastString = undefined,
                //		currentCatalogName = this.getCurrentCatalogName();

                //	if (currentCatalogName) {
                //		lastString = currentCatalogName;
                //	}

                //	if (splitCurrentUrl[1] !== 'product') {
                //		this.clearCurrentCatalogName();
                //		this.resetHistoryCounter();
                //	} else {
                //		this.incrementHistoryCounter();
                //	}

                //	return lastString;
                //},


                setCartInitialized: function () {
                    cartInitialized = true;

                },

                getCartInitialized: function () {
                    return cartInitialized;

                },

                clearCartInitialized: function () {
                    cartInitialized = false;
                },

                pad: function (num) {
                    num = num.toString();
                    if (num.length == 1) return "0" + num;
                    return num;
                },

                getGrandTotal: function (giftCertificateAmount, totalAmount, baseCurrency, currencyExchangeRates) {

                    if (!angular.isDefined(giftCertificateAmount)) return false;

                    var gcAmount = Number(EcsLocale.exchangeRate(giftCertificateAmount, baseCurrency, currencyExchangeRates)),
                        totAmount = Number(EcsLocale.exchangeRate(totalAmount, baseCurrency, currencyExchangeRates));

                    if (gcAmount > totAmount) {
                        totAmount = 0;
                    } else {
                        totAmount = totAmount - gcAmount;
                    }

                    return EcsLocale.formatCurrency(totAmount, baseCurrency, currencyExchangeRates);

                },


                isDaylightSavingsTime: function (date) {
                    // Calculate DST start day, it is the last sunday of March
                    var _year = date.getUTCFullYear(),
                        start_day = (31 - ((((5 * _year) / 4) + 4) % 7)),
                        SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0)),

                        // Calculate DST end day, it is the last sunday of October
                        end_day = (31 - ((((5 * _year) / 4) + 1) % 7)),
                        SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0)),
                        isDst = 0;

                    if (date > SUMMER_start && date < SUMMER_end) {
                        isDst = 1;
                    };

                    return isDst;
                },

                //Value parameter - required. All other parameters are optional.
                isDate: function (value, sepVal, dayIdx, monthIdx, yearIdx) {
                    try {
                        //Change the below values to determine which format of date you wish to check. It is set to dd/mm/yyyy by default.
                        var DayIndex = dayIdx !== undefined ? dayIdx : 1;
                        var MonthIndex = monthIdx !== undefined ? monthIdx : 0;
                        var YearIndex = yearIdx !== undefined ? yearIdx : 2;

                        value = value.replace(/-/g, "/").replace(/\./g, "/");
                        var SplitValue = value.split(sepVal || "/");
                        var OK = true;
                        if (!(SplitValue[DayIndex].length == 1 || SplitValue[DayIndex].length == 2)) {
                            OK = false;
                        }
                        if (OK && !(SplitValue[MonthIndex].length == 1 || SplitValue[MonthIndex].length == 2)) {
                            OK = false;
                        }
                        if (OK && SplitValue[YearIndex].length != 4) {
                            OK = false;
                        }
                        if (OK) {
                            var Day = parseInt(SplitValue[DayIndex], 10);
                            var Month = parseInt(SplitValue[MonthIndex], 10);
                            var Year = parseInt(SplitValue[YearIndex], 10);

                            if (OK = ((Year > 1900) && (Year < new Date().getFullYear() + 100))) {
                                if (OK = (Month <= 12 && Month > 0)) {

                                    var LeapYear = (((Year % 4) == 0) && ((Year % 100) != 0) || ((Year % 400) == 0));

                                    if (OK = Day > 0) {
                                        if (Month == 2) {
                                            OK = LeapYear ? Day <= 29 : Day <= 28;
                                        }
                                        else {
                                            if ((Month == 4) || (Month == 6) || (Month == 9) || (Month == 11)) {
                                                OK = Day <= 30;
                                            }
                                            else {
                                                OK = Day <= 31;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        return OK;
                    }
                    catch (e) {
                        return false;
                    }
                },

                getDateStringInPast: function (monthsInPast, daysInPast, yearsInPast) {
                    var d = new Date();
                    d.setMonth(d.getMonth() - monthsInPast);
                    d.setYear(d.getFullYear() - yearsInPast);
                    d.setDate(d.getDate() - daysInPast);

                    return (this.pad(d.getMonth() + 1) + '/' + this.pad(d.getDate()) + '/' + d.getFullYear())

                },

                convertJsonDateString: function (jsonDate, notUtc) {

                    if (jsonDate) {

                        var utcOffset = -5, // eastern tz becuase that's where the servers are
                            _date = new Date(),
                            timeZoneOffset = 0,
                            adjustedTime = '',
                            timeStamp = parseInt(jsonDate.substr(6));

                        _date.setTime(timeStamp);

                        this.isDst = this.isDst || this.isDaylightSavingsTime(_date);

                        timeZoneOffset = utcOffset + this.isDst * 60 * 60 * 1000;

                        _date.setTime(timeStamp + timeZoneOffset);

                        if (notUtc) {
                            adjustedTime = this.pad(_date.getMonth() + 1) + '/' + this.pad(_date.getDate()) + '/' + _date.getFullYear();
                        }
                        else {
                            adjustedTime = this.pad(_date.getUTCMonth() + 1) + '/' + this.pad(_date.getUTCDate()) + '/' + _date.getUTCFullYear();
                        }
                        return adjustedTime;

                    } else {

                        return null;
                    }
                },

                convertJsonLongDateString: function (jsonDate, notUtc) {

                    if (jsonDate) {

                        var utcOffset = -5, // eastern tz becuase that's where the servers are
                            _date = new Date(),
                            timeZoneOffset = 0,
                            adjustedTime = '',
                            timeStamp = parseInt(jsonDate.substr(6));

                        _date.setTime(timeStamp);

                        this.isDst = this.isDst || this.isDaylightSavingsTime(_date);

                        timeZoneOffset = utcOffset + this.isDst * 60 * 60 * 1000;

                        _date.setTime(timeStamp + timeZoneOffset);
                        var monthNames = [
                            "January", "February", "March",
                            "April", "May", "June", "July",
                            "August", "September", "October",
                            "November", "December"
                        ];
                        if (notUtc) {
                            adjustedTime = monthNames[_date.getMonth()] + ' ' + this.pad(_date.getDate()) + ', ' + _date.getFullYear();
                        }
                        else {
                            adjustedTime = monthNames[_date.getUTCMonth()] + ' ' + this.pad(_date.getUTCDate()) + ', ' + _date.getUTCFullYear();
                        }
                        return adjustedTime;

                    } else {

                        return null;
                    }
                },

                convertJsonDateDOWString: function (jsonDate, notUtc) {

                    if (jsonDate) {

                        var utcOffset = -5, // eastern tz becuase that's where the servers are
                            _date = new Date(),
                            timeZoneOffset = 0,
                            adjustedTime = '',
                            timeStamp = parseInt(jsonDate.substr(6));

                        _date.setTime(timeStamp);

                        this.isDst = this.isDst || this.isDaylightSavingsTime(_date);

                        timeZoneOffset = utcOffset + this.isDst * 60 * 60 * 1000;

                        _date.setTime(timeStamp + timeZoneOffset);
                        var monthNames = [
                            "Jan.", "Feb.", "Mar.",
                            "Apr.", "May", "June", "July",
                            "Aug.", "Sep.", "Oct.",
                            "Nov.", "Dec."
                        ];

                        var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

                        if (notUtc) {
                            adjustedTime = dayNames[_date.getDay()] + ', ' + monthNames[_date.getMonth()] + ' ' + this.pad(_date.getDate());
                        }
                        else {
                            adjustedTime = dayNames[_date.getUTCDay()] + ', ' + monthNames[_date.getUTCMonth()] + ' ' + this.pad(_date.getUTCDate());
                        }
                        return adjustedTime;

                    } else {

                        return null;
                    }
                },



                convertJsonDateObject: function (jsonDate) {

                    if (jsonDate) {

                        var utcOffset = -5, // eastern tz becuase that's where the servers are
                            _date = new Date(),
                            timeZoneOffset = 0,
                            adjustedTime = '',
                            timeStamp = parseInt(jsonDate.substr(6));

                        _date.setTime(timeStamp);

                        this.isDst = this.isDst || this.isDaylightSavingsTime(_date);

                        //For now, until I can fully understand this, don't include the timezone offset
                        //timeZoneOffset = utcOffset + this.isDst * 60 * 60 * 1000;

                        _date.setTime(timeStamp + timeZoneOffset);

                        return _date;

                    } else {

                        return null;
                    }
                },


                getMonths: function () {
                    return ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
                },

                getYears: function () {
                    var years = []
                    thisYear = new Date().getFullYear();

                    for (var i = Number(thisYear); i < thisYear + 10; i += 1) {
                        years.push(i.toString());
                    }

                    return years;

                },

                padNumber: function (s) { return (s < 10) ? '0' + s : s; },

                getStandardDateRangeFilter: function () {
                    var today = new Date(),
                        last30 = new Date(),
                        last6 = new Date(),
                        last9 = new Date();

                    today.setDate(today.getDate() + 1);
                    last30.setDate(last30.getDate() - 30);
                    last6.setMonth(last6.getMonth() - 6);
                    last9.setMonth(last9.getMonth() - 9);

                    var todayString = [this.padNumber(today.getMonth() + 1), this.padNumber(today.getDate()), today.getFullYear()].join('/'),
                        last30String = [this.padNumber(last30.getMonth() + 1), this.padNumber(last30.getDate()), last30.getFullYear()].join('/'),
                        last6String = [this.padNumber(last6.getMonth() + 1), this.padNumber(last6.getDate()), last6.getFullYear()].join('/'),
                        last9String = [this.padNumber(last9.getMonth() + 1), this.padNumber(last9.getDate()), last9.getFullYear()].join('/');


                    var filters = [{ query: last30String + '||' + todayString, label: 'Last 30 days' }
                        , { query: last6String + '||' + todayString, label: 'Last 6 months' }
                        , { query: last9String + '||' + todayString, label: 'Last 9 months' }];

                    var thisYear = today.getFullYear();
                    var earliestYear = Number(thisYear - 4);

                    for (var i = Number(thisYear); i > thisYear - 5; i -= 1) {
                        filters.push({ query: '1/1/' + i.toString() + '||12/31/' + i.toString(), label: i.toString() });
                    }

                    filters.push({ query: '1/1/2000||12/31/' + earliestYear.toString(), label: 'Before ' + earliestYear.toString() });

                    return filters;
                },

                getFYStandardDateRangeFilter: function () {

                    var today = new Date(),
                        last30 = new Date(),
                        last6 = new Date(),
                        last9 = new Date();

                    today.setDate(today.getDate() + 1);
                    last30.setDate(last30.getDate() - 30);
                    last6.setMonth(last6.getMonth() - 6);
                    last9.setMonth(last9.getMonth() - 9);

                    var todayString = [this.padNumber(today.getMonth() + 1), this.padNumber(today.getDate()), today.getFullYear()].join('/'),
                        last30String = [this.padNumber(last30.getMonth() + 1), this.padNumber(last30.getDate()), last30.getFullYear()].join('/'),
                        last6String = [this.padNumber(last6.getMonth() + 1), this.padNumber(last6.getDate()), last6.getFullYear()].join('/'),
                        last9String = [this.padNumber(last9.getMonth() + 1), this.padNumber(last9.getDate()), last9.getFullYear()].join('/');


                    var filters = [{ query: last30String + '||' + todayString, label: 'Last 30 days' }
                        , { query: last6String + '||' + todayString, label: 'Last 6 months' }
                        , { query: last9String + '||' + todayString, label: 'Last 9 months' }],

                        thisYear = today.getFullYear(),
                        thisMonth = today.getMonth();

                    if (thisMonth >= 6) //Month is 0 based
                        thisYear++;

                    for (var i = Number(thisYear); i > thisYear - 5; i -= 1) {
                        p = i - 1;
                        filters.push({ query: '7/1/' + p.toString() + '||7/1/' + i.toString(), label: 'Fiscal ' + i.toString() });
                    }

                    var firstFY = Number(thisYear - 5);

                    filters.push({ query: '1/1/2000||7/1/' + firstFY.toString(), label: 'Before Fiscal ' + Number(firstFY + 1).toString() });

                    return filters;
                },

                goHome: function () {

                    $rootScope.$broadcast('goHome');
                },

                showMessageNew: function (type, context, msgId, msgArgs, data) {
                    var message = Constants.ERROR_MESSAGES["en-US"][msgId] || Constants.ERROR_MESSAGES["en-US"][genericErrorMessage];

                    if (msgArgs) {
                        message = message.replace(msgArgs.replace, msgArgs.value);
                    }

                    if (!data) {
                        data = {};
                    }

                    if (message && message !== null && message !== '') {
                        $rootScope.$broadcast('addAlert', { type: type, context: context, msg: message, data: data });
                    }
                },

                showMessage: function (type, messageIdOrMessage, details, onAutoRemoved) {

                    var message = Constants.ERROR_MESSAGES["en-US"][genericErrorMessage];

                    if (messageIdOrMessage) {
                        message = messageIdOrMessage.length <= 4 ? Constants.ERROR_MESSAGES["en-US"][messageIdOrMessage] : messageIdOrMessage;
                    }

                    //showMessageNew(type, 'None', message, details, {});

                    if (message && message !== null && message !== '') {
                        $rootScope.$broadcast('addAlert', { type: type, context: 'None', msg: message, data: details, onAutoRemoved: onAutoRemoved });
                    }
                },

                clearQueryStringValue: function (property) {

                    if ($location.$$search[property]) {
                        delete $location.$$search[property];
                        $location.$$compose();
                    }
                },

                convertArrayToObj: function (arr, key) {

                    var obj = {};

                    for (var i = 0, len = arr.length; i < len; i += 1) {
                        obj[arr[i][key]] = arr[i];

                    }

                    return obj;
                },

                getNewCheckoutUTSID: function () {

                    var d = new Date().getTime();
                    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                        var r = (d + Math.random() * 16) % 16 | 0;
                        d = Math.floor(d / 16);
                        return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                    });

                    return uuid;
                },

                getCurrentCheckoutUTSID: function () {
                    var pathParts = $location.path().split("/");
                    if (pathParts.length === 0)
                        return getNewCheckoutUTSID();

                    return pathParts[pathParts.length - 1];
                },

                getReturnUrl: function () {
                    var pathParts = $location.path().split("/");
                    if (pathParts.length < 2)
                        return 'Shop';


                    var returnUrl;
                    switch (pathParts[1].toUpperCase()) {
                        case "CART":
                            returnUrl = "Show/Cart";
                            break;
                        case "CHECKOUT":
                            returnUrl = "Show/Checkout";
                            break;
                        case "PRODUCT":
                            if (pathParts.length < 3)
                                returnUrl = "Shop";
                            else
                                returnUrl = "Show/Product/" + pathParts[pathParts.length - 1];
                            break;
                        case "CATALOG":
                            if (pathParts.length < 3)
                                returnUrl = "Shop";
                            else
                                returnUrl = "Show/Catalog/" + pathParts[pathParts.length - 1];
                            break;
                        default:
                            returnUrl = "Shop";
                    }

                    return App.Configuration.RootPath + returnUrl;
                },

                convertToJsonDateString: function (date) {

                    if (date) {
                        var _date;

                        if (typeof date === "string") {
                            _date = new Date(date);
                        } else if (typeof date === "object") {
                            _date = date;
                        } else {
                            return null;
                        }

                        var timeStamp = _date.getTime(),
                            jsonDate = "\/Date(%timestamp%)\/";

                        return jsonDate.replace('%timestamp%', timeStamp);

                    } else {

                        return null;
                    }
                },

                validateCreditCard: function (ccNumb, ccType) {
                    var valid = "0123456789"  // Valid digits in a credit card number
                    var len = ccNumb.length;  // The length of the submitted cc number
                    var iCCN = parseInt(ccNumb);  // integer of ccNumb
                    var sCCN = ccNumb.toString();  // string of ccNumb
                    sCCN = sCCN.replace(/^\s+|\s+$/g, '');  // strip spaces
                    var iTotal = 0;  // integer total set at zero
                    var bNum = true;  // by default assume it is a number
                    var bResult = false;  // by default assume it is NOT a valid cc
                    var temp;  // temp variable for parsing string
                    var calc;  // used for calculation of each digit
                    // Determine if the ccNumb is in fact all numbers
                    for (var j = 0; j < len; j++) {
                        temp = "" + sCCN.substring(j, j + 1);
                        if (valid.indexOf(temp) == "-1") { bNum = false; }
                    }
                    // if it is NOT a number, you can either alert to the fact, or just pass a failure
                    if (!bNum) {
						    /*alert("Not a Number");*/bResult = false;
                    }
                    // Determine if it is the proper length 
                    if ((len == 0) && (bResult)) {  // nothing, field is blank AND passed above # check
                        bResult = false;
                    } else {  // ccNumb is a number and the proper length - let's see if it is a valid card number
                        var ccFirstDigit = ccNumb.substring(1, 2); //for token we check second digit
                        if ((ccFirstDigit == 3 && ccType == "AMEX") || (ccFirstDigit == 4 && ccType == "VISA") ||
                            (ccFirstDigit == 5 && ccType == "MC") || (ccFirstDigit == 2 && ccType == "MC") || (ccFirstDigit == 6 && ccType == "DISC")) {
                            bResult = true;  // This IS (or could be) a valid credit card number.
                        }
                        else {
                            bResult = false; // Credit Card Number and Card Type does not match
                        }

                    }
                    return bResult; // Return the results
                },

                parseCreditCardTokenMessage: function (eventMessage, cb) {
                    e = eventMessage || {};
                    var messageOrigin = (e.origin || '').toLowerCase();

                    if (messageOrigin.indexOf('cardconnect') >= 0) {
                        var token = JSON.parse(e.data);
                        cb(token.message);
                    } else if (messageOrigin.indexOf('snappay') >= 0) {
                        var data = (e.data || '').split('&').reduce((map, item) => {
                            var s = item.split('=');
                            map[s[0]] = s[1];
                            return map;
                        }, {});

                        cb(data.token, data.brand);
                    }
                },

                getBlurb: function (id, conditionalKey) {
                    try {
                        var lang = 'en-US';
                        var l1 = Constants.BLURBS[lang][id];
                        var l2 = $rootScope.store.StoreCode in l1 ? l1[$rootScope.store.StoreCode] : l1['default'];
                        var text = conditionalKey && conditionalKey in l2 ? l2[conditionalKey] : l2['default'];
                        return text || '';
                    } catch (er) {
                        return '';
                    }
                },

                deepCopy: function (inObject) {
                    let outObject, value, key;
                    if (typeof inObject !== "object" || inObject === null) {
                        return inObject; // Return the value if inObject is not an object  
                    }
                    // Create an array or object to hold the values  
                    outObject = Array.isArray(inObject) ? [] : {};


                    for (key in inObject) {
                        value = inObject[key];
                        // Recursively (deep) copy for nested objects, including arrays    
                        outObject[key] = this.deepCopy(value);
                    }

                    return outObject;
                },

                orderBy: function (data, isAscending, key) {
                    var query = [...data];
                    if (isAscending) {
                        query = this.sortByProperty(data, key, isAscending);
                        return query;
                    } else {
                        query = this.sortByProperty(data, key, isAscending);
                        return query;
                    }
                },

                sortByProperty: function (array, property, isAscending) {
                    if (Array.isArray(array) && array.length === 0) {
                        return [];
                    }
                    if (Array.isArray(array) && array.length > 0) {
                        let sortedArray = [...array];
                        sortedArray.sort((a, b) => {
                            let propertyA = a[property];
                            let propertyB = b[property];
                            if (isAscending) {
                                if (propertyA < propertyB) {
                                    return -1;
                                }
                                if (propertyA > propertyB) {
                                    return 1;
                                }

                                // names must be equal
                                return 0;
                            } else {
                                if (propertyA > propertyB) {
                                    return -1;
                                }
                                if (propertyA < propertyB) {
                                    return 1;
                                }

                                // names must be equal
                                return 0;
                            }
                        });
                        return sortedArray;
                    }
                },
            };

        }]);;angular
	.module('ecs.service.messaging', [])
	.factory('Messaging', [
		'$log',
        '$timeout',
		function ($log, $timeout) {

		    return function ($scope) {

		        var indexOf = function (needle) {
		            if (typeof Array.prototype.indexOf === 'function') {
		                indexOf = Array.prototype.indexOf;
		            } else {
		                indexOf = function (needle) {
		                    var i = -1, index = -1;

		                    for (i = 0; i < this.length; i++) {
		                        if (this[i] === needle) {
		                            index = i;
		                            break;
		                        }
		                    }

		                    return index;
		                };
		            }

		            return indexOf.call(this, needle);
		        },

            //basic method to initialize/reset the messages for the application.
            resetMessages = function () {

                var messagesToPersist = ['420'],
                    message = $scope.message || {},
                    errors = message ? message["errors"] : undefined;

                if (errors) {
                    if (errors.length > 0) {
                        for (var i = 0, len = errors.length; i < len; i += 1) {
                            var errMsg = errors[i];
                            if (!errMsg.data || indexOf.call(messagesToPersist, errMsg.data.errorCode) === -1) {
                                errors.splice(i, 1);
                            }

                        }
                    }

                } else {
                    message["errors"] = [];
                }

                message["alerts"] = [];

                $scope.message = message;

            },


            setSignInReturnUrl = function () {

                $scope.$signInReturnUrl = Common.getReturnUrl();
            },


            addAlert = function (alert) {
                $log.log(alert);

                //function to remove the item from the message collection.
                var remove = function () {
                    $log.log($scope.message);
                    $log.log($scope.message[type]);
                    $log.log(type);

                    var index = $scope.message[type].indexOf(alert); //find the index

                    //item may no longer exist within the messages (for instance removed manually)
                    if (index > -1) {
                        $scope.message[type].splice(index, 1);
                    }
                };

                /*
                type = (alert.type || 'warning').toLowerCase();

                //override for the error types
                if (indexOf.call(['danger', 'warning'], type) > -1) {
                    type = "errors";
                }

                //override for the alert types
                if (indexOf.call(['success'], type) > -1) {
                    type = "alerts";
                }

                //override for the pop-up types
                if (indexOf.call(['cart', 'share', 'favorite'], type) > -1) {
                    type = "popup";
                }
                */
                

                var type = 'popup',
                    items = $scope.message[type];

                if (!items ||  type == 'popup') {
                    $scope.message[type] = items = [];
                }

                var delay = 6000;
                
                $scope.message[type].push(alert);

                var timeoutHandle = $timeout(function () {
                    remove();
                    //console.log($scope.message);
                    if (alert.onAutoRemoved)
                        alert.onAutoRemoved();
                }, delay);

                //add the additional information to the alert. This can be used to reset
                //the timeout (if needed)
                alert.timeout = {
                    span: delay,
                    handle: timeoutHandle,
                    reset: function () {
                        window.clearTimeout(alert.timeout.handle);
                        alert.timeout.handle = $timeout(function () {
                            remove();
                        }, delay);
                    }
                };
            },

            closeMessage = function (type, index) {
                $scope.message[type].splice(index, 1);
            },

            closeAlert = function (index) {
                closeMessage('alerts', index);
            },

            closeError = function (index) {
                closeMessage('errors', index);
            };

		        return {

		            addAlert: addAlert,
		            closeAlert: closeAlert,
		            closeError: closeError,
		            closeMessage: closeMessage,
		            resetMessages: resetMessages,
		        }

		    }
		    
		}]);;angular
	.module('ecs.service.app-timeout', [])
	.factory('AppTimeout', [
        '$timeout',
        '$http',
        '$location',
		function ($timeout, $http, $location) {

            return function ($scope, $rootScope) {

		        // Timeout system

		        var deleteLCSEventListener = undefined,
                timeoutWarningDuration = 30,
                timeoutLastChanceDuration = 1,
                appTimeoutTimer = undefined,
                serverSideCheck = false,

                startApplicationTimeoutSystem = function (pollRate, useServerSideCheck) {
                    if (pollRate != null) {
                        timeoutWarningDuration = pollRate;
                    }
                    if (useServerSideCheck != null) {
                        serverSideCheck = useServerSideCheck;
                    }
                    if (!deleteLCSEventListener) {
                        deleteLCSEventListener = $scope.$on('$locationChangeStart', function (event) {
                            resetWarningTimer()
                        });
                    }

                },

                resetWarningTimer = function () {

                    startTimer(showTimeoutWarningModal, timeoutWarningDuration);

                },

                startTimer = function (callback, durationMinutes) {
                    if (appTimeoutTimer) {
                        $timeout.cancel(appTimeoutTimer);
                    };
                    appTimeoutTimer = $timeout(callback, durationMinutes * 1000 * 60);

                },

                remove_cancelApplicationTimeout = $scope.$on('cancelApplicationTimeout', function (event) {
                    resetWarningTimer();
                }),

                showTimeoutWarningModal = function () {
                    if (serverSideCheck) {
                        //If we use server side check, we ping the server and check if further action is needed.
                        url = App.Configuration.RootPath + ('Authentication/SessionCheck');

                        $http({
                            method: 'GET',
                            url: url,
                            headers: {
                                "Referrer": $location.absUrl()
                            }
                        })
                            .then(function (response) {
                                var data = response.data;

                                if (response.data != null && response.data.active != null) {
                                    if (response.data.active) {
                                        //all good, reset the timer.
                                        resetWarningTimer();
                                    }
                                    else {
                                        //We got an inactive result, let's redirect the user to log out.
                                        lastChanceExpred();
                                    }
                                }
                                else {
                                    //We didn't receive any data, perhaps they lost internet connection or the browser stopped handling the tab?
                                    //Server-side the session may still expire, but we won't auto-log them out, so just reset the timer again.
                                    resetWarningTimer();
                                }
                                //deferred.resolve(config);

                            }, function (rejection) {
                                console.log(rejection);
                            });
                    }
                    else {
                        //Standard, show modal and give the user an opportunity to renew the session timer.
                        $rootScope.$broadcast('showTimeoutWarningModal');

                        startTimer(lastChanceExpred, timeoutLastChanceDuration);
                    }

                },

                stopApplicationTimeoutSystem = function () {
                    remove_cancelApplicationTimeout();
                    deleteLCSEventListener();
                    $timeout.cancel(appTimeoutTimer);
                },

                lastChanceExpred = function () {

                    stopApplicationTimeoutSystem();
                    $scope.$goSessionTimeOut();

                };

		        return {
		            startApplicationTimeoutSystem: startApplicationTimeoutSystem
		        }

		    }
		    
		}]);;'use strict';

angular
    .module('ecs.service.cart', [])
    .service('CartService', [
        '$rootScope',
        '$cookieStore',
        'ShoppingCarts',
        'Customers',
        'Common',
        'StoreService',
        '$log',
        '$q',
        '$http',
        function ($rootScope, $cookieStore, ShoppingCarts, Customers, Common, StoreService, $log, $q, $http) {

            var successAddToCart = '660',
                successMultipleAddToCart = '661',
                successRemove = '662',
                successClear = '664',
                successPromo = '666',
                successRemovePromo = '668',
                successUpdateCartItem = '670',
                successUpdatePersonalization = '671';

            this.shoppingCart = {};
            this.loadingCart = false;


            this.numberOfItems = function () {

                return this.shoppingCart.numberOfItems;
            };

            this.freeShippingHelpMessage = function () {
                return (this.shoppingCart.freeShippingHelpMessage || "");
            };

            this.discountAmount = function () {

                return this.shoppingCart.discountAmount;
            };

            this.applyPromoCode = function (data) {
                var self = this;

                return ShoppingCarts.applyPromoCode(self.shoppingCart.cart.CartId, data)
                    .then(function (response) {
                        if (response.data) {
                            self.shoppingCart.cart = response.data;

                        }
                        self.updateCartTotals();
                        Common.showMessage('success', successPromo);
                        $rootScope.$broadcast('onCartChange');
                    });
            };

            this.removePromoCode = function (data) {
                var self = this;

                return ShoppingCarts.removePromoCode(self.shoppingCart.cart.CartId, data)
                    .then(function (response) {
                        if (response.data) {
                            self.shoppingCart.cart = response.data;

                        }
                        self.updateCartTotals();
                        Common.showMessage('success', successRemovePromo);
                        $rootScope.$broadcast('onCartChange');
                    });
            };

            this.updateCartItem = function (data, quantityUpdate) {
                var self = this;

                var qty = Number(data.Qty)
                if (!qty || qty === 0) {
                    self.removeCartItem(data);
                }
                else {
                    Common.showLoader('130');

                    ShoppingCarts.updateCartItem(self.shoppingCart.cart.CartId, data)
                        .then(async function (response) {
                            if (response.data) {
                                self.shoppingCart.cart = response.data;

                            }

                            if (quantityUpdate) {
                                await self.updateCartTotals();

                                //Common.showMessage('success', successUpdateCartItem);
                                Common.showMessageNew('cart', 'UpdateCartItem', successUpdateCartItem, null, {
                                    product: {
                                        name: data.Name,
                                        productSlug: data.ProductSlug,
                                        productNumber: data.ProductNumber,
                                        image: data.Image.Url,
                                        qty: data.Qty,
                                        price: data.Price,
                                        url: data.Url
                                    },
                                    cart: {
                                        total: self.shoppingCart.totalAmount,
                                        count: self.shoppingCart.numberOfItems,
                                        baseCurrency: self.shoppingCart.cart.BaseCurrency,
                                        currencyExchangeRates: self.shoppingCart.cart.CurrencyExchangeRates
                                    }
                                });

                                $rootScope.$broadcast('onCartChange');
                            }
                            else {
                                Common.showMessage('success', successUpdatePersonalization);
                            }
                        });
                }
            };


            this.addCartItem = function (data) {
                var self = this,

                    //the api requires a sub-set of data. very specific.
                    apiData = {
                        ProductNumber: data.ProductNumber,
                        Qty: data.Qty,
                        Price: data.Price,
                        DisplayPrice: data.DisplayPrice,
                        PurchaseProductNumber: data.PurchaseProductNumber,
                        IsDownload: data.IsDownload,
                        IsOnBackorder: data.IsOnBackorder,
                        PersonalizedInfo: data.PersonalizedInfo,
                        ThirdPartyPersonalizations: data.ThirdPartyPersonalizations,
                        CartItemPersonalizationLites: data.CartItemPersonalizationLites,
                        IsPreOrder: data.IsPreOrder,
                        BOGOProductNumber: data.BOGOProductNumber,
                        ExpectedLeadTime: data.ExpectedLeadTime
                    },
                    showAddToCartMessage = function () {
                        Common.showMessageNew('cart', 'AddCartItem', successAddToCart, null, {
                            product: {
                                name: data.Name,
                                productSlug: data.ProductSlug,
                                productNumber: data.ProductNumber,
                                image: data.Image,
                                qty: data.Qty,
                                price: data.Price,
                                DisplayPrice: data.DisplayPrice,
                                url: data.Url
                            },
                            cart: {
                                total: self.shoppingCart.totalAmount,
                                count: self.shoppingCart.numberOfItems,
                                baseCurrency: self.shoppingCart.cart.BaseCurrency,
                                currencyExchangeRates: self.shoppingCart.cart.CurrencyExchangeRates
                            }
                        });
                    };

                if (this.shoppingCart.cart) {

                    angular.deepExtend(apiData, { CartId: self.shoppingCart.cart.CartId, HasSellAndDisplayPriceProducts: false });

                    //We have an existing cart, just add the item
                    return ShoppingCarts.addCartItem(self.shoppingCart.cart.CartId, apiData)
                        .then(async function (response) {
                            if (response.data) {
                                self.shoppingCart.cart = response.data;

                            }
                            await self.updateCartTotals();
                            showAddToCartMessage();

                            //Common.showMessage('success', successAddToCart);
                            $rootScope.$broadcast('onCartChange');
                        });
                }
                else {
                    var user = $rootScope.user;

                    //We don't have a cart, so let's create one.
                    if (user.IsAnonymous) {
                        //Create Anonymous
                        return ShoppingCarts.createAnonymousCart(apiData)
                            .then(async function (response) {
                                if (response.data) {
                                    self.shoppingCart.cart = response.data;

                                    user.AnonCrtId = self.shoppingCart.cart.CartGuid;
                                    self.setAnonymousCart(user.AnonCrtId);
                                }
                                await self.updateCartTotals();
                                showAddToCartMessage();

                                $rootScope.$broadcast('onCartChange');
                            });
                    }
                    else {
                        //Create a cart for the customer
                        return Customers.createShoppingCart(user.CustomerId, apiData)
                            .then(async function (response) {
                                if (response.data) {
                                    self.shoppingCart.cart = response.data;

                                }
                                await self.updateCartTotals();
                                showAddToCartMessage();

                                $rootScope.$broadcast('onCartChange');
                            });
                    }
                }

            };

            this.addMultipleCartItems = function (dataArray, additional) {

                var self = this;

                self.additional = self.additional || additional;

                //the api requires a sub-set of data. very specific.
                //we are going to transition the array of information into our
                //api data.
                var apiData = dataArray.map(function (data) {
                    return {
                        ProductNumber: data.ProductNumber,
                        Qty: data.Qty,
                        Price: data.Price,
                        DisplayPrice: data.DisplayPrice,
                        PurchaseProductNumber: data.PurchaseProductNumber,
                        CartItemPersonalizationLites: data.CartItemPersonalizationLites,
                        IsDownload: data.IsDownload,
                        IsOnBackorder: data.IsOnBackorder,
                        BOGOProductNumber: data.BOGOProductNumber,
                        ExpectedLeadTime: data.ExpectedLeadTime
                    };
                });

                var showAddToCartMessage = function (additional) {
                    //we are going to pass the parent as the product. This will allow that information
                    //to be displayed as part of the messaging (product image, info, etc).
                    Common.showMessageNew('cart', 'AddMultipleCartItem', successMultipleAddToCart, null, {
                        product: {
                            name: additional.parent.Name,
                            productSlug: additional.parent.ProductSlug,
                            productNumber: additional.parent.ProductNumber,
                            image: additional.parent.Image,
                            qty: additional.parent.Qty,
                            price: additional.parent.Price,
                            DisplayPrice: additional.parent.DisplayPrice,
                            url: additional.parent.Url
                        },
                        products: dataArray.map(function (data) {
                            return {
                                name: data.Name,
                                productSlug: data.ProductSlug,
                                productNumber: data.ProductNumber,
                                image: data.Image,
                                qty: data.Qty,
                                price: data.Price,
                                DisplayPrice: data.DisplayPrice,
                                url: data.Url
                            };
                        }),
                        cart: {
                            total: self.shoppingCart.totalAmount,
                            count: self.shoppingCart.numberOfItems,
                            baseCurrency: self.shoppingCart.cart.BaseCurrency,
                            currencyExchangeRates: self.shoppingCart.cart.CurrencyExchangeRates
                        }
                    });

                    delete self.additional;
                };

                if (this.shoppingCart.cart) {
                    angular.deepExtend(apiData, {
                        CartId: self.shoppingCart.cart.CartId
                    });

                    //We have an existing cart, just add the item
                    return ShoppingCarts.addMultipleCartItem(self.shoppingCart.cart.CartId, apiData)
                        .then(async function (response) {
                            if (response.data) {
                                self.shoppingCart.cart = response.data;

                            }
                            await self.updateCartTotals();
                            showAddToCartMessage(self.additional);

                            $rootScope.$broadcast('onCartChange');
                        });
                }
                else {
                    //We don't have a cart, so let's create one. Pop a single item off the cart and create the cart with that
                    var item = apiData.pop();
                    var user = $rootScope.user;
                    if (user.IsAnonymous) {
                        //Create Anonymous
                        return ShoppingCarts.createAnonymousCart(item)
                            .then(async function (response) {
                                if (response.data) {
                                    self.shoppingCart.cart = response.data;
                                    user.AnonCrtId = self.shoppingCart.cart.CartGuid;
                                    self.setAnonymousCart(user.AnonCrtId);

                                }
                                if (apiData.length !== 0) {
                                    self.addMultipleCartItems(apiData, self.additional);
                                } else {
                                    //No more
                                    await self.updateCartTotals();
                                    showAddToCartMessage(self.additional);
                                    $rootScope.$broadcast('onCartChange');
                                }
                            });
                    }
                    else {
                        //Create a cart for the customer
                        return Customers.createShoppingCart(user.CustomerId, item)
                            .then(async function (response) {
                                if (response.data) {
                                    self.shoppingCart.cart = response.data;

                                }
                                if (apiData.length !== 0) {
                                    self.addMultipleCartItems(apiData);
                                } else {
                                    //No more
                                    await self.updateCartTotals();
                                    showAddToCartMessage(self.additional);
                                    $rootScope.$broadcast('onCartChange');
                                }
                            });
                    }
                }

            };


            this.removeCartItem = function (data) {
                var self = this;

                Common.showLoader('130');

                ShoppingCarts.removeCartItem(self.shoppingCart.cart.CartId, data)
                    .then(async function (response) {
                        if (response.data) {
                            self.shoppingCart.cart = response.data;

                        }
                        await self.updateCartTotals();
                        //Common.showMessage('success', successRemove);
                        Common.showMessageNew('cart', 'RemoveCartItem', successRemove, null, {
                            product: {
                                name: data.ProductName,
                                productSlug: data.ProductSlug,
                                productNumber: data.ProductNumber,
                                image: data.Image.Url,
                                qty: data.Qty,
                                price: data.Price,
                                url: data.Url
                            },
                            cart: {
                                total: self.shoppingCart.totalAmount,
                                count: self.shoppingCart.numberOfItems,
                                baseCurrency: self.shoppingCart.cart.BaseCurrency,
                                currencyExchangeRates: self.shoppingCart.cart.CurrencyExchangeRates
                            }
                        });

                        $rootScope.$broadcast('onCartChange');

                    });
            };



            this.getCart = function () {
                var deferred = $q.defer(),
                    self = this;

                //If cart is there return it. Though we are going to return it in a promise
                if (self.shoppingCart && self.shoppingCart.cart) {

                    setTimeout(function () {
                        deferred.resolve(self.shoppingCart);
                    }, 100);


                    return deferred.promise;
                }

                //If not.. load the cart and return the promise 
                return self.loadCart();

            };


            this.clearCart = function () {
                var self = this;

                self.setAnonymousCart('');
                ShoppingCarts.deleteCart(self.shoppingCart.cart.CartGuid)
                    .then(function (response) {
                        //Cart has been deleted, load an empty cart in the UI
                        self.loadEmptyCart();
                    });
            };


            this.loadCart = function (refreshCart) {

                var self = this;

                //This code will remove any older cart id cookies that may be around. New code now uses MVC controller for setting the cookie
                //We'll leave this here for a while just in case, but this specific cookie will no longer be used by the site
                var oldCartCookie = $cookieStore.get("anoncrtid");
                if (oldCartCookie) {
                    $cookieStore.remove("anoncrtid");
                }


                var user = $rootScope.user;
                var anonymousCartId = user.AnonCrtId;

                // Punchout stories EST 164,167,166,168
                if (!!user.PunchoutSessionId) {
                    anonymousCartId = null;
                }

                if (!self.shoppingCart || !self.shoppingCart.cart || refreshCart) {
                    if (!user.IsAnonymous) {
                        self.shoppingCart.isAnonymous = false;

                        if (!!anonymousCartId) {
                            user.AnonCrtId = null;
                            self.setAnonymousCart('');
                            //Transfer the cart to the logged in user
                            return Customers.transferShoppingCart(user.CustomerId, anonymousCartId)
                                .then(async function (response) {
                                    if (response.data.length > 0) {
                                        self.shoppingCart.cart = response.data[0];

                                    }
                                    await self.updateCartTotals();
                                    return self.shoppingCart;
                                });
                        }
                        else {
                            // Punchout stories EST 164,167,166,168
                            if (!!user.PunchoutSessionId) {
                                return ShoppingCarts.getCartByPunchoutSessionId(user.PunchoutSessionId)
                                    .then(async function (response) {
                                        if (!!response.data) {
                                            self.shoppingCart.cart = response.data;

                                        }
                                        await self.updateCartTotals();
                                        return self.shoppingCart;
                                    });
                            } else {
                                if (self.loadingCart) {
                                    self.cartLoadCallbacks = self.cartLoadCallbacks || [];
                                    var deferred = $q.defer();
                                    self.cartLoadCallbacks.push(deferred);
                                    return deferred.promise;
                                } else {
                                    self.loadingCart = true;

                                    return Customers.getShoppingCarts(user.CustomerId)
                                        .then(async function (response) {
                                            if (response.data.length > 0) {
                                                self.shoppingCart.cart = response.data[0];

                                            }
                                            await self.updateCartTotals();
                                            return self.shoppingCart;
                                        }).finally(() => {
                                            self.loadingCart = false;
                                            for (var p of (self.cartLoadCallbacks || [])) {
                                                p.resolve(self.shoppingCart);
                                            }
                                            self.cartLoadCallbacks = [];
                                        });
                                }
                            }
                        }
                    } else {
                        self.shoppingCart.isAnonymous = true;
                        if (!!anonymousCartId) {
                            return ShoppingCarts.getCartByGuid(anonymousCartId)
                                .then(async function (response) {
                                    self.shoppingCart.cart = response.data;

                                    await self.updateCartTotals();
                                    return self.shoppingCart;
                                });
                        }
                        else {
                            self.updateCartTotals();
                            //All we have is an empty cart to return
                            var deferred = $q.defer();
                            deferred.resolve(self.shoppingCart);
                            return deferred.promise;
                        }
                    }

                }


            };


            this.loadEmptyCart = function () {

                //Ensure we've got our global shopping cart info
                this.shoppingCart.cartItems = {};
                this.shoppingCart.cart = {};
                this.shoppingCart = {};
                this.shoppingCart.isAnonymous = $rootScope.user.IsAnonymous;
                this.updateCartTotals();
            };

            this.updateCartTotals = async function () {
                var storeInfo = null;
                var useSellDisplayPrice
                await StoreService.getStore().success(function (data) {
                    storeInfo = data.Store;
                    $rootScope.store = storeInfo;
                    useSellDisplayPrice = storeInfo.Functionality.UseSellDisplayPrice;
                });
                // check if store has display price value
                var subtotalAmount = 0,
                    totalDiscounts = 0,
                    totalQty = 0,
                    displaySubtotalAmount = 0;

                if (this.shoppingCart.cart && this.shoppingCart.cart.CartItems) {
                    var cartItems = this.shoppingCart.cart.CartItems;
                    for (var i = 0; i < cartItems.length; i++) {
                        subtotalAmount += Number(cartItems[i].Amount);
                        totalDiscounts += (Number(cartItems[i].DiscountAmount) + Number(cartItems[i].DiscountBundledAmount)) * Number(cartItems[i].Qty);
                        totalQty += Number(cartItems[i].Qty);
                        if (useSellDisplayPrice) {
                            if (!cartItems[i].DisplayPrice && !cartItems[i].IsOnDemand) {
                                displaySubtotalAmount += Number(cartItems[i].Amount);
                            } else {
                                displaySubtotalAmount += Number(cartItems[i].Qty * cartItems[i].DisplayPrice);
                            }
                            this.shoppingCart.cart.HasSellAndDisplayPriceProducts = this.shoppingCart.cart.CartItems.some(i => i.DisplayPrice != null);
                        }
                    }
                }

                if (this.shoppingCart.cart && this.shoppingCart.cart.PromoCodes) {
                    var cartPromos = this.shoppingCart.cart.PromoCodes;
                    for (var i = 0; i < cartPromos.length; i++) {
                        if (cartPromos[i].ApplyToTotal) {
                            totalDiscounts += cartPromos[i].Amount;
                        }
                    }
                }

                if (totalDiscounts > subtotalAmount)
                    totalDiscounts = subtotalAmount

                this.shoppingCart.numberOfItems = totalQty;
                this.shoppingCart.totalAmount = subtotalAmount - totalDiscounts;
                this.shoppingCart.subTotalAmount = subtotalAmount;
                this.shoppingCart.discountAmount = totalDiscounts;
                this.shoppingCart.displaySubtotalAmount = displaySubtotalAmount;
                this.shoppingCart.displayTotalAmount = displaySubtotalAmount - totalDiscounts;
                var that = this;

                if (!this.shoppingCart.isAnonymous) {
                    Customers.getAddresses($rootScope.user.CustomerId, 'shipping')
                        .then(function (response) {
                            $rootScope.addresses = response.data;
                            //$rootScope.loadingShippingAddresses = false;

                            $rootScope.showFreeShippingHelpMessage = that.isFreeShippingStores(storeInfo.StoreCode) && $rootScope.addresses[0].Country == "US";

                            if ($rootScope.showFreeShippingHelpMessage && !!that.shoppingCart.cart && that.shoppingCart.cart.CartItems.length > 0) {
                                that.getFreeShippingHelpMessage($rootScope, that.shoppingCart.cart.CartItems);
                                that.shoppingCart.freeShippingHelpMessage = $rootScope.freeShippingHelpMessage;
                                $rootScope.$broadcast('onHelpMessageChange');
                            }
                        });
                }

            };

            this.getFreeShippingHelpMessage = function (scope, cartItems) {
                return Common.getFreeShippingHelpMessage(scope, cartItems, []);
            };

            this.isFreeShippingStores = function (storeCode) {
                return Common.isFreeShippingStores(storeCode);
            };

            this.getFreeShippingThreshold = function () {
                return Common.getFreeShippingThreshold();
            };

            this.getShippingChargeAmount = function () {
                return Common.getShippingChargeAmount();
            };

            this.isPromotionalProduct = function (productNumber) {
                return Common.isPromotionalProduct(productNumber);
            };

            this.setAnonymousCart = function (cartGuid) {

                var endpointURL = App.Configuration.RootPath + 'User/AnonymousCart',
                    model = { CartGuid: cartGuid };

                $http({
                    method: "post",
                    url: endpointURL,
                    data: JSON.stringify(model)
                });

            };

            this.isItemInCart = function (productNumber) {
                var toReturn = false;

                //Not doing the foreach because I want to break the loop if found
                if (this.shoppingCart && this.shoppingCart.cart && this.shoppingCart.cart.CartItems) {
                    for (var i = 0; i < this.shoppingCart.cart.CartItems.length; i++) {
                        if (productNumber.localeCompare(this.shoppingCart.cart.CartItems[i].ProductNumber, 'en', { sensitivity: 'base' }) === 0) {
                            toReturn = true;
                            break;
                        }
                    }


                }
                return toReturn;
            };

            this.isAnyItemInCart = function (productsList) {
                var toReturn = false;

                //Not doing the foreach because I want to break the loop if found
                for (var i = 0; i < productsList.length; i++) {
                    if (this.isItemInCart(productsList[i].ProductNumber)) {
                        toReturn = true;
                        break;
                    }
                }
                return toReturn;
            };

            //Product Visible Fee helpers
            this.ItemsContainFee = function (FeeTypeId, items) {
                if (items) {
                    for (let i = 0; i < items.length; i++) {
                        if (items[i].VisibleFees) {
                            for (let v = 0; v < items[i].VisibleFees.length; v++) {
                                if (items[i].VisibleFees[v].Fee.FeeTypeId == FeeTypeId) {
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            };

            this.VisibleFeeTotal = function (FeeTypeId, items) {
                var feeTotal = 0;
                if (items) {
                    for (let i = 0; i < items.length; i++) {
                        feeTotal += this.VisibleFeeTotalForItem(FeeTypeId, items[i]);
                    }
                }
                return feeTotal;
            };

            this.VisibleFeeTotalForItem = function (FeeTypeId, item) {
                var feeTotal = 0;
                if (item.VisibleFees) {
                    for (let v = 0; v < item.VisibleFees.length; v++) {
                        if (item.VisibleFees[v].Fee.FeeTypeId == FeeTypeId) {
                            feeTotal += item.VisibleFees[v].Fee.Amount * item.Qty;
                        }
                    }
                }
                return feeTotal;
            };

            //searchShoppingCarts: function (params) {
            //    try {
            //        return new EcsResource(ShoppingCartsCallData.searchCarts).query(params);
            //    } catch (e) {
            //        $log.warn('searchShoppingCarts () :: Error ', e);
            //    }
            //},

            //this.loadCart(); // RF - commenting this out; causing duplicate call


        }]);
;'use strict';

angular
    .module('ecs.service.budgets', [])
    .service('BudgetsService', [
        '$rootScope',
        'Customers',
        'Employees',
        '$q',
        function ($rootScope, Customers, Employees, $q) {

            this.budgets = [];
            this.budgetsEnabled = false;

            this.returnBudgetAsPromise = function()
            {
                var self = this;

                var deferred = $q.defer();
                setTimeout(function () {
                    deferred.resolve(self.budgets);
                }, 100);

                return deferred.promise;
            }

            this.getBudgets = function (isRefresh) {
                if (isRefresh == undefined)
                    isRefresh = false;

                var self = this;

                //If budgets aren't available, return the budgets array
                if (!self.budgetsEnabled) {
                    return self.returnBudgetAsPromise();
                }

                //If budgets are loaded and it's not a refrsh, return the budgets array
                if (self.budgets && self.budgets.length > 0 && !isRefresh) {
                    return self.returnBudgetAsPromise();
                }

                //Otherwise load the cart and return the promise 
                return self.loadBudgets();

            };

            //Returns the promise for the API call to load the budgets
            this.loadBudgets = function () {

                var self = this;

                var currentUser = $rootScope.user;
                var currentStore = $rootScope.store;

                
                if (currentStore.Functionality.LegacyCustomBalances) {
                    //Old legacy code for MS EPP, BAY EPP, and MSU
                    if (currentUser.IsEmployee && currentUser.EmployeeId) {
                        return Employees.getPurchaseBalances(currentUser.EmployeeId)
                            .then(function (response) {
                                self.budgets = response.data;
                                return self.budgets;
                            });
                    }
                    else {
                        //Return promise with empty array. This is for users that are no longer active employees, but can still login to access their old orders.
                        self.budgets = [];
                        return self.returnBudgetAsPromise();
                    }
                }
                else {
                    return Customers.getPurchaseBalances(currentUser.CustomerId)
                        .then(function (response) {
                            self.budgets = response.data;
                            return self.budgets;
                        });
                }
            };

            this.init = function () {

                //Just capture if the budget is enabled on init
                this.budgetsEnabled = ($rootScope.store.Functionality.EmployeeBalances && !$rootScope.user.IsAnonymous);
            };

            this.init()

        }]);
;'use strict';

angular
    .module('ecs.service.address', [])
    .service('AddressService', [
        'Common',
        'Constants',
        'Objects',
        'Customers',
        '$log',
        'PostalCodeOptionalCountries',
        function (Common, Constants, Objects, Customers, $log, PostalCodeOptionalCountries) {

            this.activeShippingAddress = undefined;
            this.defaultShippingAddress = undefined;

            this.billingCountries = undefined;
            this.shippingCountries = undefined;
            this.fafCountries = undefined;

            this.getDefaultShippingAddress = function (custId) {

                return this.defaultShippingAddress;

            };

            this.isPostalCodeRequired = function (country) {
                return PostalCodeOptionalCountries.indexOf(country) === -1;
            };

            this.getActiveShippingAddress = function () {

                var address = this.activeShippingAddress,
                    cityStateZip = [];

                cityStateZip.push(address.City);
                cityStateZip.push(', ');
                cityStateZip.push(address.State);
                cityStateZip.push(address.PostalCode);

                address.cityStateZip = cityStateZip.join('');

                return address;
            };


            this.setActiveShippingAddress = function (address) {
                this.activeShippingAddress = address;
                return address;
            };

            this.setDefaultShippingAddress = function (address) {

                this.activeShippingAddress = address;

            };

            this.getAddress = function (customerId, type, addressid) {
                return Customers.getAddress(customerId, type, addressid);
            },


                this.getShippingAddress = function (custId, mode, addressId) {

                    // implement the promise structure  here ?...

                    var shippingAddress = this.getDefaultShippingAddress();

                    if (shippingAddress) {
                        return shippingAddress;

                    } else {

                        return Customers.getAddresses(custId, 'shipping', mode, addressId);

                    }

                };

            this.getCountries = function ($scope, type, cb) {
                var countries = [],
                    self = this;

                if (!type)
                    type = 'BILLING';

                if (type.toUpperCase() == "BILLING" && !!self.billingCountries && self.billingCountries.length > 0) {
                    $scope.countries = self.billingCountries;
                    if (cb) {
                        cb();
                    }
                } else if (type.toUpperCase() == "FAF" && !!self.fafCountries && self.fafCountries.length > 0) {
                    $scope.countries = self.fafCountries;
                    if (cb) {
                        cb();
                    }
                } else if (!!self.shippingCountries && self.shippingCountries.length > 0) {
                    $scope.countries = self.shippingCountries;
                    if (cb) {
                        cb();
                    }
                } else {
                    Objects.getCountries({ type: type }).then(function (response) {
                        $scope.countries = !!$scope.store.StoreCode && Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                        if (type.toUpperCase() == "BILLING")
                            self.billingCountries = $scope.countries;
                        else if (type.toUpperCase() == "FAF")
                            self.fafCountries = $scope.countries;
                        else
                            self.shippingCountries = $scope.countries;
                        if (cb) {
                            cb();
                        }
                    });
                }
            };

            this.statesObj = {};

            this.getStateOrRegions = function ($scope, country) {
                var states = [],
                    scope = $scope,
                    self = this;

                scope.postalCodeRequired = this.isPostalCodeRequired(country);

                //Country changed, so check the Tax jurisidictions
                this.updateTaxJurisdictions(scope);

                return Objects.getStateOrRegions({ country: country }).then(function (response) {
                    scope.states = response.data;
                    self.statesObj = Common.convertArrayToObj(response.data, 'RegionCode');
                });
            };

            /*
                    By default the County/Jurisdiction dropdown is not visible. 
                    After the user enters both the City and PostalCode and country is US, 
                    get the TaxJurisdictions for the City and Postal Code via the API. 
                    If more than 1 jurisdiction is returned, show the County/Jurisdiction 
                    drop down
                    */

            this.updateTaxJurisdictions = function (scope, refresh) {

                try {

                    if (refresh) {
                        scope.customer[scope.addressType].TaxJurisdictionCode = '';
                    }

                    var hasCity = scope.customer[scope.addressType].City,
                        hasPostalCode = scope.customer[scope.addressType].PostalCode,
                        isCountryUS = scope.customer[scope.addressType].Country === 'US';

                    if (isCountryUS) {
                        if (hasCity && hasPostalCode) {
                            this.getTaxJuridictions(scope);
                        }
                    }
                    else {
                        //Not US, make sure we don't have the error message
                        this.setPostalAndCityValidity(scope, true);
                    }

                } catch (e) {
                    $log.error('registerCtrl > updatetaxJurisdictions() error = ', e);
                }

            };


            this.getTaxJuridictions = function (scope) {

                var params = {},
                    self = this;

                params.city = scope.customer[scope.addressType].City;
                params.postalcode = scope.customer[scope.addressType].PostalCode;

                scope.taxJurisdictions = [];
                scope.taxJurisdictionsLoading = true;

                return Objects.getTaxJurisdictions(params)
                    .then(function (response) {
                        scope.taxJurisdictionsLoading = false;
                        var form = scope[scope.activeForm];

                        self.updateForTaxJurisdiction(scope, response.data);
                        self.setPostalAndCityValidity(scope, true);

                        if (form) {
                            form.TaxJurisdiction.$setValidity("required", true);
                        }

                    }, function (response) {
                        scope.taxJurisdictionsLoading = false;
                        self.setPostalAndCityValidity(scope, false);
                    });

            };

            this.setPostalAndCityValidity = function (scope, bool) {

                var form = scope[scope.activeForm];

                if (form) {
                    form.PostalCode.$setValidity("doesNotResolveTaxJurisdiction", bool);
                    form.City.$setValidity("doesNotResolveTaxJurisdiction", bool);
                    form.City.$setPristine();
                    form.PostalCode.$setPristine();
                }

            };

            this.updateForTaxJurisdiction = function ($scope, data) {
                $scope.taxJurisdictions = data;

                if (data.length > 0) {
                    $scope.customer[$scope.addressType].TaxJurisdictionCode = $scope.customer[$scope.addressType].TaxJurisdictionCode || data[0].TaxJurisdictionCode;
                    var state = this.statesObj[data[0].State];
                    var originalState = $scope.customer[$scope.addressType].State || '';
                    const apoFpo = ['AA', 'AE', 'AP'];
                    const isApoFpo = apoFpo.some(function (term) {
                        return (originalState.indexOf(term) !== -1)
                    });

                    if (state) {
                        if (!isApoFpo)
                            $scope.customer[$scope.addressType].State = state.RegionCode;
                    } else {
                        $log.error('registerCtrl.js > updateForTaxJurisdiction() > state not found in data.');
                    }
                }

            };

            //Only needed if we have a register form where user is allowed to change first (or potentially last) name
            this.testNameValidity = function (form, customer) {
                var valid = true,
                    isNameTooLong = function () {
                        return (customer.firstName + ' ' + customer.lastName).length > 35;
                    };

                if (isNameTooLong()) {
                    valid = false;
                }

                form.FirstName.$setValidity("length", valid);
                form.LastName.$setValidity("length", valid);

                return valid;
            };
        }]);
;/// <reference path="impl/orders.js" />
'use strict';

angular
    .module('ecs.service.checkout', [])
    .service('CheckoutService', [
        'CartService',
        'ShoppingCarts',
        'AddressService',
        'Orders',
        'Common',
        'Constants',
        'Customers',
        '$rootScope',
        '$uibModal',
        '$log',
        '$q',
        function (CartService, ShoppingCarts, AddressService, Orders, Common, Constants, Customers, $rootScope, $uibModal, $log, $q) {


            /*
            If only one PaymentMethod is returned, choose that by default and don't show the Payment Methods screen. 
            Then show the Shipping Address Section for the selected Payment Method
            
            */
            this.getPaymentMethods = function () {

                return [{ PaymentMethodCode: "YP-0001", PaymentMethod: "Credit Card", IsTerms: false }];
                /*
                var self = this;
                
                Orders.getPaymentMethods()
                .then(function (response) {
    
                    // need to add popover mesages to db...
                    //
                    return response;
                    
                });
                
                */


            };

            

            this.getCustomerPaymentMethods = function (customerId, cartId) {
                var self = this;
                var paymentMethods = [];

                return ShoppingCarts.getPaymentMethods(cartId).then(function (response) {
                    var pm = response.data.filter(pm => pm.IsVisible);
                    var paymentMethodsLegacy = pm.filter(pm => !(!!(pm.ApprovalTypeId)));
                    paymentMethods.push(...paymentMethodsLegacy);

                    var paymentMethodsWithoutRequiredCustomers = pm.filter(pm => !!(pm.ApprovalTypeId) && pm.ApprovalTypeId !== 148);
                    paymentMethods.push(...paymentMethodsWithoutRequiredCustomers);

                    var paymentMethodsWithRequiredCustomers = pm.filter(pm => (pm.PaymentMethodApproverGroups.length > 0) && pm.PaymentMethodApproverGroups.some(pmag => (pmag.PaymentMethodApproverGroupCustomers.length > 0) && pmag.PaymentMethodApproverGroupCustomers.some(c => c.StoreUser.CustomerId === customerId)));
                    paymentMethods.push(...paymentMethodsWithRequiredCustomers);

                    self.customerPaymentMethods = paymentMethods;
                  });
            };


            this.showValidationErrorModal = function (errorArray) {

                var self = this,
                    modalInstance = $uibModal.open({
                        templateUrl: 'validationErrorsContent',
                        controller: 'ValidationErrorsModalCtrl',
                        resolve: {
                            errorArray: function () {
                                return errorArray;
                            }
                        }
                    });

                modalInstance.result.then(function () {

                    $log.log('Dismissing modal');
                }, function () {
                    //when cancelled do nothing
                });
            };


            this.cartCheckout = undefined;
            this.paymentCardToUse = undefined;
            this.lastOrderConfirmation = undefined;
            this.errorArray = undefined;
            this.shippingMethodRefreshNeeded = false;
            this.paymentDetailRefreshNeeded = false;
            this.paymentMethodApproverGroups = undefined;
            this.customerPaymentMethods = [];

            this.getCheckoutCart = function (cb, errCb) {
                var self = this;

                self.cartCheckout = undefined;
                self.lastOrderConfirmation = undefined;
                return CartService.getCart()
                    .then(function (response) {
                        if (response.cart) {
                            self.getShopCartCheckout(response)
                                .then(function (response) {
                                    if (response.data.ValidationErrors && response.data.ValidationErrors.length > 0) {
                                        //self.showValidationErrorModal(response.data.ValidationErrors);
                                        self.errorArray = response.data.ValidationErrors;
                                        $rootScope.$broadcast('onRefreshCart');
                                        if (errCb) {
                                            errCb();
                                        }
                                    }

                                    if (response.data && response.data.PaymentMethod && response.data.PaymentMethod.ApprovalTypeId == 149) {
                                        return ShoppingCarts.getApproverGroups(response.data.PaymentMethod.PaymentMethodCode).then(function (response2) {
                                            self.cartCheckout = response.data;
                                            self.paymentMethodApproverGroups = response2.data;
                                            Common.setCartInitialized();
                                            if (cb) {
                                                cb();
                                            }
                                        });
                                    }
                                    else {
                                        self.cartCheckout = response.data;
                                        self.paymentMethodApproverGroups = undefined;
                                        Common.setCartInitialized();
                                        if (cb) {
                                            cb();
                                        }
                                    }
                                    
                                }, function (response) {
                                    //redirect to cart if cart value exceeds purchase balance (418)
                                    if (response.data && response.data.errorCode === '418') {
                                        Common.linkTo('cart');
                                    }
                                    if (errCb) {
                                        errCb();
                                    }
                                })
                        } else {
                            Common.goHome();
                        }

                    });

            };

            this.clearCheckoutCart = function () {
                this.cartCheckout = undefined;
            };

            this.updateCheckoutCart = function (paymentDetailCaptured) {
                var self = this;

                this.cartCheckout.PaymentDetailsCaptured = false;
                if (!!paymentDetailCaptured)
                    this.cartCheckout.PaymentDetailsCaptured = true;

                return ShoppingCarts.updateCheckout(this.cartCheckout)
                    
                    .then(function (response) {
                        if (response.data.PaymentMethod.ApprovalTypeId == 149) {
                            return ShoppingCarts.getApproverGroups(self.cartCheckout.PaymentMethod.PaymentMethodCode).then(function (response2) {
                                self.cartCheckout = response.data;
                                self.paymentMethodApproverGroups = response2.data;
                            })
                        }
                        else {
                            self.cartCheckout = response.data;
                            self.paymentMethodApproverGroups = undefined;
                        }
                    });

            };

            this.getCopyrightLevyFeeByCart = function () {
                var self = this;

                return ShoppingCarts.getCopyrightLevyFeeByCart(this.cartCheckout.CartId)
                    .then(function (response) {
                        self.cartCheckout.CopyrightLevy = response.data;
                    });
            };


            this.updatePaymentMethod = function (method) {
                var self = this;

                this.cartCheckout.PaymentDetailsCaptured = false;
                this.cartCheckout.PaymentMethod = method;
                this.cartCheckout.ChosenApproverGroupId = undefined;
                return ShoppingCarts.updateCheckout(this.cartCheckout)
                    .then(function (response) {
                       if (self.cartCheckout.PaymentMethod.ApprovalTypeId == 149) {
                            return ShoppingCarts.getApproverGroups(self.cartCheckout.PaymentMethod.PaymentMethodCode).then(function (response2) {
                                self.paymentMethodApproverGroups = response2.data;
                                self.cartCheckout = response.data;
                                self.paymentDetailRefreshNeeded = true;
                            });
                        }
                        else {
                            self.paymentMethodApproverGroups = undefined;
                            self.cartCheckout = response.data;
                            self.paymentDetailRefreshNeeded = true;
                        }
                    });

            };

            this.applyPromoCodeOnCheckout = function (code) {

                var self = this,
                    data = {
                        Code: code
                    };

                return ShoppingCarts.applyPromoCodeOnCheckout(self.cartCheckout.CartId, data)
                    .then(function (response) {
                        if (response.data) {
                            self.cartCheckout = response.data;
                        }
                        Common.showMessage('success', '666'); //successPromo,
                        $rootScope.$broadcast('onCartChangeCheckout');
                        CartService.loadCart(true);

                        //There is the potential that this could change the avalable shipping methods, so lets set that.
                        self.shippingMethodRefreshNeeded = true;

                    });

            };

            this.removePromoCodeOnCheckout = function (code) {

                var self = this;

                return ShoppingCarts.removePromoCodeOnCheckout(self.cartCheckout.CartId, code)
                    .then(function (response) {
                        if (response.data) {
                            self.cartCheckout = response.data;
                        }
                        Common.showMessage('success', '668'); //successPromo,
                        $rootScope.$broadcast('onCartChangeCheckout');
                        CartService.loadCart(true);
                    });

            };


            this.getShopCartCheckout = function (res) {
                if (res.cart) {
                    return res.cart.CartGuid ?
                        ShoppingCarts.getCheckoutByGuid(res.cart.CartGuid) :
                        ShoppingCarts.getCheckout(res.cart.CartId);
                } else {
                    //the cart in the response is undefined (or null) just return it back
                    res.cart;
                }
            };

            this.placeOrder = function (message) {
                var self = this;

                //Make sure when placing the order we put in our Payment Card to Use
                self.cartCheckout.PaymentCard = self.paymentCardToUse;
                self.shippingMethodRefreshNeeded = true;

                return Customers.createOrder(self.cartCheckout, message);

            };

            this.requestCartApproval = function (message) {
                var self = this;

                return Customers.requestCartApproval(self.cartCheckout, message);

            };

            this.updateCartBillingAddress = function () {
                return ShoppingCarts.updateCartBillingAddress(this.cartCheckout.CartGuid, this.cartCheckout.BillingAddress);
            };

            this.updateCartShippingAddress = function () {
                return ShoppingCarts.updateCartShippingAddress(this.cartCheckout.CartGuid, this.cartCheckout.ShippingAddress);
            };

            this.getApproverGroups = function (paymentMethodCode) {
                return ShoppingCarts.getApproverGroups(paymentMethodCode);
            };

            //There might be a better way of exposing CartService fee helpers but this seems like the least impactful
            this.ItemsContainFee = function (FeeTypeId, items) {
                return CartService.ItemsContainFee(FeeTypeId, items);
            };

            this.VisibleFeeTotal = function (FeeTypeId, items) {
                return CartService.VisibleFeeTotal(FeeTypeId, items);
            };

            this.VisibleFeeTotalForItem = function (FeeTypeId, item) {
                return CartService.VisibleFeeTotalForItem(FeeTypeId, item);
            };
        }]);
;'use strict';

angular
	.module('ecs.service.campaignwizard', [])
	.service('CampaignWizard', [
		'$log',
        '$location',
        '$routeParams',
        '$q',
        '$rootScope',
        'Campaigns',
        'Objects',
        'Common',
		function ($log, $location, $routeParams, $q, $rootScope, Campaigns, Objects, Common) {
		    this.selectedTrophyPack = null;
		    this.availableTrophies = null;

		    this.currentCampaign = null;
		    this.currentCampaignStatus = {
		        stepsComplete: {},
		        recipientCounts: { total: 0, ready: 0, notReady: 0 },
		        ownersCount: 0,
		        readyForLaunch: false,
		    };

		    this.recipientNavigationFilter = '';
		    this.currentCampaignOwners = null;
		    this.currentCampaignPacks = { AwardPack: null, SWAGPack: null };
            this.currentCampaignStatus.stepsComplete['General'] = { status: false, loading: true };
            this.currentCampaignStatus.stepsComplete['Owners'] = { status: false, loading: true };
            this.currentCampaignStatus.stepsComplete['Components'] = { status: false, loading: true };
            //For recipients, we want to track if we updated, removed, or deleted any recipients so that we can refresh the status as we navigate to a different tab
            this.currentCampaignStatus.stepsComplete['Recipients'] = { status: false, loading: true, dirty: false };
            this.currentCampaignStatus.stepsComplete['Communication'] = { status: false, loading: true, dirty: false };

            this.resetCampaign = function () {
                var self = this;
                self.currentCampaign = null;
                self.currentCampaignStatus = {
                    stepsComplete: {},
                    recipientCounts: { total: 0, ready: 0, notReady: 0 },
                    ownersCount: 0,
                    readyForLaunch: false,
                };
                self.currentCampaignOwners = null;
                self.currentCampaignPacks = { AwardPack: null, SWAGPack: null };
                self.currentCampaignStatus.stepsComplete['General'] = { status: false, loading: true };
                self.currentCampaignStatus.stepsComplete['Communication'] = { status: false, loading: true };
                self.currentCampaignStatus.stepsComplete['Owners'] = { status: false, loading: true };
                self.currentCampaignStatus.stepsComplete['Components'] = { status: false, loading: true };
                //For recipients, we want to track if we updated, removed, or deleted any recipients so that we can refresh the status as we navigate to a different tab
                self.currentCampaignStatus.stepsComplete['Recipients'] = { status: false, loading: true, dirty: false };
            };

		    this.loadCampaignStatus = function (loadChildren) {
		        var self = this;

		        if (!!self.currentCampaign) {
		            if (loadChildren) {
		                self.getRecipientCurrentStatus();

		                Campaigns.getCampaignOwners(self.currentCampaign.CampaignId)
                            .then(function (response) {
                                self.onCampaignOwnersLoaded(response.data);
                            });

		                Campaigns.getCampaignPacks(self.currentCampaign.CampaignId)
                            .then(function (response) {
                                self.onCampaignPacksLoaded(response.data);
                            });
		            }

		            self.currentCampaignStatus.stepsComplete['General'].loading = false;
		            self.currentCampaignStatus.stepsComplete['Communication'].loading = false;

		            if (self.currentCampaign.RedeemptionType === 1) {
		                self.currentCampaignStatus.stepsComplete['General'].status = (!!self.currentCampaign.Name
                                                                        && !!self.currentCampaign.LaunchDate
                                                                        && !!self.currentCampaign.RedeemptionType
                                                                        && self.currentCampaign.DaysToRedeem > 0);
		            }
		            else {
		                self.currentCampaignStatus.stepsComplete['General'].status = (!!self.currentCampaign.Name
                                                                        && !!self.currentCampaign.LaunchDate
                                                                        && !!self.currentCampaign.RedeemptionType);
		            }

		            if (self.currentCampaign.SendLaunchEmail || self.currentCampaign.RedeemptionType === 1)
		            {
		                self.currentCampaignStatus.stepsComplete['Communication'].status = (!!self.currentCampaign.RewardName
                                                                    && !!self.currentCampaign.Description
                                                                    && (!!self.currentCampaign.PurposeType || self.currentCampaign.PurposeType == 0)
                                                                    && !!self.currentCampaign.PurposeTypeAction
                                                                    && !!self.currentCampaign.EmailFromName
                                                                    && !!self.currentCampaign.EmailFromAddress
                                                                    && !!self.currentCampaign.EmailReplyToAddress);
		            }
		            else if (!self.currentCampaign.SendLaunchEmail || self.currentCampaign.RedeemptionType !== 1) {
		                self.currentCampaignStatus.stepsComplete['Communication'].status = true;
		            }


		            

		            self.currentCampaignStatus.readyForLaunch = ((self.currentCampaign.Status == 1 || self.currentCampaign.Status == 2) && !!self.currentCampaign.PONumber && self.currentCampaign.PONumber !== '');

		            $rootScope.$broadcast('onCampaignWizardLoadStatus');
		        }

		    };

		    this.onCampaignOwnersLoaded = function (owners) {
		        var self = this;

		        self.currentCampaignStatus.stepsComplete['Owners'].loading = false;
		        self.currentCampaignStatus.stepsComplete['Owners'].status = (!!owners && owners.length > 0);
		        self.currentCampaignStatus.ownersCount = owners.length;
		        self.currentCampaignOwners = owners;

		    };

		    this.onRecipientTotalsLoaded = function (recipientSearchResults) {
		        var self = this;

		        self.currentCampaignStatus.stepsComplete['Recipients'].loading = false;
		        self.currentCampaignStatus.stepsComplete['Recipients'].dirty = false;
		        self.currentCampaignStatus.stepsComplete['Recipients'].status = (recipientSearchResults.Total > 0 && recipientSearchResults.DataMissing <= 0);
		        self.currentCampaignStatus.recipientCounts.total = recipientSearchResults.Total;
		        self.currentCampaignStatus.recipientCounts.notReady = recipientSearchResults.DataMissing;
		        self.currentCampaignStatus.recipientCounts.ready = recipientSearchResults.DataComplete;
		    };

		    this.onCampaignPacksLoaded = function (campaignPacks) {
		        var self = this;

		        //If we have the campaign packs array, parse through and load them to our currentCampaignPacks object
		        if (campaignPacks) {
		            //Reset the packs
		            self.currentCampaignPacks.AwardPack = null;
		            self.currentCampaignPacks.SWAGPack = null;
		            for (var i = 0; i < campaignPacks.length; i++) {
                        //This will create the currentCampaignPacks.AwardPack && SWAGPack if we have them
		                self.setCampaignPackInCurrentPacks(campaignPacks[i]);
		            }
		        }

		        //Create an array of SWAGProducts, we'll loop through all the packs/groups and collect all the SWAG
		        self.currentCampaignPacks.SWAGProducts = new Array();                

		        //loop through the award pack to get the Trophy config and any products that may be on a SWAG group under the award pack
		        if (!!self.currentCampaignPacks.AwardPack && self.currentCampaignPacks.AwardPack.Groups.length > 0) {
		            for (var i = 0; i < self.currentCampaignPacks.AwardPack.Groups.length; i++) {
		                if (self.currentCampaignPacks.AwardPack.Groups[i].Type === 1 && self.currentCampaignPacks.AwardPack.Groups[i].Products.length > 0) {
		                    self.currentCampaignPacks.AwardPack.objConfigJSON = {};
		                    if (!!self.currentCampaignPacks.AwardPack.Groups[i].Products[0].ConfigJson) {
		                        self.currentCampaignPacks.AwardPack.objConfigJSON = JSON.parse(self.currentCampaignPacks.AwardPack.Groups[i].Products[0].ConfigJson);
		                    }
		                    self.currentCampaignPacks.AwardPack.IsPersonalized = self.currentCampaignPacks.AwardPack.Groups[i].Products[0].IsPersonalized;
                        }
		                if (self.currentCampaignPacks.AwardPack.Groups[i].Type === 2 && self.currentCampaignPacks.AwardPack.Groups[i].Products.length > 0) {
		                    self.currentCampaignPacks.SWAGProducts = self.currentCampaignPacks.SWAGProducts.concat(self.currentCampaignPacks.AwardPack.Groups[i].Products);
		                }
		            }
		        }
		        //loop through swag pack to get any products from it's groups
		        if (!!self.currentCampaignPacks.SWAGPack && self.currentCampaignPacks.SWAGPack.Groups.length > 0) {
		            for (var i = 0; i < self.currentCampaignPacks.SWAGPack.Groups.length; i++) {
		                if (self.currentCampaignPacks.SWAGPack.Groups[i].Type === 2 && self.currentCampaignPacks.SWAGPack.Groups[i].Products.length > 0) {
		                    self.currentCampaignPacks.SWAGProducts = self.currentCampaignPacks.SWAGProducts.concat(self.currentCampaignPacks.SWAGPack.Groups[i].Products);
		                }
		            }
		        }

		        var hasComponents = false;
		        if (self.currentCampaign.ComponentType === 1) {
		            //Just Award. Make sure Award pack with 1 group and 1 product exists
		            hasComponents = (!!self.currentCampaignPacks.AwardPack
                                        && !!self.currentCampaignPacks.AwardPack.Groups[0]
                                        && !!self.currentCampaignPacks.AwardPack.Groups[0].Products.length > 0);
		        } else if (self.currentCampaign.ComponentType === 2) {
		            //Just SWAG
		            hasComponents = (!!self.currentCampaignPacks.SWAGPack
                                        && !!self.currentCampaignPacks.SWAGPack.Groups[0]
                                        && !!self.currentCampaignPacks.SWAGPack.Groups[0].Products.length > 0);
		        } else if (self.currentCampaign.ComponentType === 3) {
                    //Award Or SWAG
		            hasComponents = ((!!self.currentCampaignPacks.SWAGPack
                                            && !!self.currentCampaignPacks.SWAGPack.Groups[0]
                                            && !!self.currentCampaignPacks.SWAGPack.Groups[0].Products.length > 0)
                                    &&
                                        (!!self.currentCampaignPacks.AwardPack
                                            && !!self.currentCampaignPacks.AwardPack.Groups[0]
                                            && !!self.currentCampaignPacks.AwardPack.Groups[0].Products.length > 0));
		        } else {
                    //Award AND Swag, just has the Award Pack, but with two groups
		            hasComponents = (!!self.currentCampaignPacks.AwardPack
                                        && !!self.currentCampaignPacks.AwardPack.Groups[0]
                                        && !!self.currentCampaignPacks.AwardPack.Groups[0].Products.length > 0
                                        && !!self.currentCampaignPacks.AwardPack.Groups[1]
                                        && !!self.currentCampaignPacks.AwardPack.Groups[1].Products.length > 0);
		        }

                //Assume this is true, and we'll update it if we actually have a trophy
		        var validTrophy = true;
		        if (hasComponents && !!self.currentCampaignPacks.AwardPack) {
		            if (self.currentCampaignPacks.AwardPack.TrophyType !== 3 && !self.currentCampaignPacks.AwardPack.BaseOnly) {//Not custom trophy And NOT Base Only
		                validTrophy = false;
		                if (!!self.currentCampaignPacks.AwardPack.objConfigJSON) {
		                    if (self.currentCampaignPacks.AwardPack.TrophyType === 2) {
		                        //Ship it, validate we have the Product
		                        validTrophy = (!!self.currentCampaignPacks.AwardPack.objConfigJSON.Product
                                                    && self.currentCampaignPacks.AwardPack.objConfigJSON.Product !== '');
		                    }
		                    else if (self.currentCampaignPacks.AwardPack.TrophyType === 1) {
		                        //Award with lines, check we have the required lines
		                        if (!!self.currentCampaignPacks.AwardPack.objConfigJSON.Lines) {
		                            validTrophy = true; //Assume it's good, but loop through until we find a missing required line
		                            for (var i = 0; i < self.currentCampaignPacks.AwardPack.objConfigJSON.Lines.length; i++) {
		                                if (self.currentCampaignPacks.AwardPack.objConfigJSON.Lines[i].Required === 'True'
                                                && (!self.currentCampaignPacks.AwardPack.objConfigJSON.Lines[i].Value || self.currentCampaignPacks.AwardPack.objConfigJSON.Lines[i].Value === '')
                                            ) {

		                                    validTrophy = false;
		                                    break;
		                                }
		                            }
		                        }
		                    }
		                }
		            }
		        }
                //staus is complete if we have the required components and, if there is a trophy, the trophy config is valid
		        self.currentCampaignStatus.stepsComplete['Components'].status = (hasComponents && validTrophy);
		        self.currentCampaignStatus.stepsComplete['Components'].loading = false;
		    };

		    this.getCampaignWizardStep = function () {
		        if ($routeParams.step)
		            return $routeParams.step;
		        else
		            return "";
		    };

            this.setCurrentCampaignById = function (campaignid) {
                var self = this;

                self.resetCampaign();
                return Campaigns.getCampaign(campaignid)
                        .then(function (response) {
                            self.setCurrentCampaign(response.data, true);
                            return;
                        });

            };

            this.setCurrentCampainLogoUrlIfNull = function (campaignid) {
                var self = this;
                return Campaigns.getCampaign(campaignid)
                        .then(function (response) {
                            self.currentCampaign.LogoUrl = response.data.LogoUrl;
                            return;
                        });
            };

            this.setCurrentCampaignByIdFromLocation = function () {
                var self = this;

                if ($routeParams.id) {

                    self.resetCampaign();
                    return Campaigns.getCampaign($routeParams.id)
                            .then(function (response) {
                                self.setCurrentCampaign(response.data, true);
                                return true;
                            }, function(response) {
                                return false; //Couldn't load it
                            });
                }
                else {
                    //Don't have an ID
                    var deferred = $q.defer();
                    deferred.resolve(false);
                    return deferred.promise;
                }

            };



            this.setCurrentCampaign = function (campaign, loadChildren) {
                var self = this;

                self.currentCampaign = campaign;
                self.setCampaignDateFields();
                self.loadCampaignStatus(loadChildren);

            };

            this.setCampaignDateFields = function () {
                this.currentCampaign.dtLaunchDate = Common.convertJsonDateString(this.currentCampaign.LaunchDate);
                this.currentCampaign.dtExpirationDate = Common.convertJsonDateString(this.currentCampaign.ExpirationDate);
                this.currentCampaign.dtReminderDate = Common.convertJsonDateString(this.currentCampaign.ReminderDate);
                this.currentCampaign.dtReminder2Date = Common.convertJsonDateString(this.currentCampaign.Reminder2Date);

                this.currentCampaign.strLaunchDate = Common.convertJsonDateString(this.currentCampaign.LaunchDate);
                this.currentCampaign.strExpirationDate = Common.convertJsonDateString(this.currentCampaign.ExpirationDate);
                this.currentCampaign.strReminderDate = Common.convertJsonDateString(this.currentCampaign.ReminderDate);
                this.currentCampaign.strReminder2Date = Common.convertJsonDateString(this.currentCampaign.Reminder2Date);
            }

            this.setCampaignPackInCurrentPacks = function (pack) {
                var self = this;
                if (pack.Type === 1) {
                    self.currentCampaignPacks.AwardPack = pack;
                } else {
                    self.currentCampaignPacks.SWAGPack = pack;
                }
            };

            this.getRecipientCurrentStatus = function () {
                var self = this;
                self.currentCampaignStatus.stepsComplete['Recipients'].loading = true;
                Campaigns.searchCampaignRecipients(self.currentCampaign.CampaignId, 0, 0, '')
                        .then(function (response) {
                            self.onRecipientTotalsLoaded(response.data);
                        });
            };

            this.refreshDirtyStatuses = function() {
                var self = this;
                if (!!self.currentCampaign) {
                    //If the recipients data is dirty (and we are currently loading it), refresh the recipient totals
                    if (self.currentCampaignStatus.stepsComplete['Recipients'].dirty && !self.currentCampaignStatus.stepsComplete['Recipients'].loading) {
                        self.getRecipientCurrentStatus();
                    }
                }
            };

            this.getCampaignTemplateCategories = function () {
                try {
                    return Objects.getCampaignTemplateCategories()
                        .then(function (response) {
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('getCampaignTemplateCategories() :: Error ', e);
                }
            };

            this.getCountries = function (type) {

                return Objects.getCountries({ type: type })
                    .then(function (response) {
                        return response;
                    });

            };

            this.getStateOrRegions = function (country) {

                return Objects.getStateOrRegions({ country: country })
                    .then(function (response) {
                        return response;
                    });


            };

            this.goToCampaignList = function () {
                this.resetCampaign();
                this.scrollToTop();
                $location.path('/rewardcampaigns/');
            };


            this.goToGeneral = function () {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/general/'+this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/general');
            };

            this.goToCommunication = function () {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/Communication/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/Communication');
            };

            this.goToGeneralWithPartialCampaign = function () {
                this.refreshDirtyStatuses();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/general/' + this.currentCampaign.CampaignId);
            };

            this.goToOwners = function () {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/owners/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/owners');
            };

            this.goToComponents = function () {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/components/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/components');
            };

            this.goToSWAGSearch = function () {
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/swagsearch/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/swagsearch');
            };

            this.goToRecipients = function (filter) {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                this.recipientNavigationFilter = filter;
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/recipients/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/recipients');
            };

            this.getRecipientNavigationFilter = function () {
                var filter = this.recipientNavigationFilter;
                this.recipientNavigationFilter = '';
                return filter;
            };

            this.goToSummary = function () {
                this.refreshDirtyStatuses();
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/summary/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/summary');
            };

            this.goToCreateCampaign = function () {
                this.scrollToTop();
                this.resetCampaign();
                $location.path('/rewardcampaigns/create/templates');
            };

            this.goToComponentAwards = function () {
                this.scrollToTop();
                if (this.currentCampaign)
                    $location.path('/rewardcampaigns/create/componentawards/' + this.currentCampaign.CampaignId);
                else
                    $location.path('/rewardcampaigns/create/componentawards/');
            };

            this.scrollToTop = function () {
                $rootScope.$broadcast('scrollTop');
            }

            this.searchCampaigns = function (skip, top, query) {
                try {
                    return Campaigns.searchCampaigns(skip, top, query)
                        .then(function (response) {
                            return response;
                        });
                } catch (e) {
                    $log.warn('searchCampaigns () :: Error ', e);
                }
            };

            this.cloneCampaign = function (params, clone) {
                try {
                    Common.showLoader('113');
                    return Campaigns.cloneCampaign(params, clone)
                        .then(function (response) {
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('cloneCampaign() :: Error ', e);
                }
            };

            this.extendCampaign = function (campaignId, extension) {
                try {
                    Common.showLoader('114');
                    return Campaigns.extendCampaign(campaignId, extension)
                        .then(function (response) {
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('extendCampaign() :: Error ', e);
                }
            };

            this.createCampaign = function (campaign) {
                var self = this;
                try {
                    Common.showLoader('113');
                    return Campaigns.createCampaign(campaign)
                        .then(function (response) {
                            self.setCurrentCampaign(response.data, true);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('createCampaign() :: Error ', e);
                }
            };

            this.updateCampaign = function (campaignId, campaign) {
                var self = this;
                try {
                    Common.showLoader('131');
                    return Campaigns.updateCampaign(campaignId, campaign)
                        .then(function (response) {
                            self.setCurrentCampaign(response.data, false);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('updateCampaign() :: Error ', e);
                }
            };

            this.addRecipient = function (campaignId, recipient) {
                var self = this;
                try {
                    return Campaigns.addCampaignRecipient(campaignId, recipient)
                        .then(function (response) {
                            self.currentCampaignStatus.stepsComplete['Recipients'].dirty = true;
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('addRecipient() :: Error ', e);
                }
            };

            this.updateRecipient = function (campaignId, recipientId, recipient) {
                var self = this;
                try {
                    return Campaigns.updateCampaignRecipient(campaignId, recipientId, recipient)
                        .then(function (response) {
                            self.currentCampaignStatus.stepsComplete['Recipients'].dirty = true;
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('updateRecipient() :: Error ', e);
                }
            };

            this.removeRecipient = function (campaignId, recipientId) {
                var self = this;
                try {
                    return Campaigns.deleteCampaignRecipient(campaignId, recipientId)
                        .then(function (response) {
                            self.currentCampaignStatus.stepsComplete['Recipients'].dirty = true;
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('removeRecipient() :: Error ', e);
                }
            };
            this.getPacks = function (campaignId) {
                var self = this;
                try {
                    return Campaigns.getCampaignPacks(campaignId)
                        .then(function (response) {
                            self.onCampaignPacksLoaded(response.data);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('getPacks() :: Error ', e);
                }
            };

             this.getCampaignPack = function (campaignId) {
		        try {
		            return Campaigns.getCampaignPacks(campaignId)
                        .then(function (response) {
                            return response;
                        });
		        }
		        catch (e) {
		            $log.warn('getCampaignPack() :: Error ', e);
		        }
		    };

             this.getCampaignTrophies = function () {
                 try {
                     return Objects.getCampaignTrophies()
                         .then(function (response) {
                             return response;
                         });
                 }
                 catch (e) {
                     $log.warn('getCampaignTrophies() :: Error ', e);
                 }
             };

             this.updatePack = function (campaignId, packId, pack) {
                 var self = this;
                 try {
                     Common.showLoader('114');
                     return Campaigns.updateCampaignPack(campaignId, packId, pack)
                         .then(function (response) {
                             if (!!response.data) {
                                 //Got the pack back from API, update it in the current packs
                                 self.setCampaignPackInCurrentPacks(response.data);
                             } else {
                                 //did API return NULL for updated pack, if so the pack has been deleted due to all products remove
                                 //check the pack passed in to update to see if it was Award or SWAG and update the pack in currentCampaignPack
                                 if (pack.Type === 1)
                                     self.currentCampaignPacks.AwardPack = null;
                                 else
                                     self.currentCampaignPacks.SWAGPack = null;
                             }
                             self.onCampaignPacksLoaded();
                             return response;
                         });
                 }
                 catch (e) {
                     $log.warn('updatePack() :: Error ', e);
                 }
             };

             this.addPack = function (campaignId, pack) {
                var self = this;
                 try {
                     Common.showLoader('114');
                    return Campaigns.addCampaignPack(campaignId, pack)
                        .then(function (response) {
                            self.setCampaignPackInCurrentPacks(response.data);
                            self.onCampaignPacksLoaded();
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('addPack() :: Error ', e);
                }
            };

            this.getCampaignOwners = function (campaignId) {
                try {
                    var self = this;

                    return Campaigns.getCampaignOwners(campaignId)
                        .then(function (response) {
                            self.onCampaignOwnersLoaded(response.data);
                            return; //don't return the response. Any sort of failure processing will take place in the wizard
                        });
                } catch (e) {
                    $log.warn('getCampaignOwners () :: Error ', e);
                }
            };

            this.addCampaignOwner = function(campaignId, owner) {
                try {
                    var self = this;
                    return Campaigns.addCampaignOwner(campaignId, owner)
                        .then(function (response) {
                            self.onCampaignOwnersLoaded(response.data);
                            return; //don't return the response. Any sort of failure processing will take place in the wizard
                        });
                } catch (e) {
                    $log.warn('addCampaignOwner () :: Error ', e);
                }
            };

            this.removeCampaignOwner = function(campaignid, ownerid) {
                try {
                    return Campaigns.removeCampaignOwner(campaignid, ownerid)
                        .then(function (response) {
                            return; //don't return the response. Any sort of failure processing will take place in the wizard
                        });
                } catch (e) {
                    $log.warn('removeCampaignOwner () :: Error ', e);
                }
            };

            this.sendCampaignReminder = function (campaignid, campaignReminder) {
                try {
                    Common.showLoader('110'); //Processing...
                    return Campaigns.addCampaignAction(campaignid, campaignReminder)
                        .then(function (response) {
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('sendCampaignReminder() :: Error ', e);
                }
            };

            this.submitForReview = function (campaignid) {
                var self = this;
                try {
                    Common.showLoader('115'); //Submitting...
                    return Campaigns.addCampaignAction(campaignid, { Action: 'SendForReview' })
                        .then(function (response) {
                            self.currentCampaign.Status = 1;
                            self.loadCampaignStatus(false);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('submitForReview() :: Error ', e);
                }
            };

            this.submitReviewComplete = function (campaignid) {
                var self = this;
                try {
                    Common.showLoader('116'); //Approving...
                    return Campaigns.addCampaignAction(campaignid, { Action: 'ReviewComplete' })
                        .then(function (response) {
                            //TODO: In the future we'd look at the response to determine if we need a PO or if it has already been approved
                            self.currentCampaign.Status = 2;
                            self.loadCampaignStatus(false);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('submitForReview() :: Error ', e);
                }
            };

            this.launchCampaign = function (campaignid) {
                var self = this;
                try {
                    Common.showLoader('116'); //Launching...
                    return Campaigns.addCampaignAction(campaignid, { Action: 'LaunchCampaign' })
                        .then(function (response) {
                            self.currentCampaign.Status = 4;
                            self.loadCampaignStatus(false);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('updateCampaignReviewComplete() :: Error ', e);
                }
            };

            this.cancelCampaign = function (campaignid) {
                var self = this;
                try {
                    Common.showLoader('114'); //Updating...
                    return Campaigns.addCampaignAction(campaignid, { Action: 'CancelCampaign' })
                        .then(function (response) {
                            self.currentCampaign.Status = 6;
                            self.loadCampaignStatus(false);
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('cancelCampaign() :: Error ', e);
                }
            };

            this.submitForPOApproval = function (campaignid) {
                var self = this;
                try {
                    Common.showLoader('115'); //Submitting...
                    return Campaigns.addCampaignAction(campaignid, { Action: 'SendForPOApproval' })
                        .then(function (response) {
                            self.currentCampaign.Status = 3;
                            self.loadCampaignStatus(false);

                            return response;
                        });
                }
                catch (e) {
                    $log.warn('submitForPOApproval() :: Error ', e);
                }
            };

            this.getFees = function (campaignId) {
                try {
                    return Campaigns.getCampaignFees(campaignId)
                        .then(function (response) {
                            return response;
                        });
                }
                catch (e) {
                    $log.warn('getFees() :: Error ', e);
                }
            };

            this.canEditCampaign = function () {
                try {
                    if(this.currentCampaign) {
                        return (((this.currentCampaign.Status == 0) || this.currentCampaign.Status == 1) && (this.currentCampaign.AccessLevel == 4))
                               || (this.currentCampaign.Status == 0 && this.currentCampaign.AccessLevel == 2);
                    }
                        
                    return false;
                }
                catch (e) {
                    $log.warn('canEditCampaign() :: Error ', e);
                }
            }

            this.canEditRecipients = function () {
                try {
                    if (this.currentCampaign) {
                        if (this.canEditCampaign()) {
                            return true;
                        }
                        else {
                        return (this.currentCampaign.Status == 0) && (this.currentCampaign.AccessLevel == 3);
                    }
                    }

                    return false;
                }
                catch (e) {
                    $log.warn('canEditRecipients() :: Error ', e);
                }
            }

            this.canAddExceptions = function () {
                try {
                     if (this.currentCampaign) {
                         return (
                                 (this.currentCampaign.Status == 4 || this.currentCampaign.Status == 5) &&
                                 (!!this.currentCampaign.ExceptionRecipientBuffer && this.currentCampaign.ExceptionRecipientBuffer > 0) &&
                                 (this.currentCampaign.NumberOfExceptions < Math.round(this.currentCampaign.ExceptionRecipientBuffer / 100 * this.currentCampaign.NumberOfRecipients))
                             );
                    }

                    return false;
                }
                catch (e) {
                    $log.warn('canAddExceptions() :: Error ', e);
                }
            }
		}]);
;'use strict';

angular
	.module('ecs.service.storePassesStateManager', [])
	.service('StorePassesStateManager', [
		'$log',
		function ($log) {
		    this.customerFAFPasses = null;
		    this.currentTab = null;
		    this.vipTabSearchOptions = null;
		    
		    this.saveState = function (tab, searchOptions) {
		        this.currentTab = tab;
                if (tab === 'VIP')
                    this.vipTabSearchOptions = searchOptions;

		    }

		}]);
;angular
    .module('ecs.service.ecsResource.utils', [])
	.factory('ResourceUtils', ['$http', '$log', '$injector', function ($http, $log, $injector) {

	    return {

	        convertParamsToObj: function (query) {

	            var match,
                    pl = /\+/g,  // Regex for replacing addition symbol with a space
                    search = /([^&=]+)=?([^&]*)/g,
                    decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); };

	                urlParams = {};
	                while (match = search.exec(query))
	                    urlParams[decode(match[1])] = decode(match[2]);

	                return urlParams;

	        },

	        parseUri: function (uri) {

	            var uriObj = { path: '', params: '' },
                    path = uri.substr(0, uri.indexOf('?')),
                    params = uri.substr(uri.indexOf('?') + 1, uri.length);

	            uriObj.path = path;
	            uriObj.params = this.convertParamsToObj(params);

	            return uriObj;

	        },

	        makeUri: function (path, params) {
	            var uri = [];

	            uri.push(path);
	            uri.push('?');
	            uri.push(decodeURIComponent($.param(params)));

	            return uri.join('');

	        },

	        getApiData: function (api_data) {

	            var serviceImpl = $injector.get(api_data.impl);

	            try {

	                var apiObj = serviceImpl[api_data.name];

	                if (apiObj) {
	                    return apiObj;
	                }

	            } catch (err) {

	                $log('Error: Api object not found, ', err, serviceImpl);

	            }

	        },




	        // This function changes the params object structure found in the impl structres
	        // from param.blah.value to param.value so that it can be parsed into querystring
	        // parameters.

	        flattenParams: function (params) {
	            var flatParams = {};

	            for (key in params) {
	                if (key.indexOf(':') === -1) {
	                    flatParams[key] = params[key].value;
	                }
	            }

	            return flatParams;
	        },


	        stripTemplateParams: function (params) {
	            var flatParams = {};

	            for (key in params) {
	                if (key.indexOf(':') === -1) {
	                    flatParams[key] = params[key];
	                }
	            }

	            return flatParams;
	        },

	        // This function updates the templates found in urls, ie. :customerId,
	        // with parameter value, if found.  if parameter value is not found the 
	        // template is removed from the url. 

            /*
	        resolveTemplates: function (url, params) {

	            var resourceArr = this.getUrlTemplates(url);

	            for (var i = 0, len = resourceArr.length; i < len; i += 1) {

	                var wildcard = resourceArr[i],
                        resource = params[wildcard];

	                if (resource !== undefined) {
	                    url = url.replace(wildcard, resource);
	                    if (url.slice(-1) === '/') {
	                        url = url.slice(0,-1);
	                    }

	                } else {
	                    url = this.removeParam(url, wildcard);
	                    $log.warn('EcsResource:: function resolveTemplates() :: resource param not found in params, removing from url.');

	                }
	            }

	            return url;

	        },
            */

	        
            resolveTemplates: function (url, params) {

	            var resourceArr = this.getUrlTemplates(url),
	                needTrailingSlash = url.slice(-1) === '/',
	                newUrlHasTrailingSlash = false;


	            for (var i = 0, len = resourceArr.length; i < len; i += 1) {

	                var wildcard = resourceArr[i],
                        resource = params[wildcard];

	                if (resource !== undefined) {
	                    url = url.replace(wildcard, resource);
	                    newUrlHasTrailingSlash = url.slice(-1) === '/';

	                    if (needTrailingSlash && !newUrlHasTrailingSlash) {
	                        url += '/';

	                    } else if ((!needTrailingSlash && newUrlHasTrailingSlash)) {
	                        url = url.slice(0,-1);
	                    }

	                } else {
	                    url = this.removeParam(url, wildcard);
	                    $log.warn('EcsResource:: function resolveTemplates() :: resource param not found in params, removing from url.');

	                }
	            }

	            return url;

	        },
            

	        //This function removes a paramter from a url. See above

	        removeParam: function (url, param) {

	            var pattern = new RegExp('\/' + param); //+ '+([/]?)');

	            return url.replace(pattern, '');

	        },

	        // This function returns a list of all the templates within a given url 
	        getUrlTemplates: function (url) {
	            var templates = [],
                    pattern = /^:/;

	            angular.forEach(url.split(/\//), function (str) {
	                if (str.match(pattern)) {
	                    templates.push(str);
	                }
	            });

	            return templates;

	        }



	    };



	}]);;angular
    .module('ecs.service.ecsResource', [])
	.factory('EcsResource', ['$http', 'Config', 'ResourceUtils', '$log', function ($http, Config, ResourceUtils, $log) {

	    return function (collectionName) {
	        /**
			*	Generic api resource to be instantiated for each collection.

			**/

	        var collectionUrl = Config.API.host + Config.API.path + collectionName,

			    Resource = function (data) {
			        angular.extend(this, data);
			    };

	        Resource.configAPI = Config.API;

	        Resource.query = function (params, options) {

	            var qs = decodeURIComponent($.param(ResourceUtils.stripTemplateParams(params))),
	                url = ResourceUtils.resolveTemplates(collectionUrl, params),
	                bei = options && options.bypassErrorInterceptor ? true : false,
	                bg = options && options.backgroundTask ? true : false,
	                opts = { bypassErrorsInterceptor: bei, backgroundTask: bg };

	            qs = (qs !== '' ? '?' + qs : '');

	            // if the call has parameters then the url must end with a fwd slash
	            // otherwise it must not.  The resolveTemplates method removes the trailing
	            // fwd slash when removing unused template params.  The below logic re-adds the trailing slash if there are 
	            // querystring params that are to be appended.

	            if (qs.length > 0 && url.slice(-1) !== '/') {
	                url += '/';
	            }

	            return $http({
	                method: 'GET',
	                url: url + qs,
	                options: opts


	            }).then(function (response) {

	                return response;
	            });

	        };

	        Resource.update = function (params, data, options) {

	            var bei = options && options.bypassErrorInterceptor ? true : false,
	                bg = options && options.backgroundTask ? true : false,
	                opts = { bypassErrorsInterceptor: bei, backgroundTask: bg };

	            if (!data)
	                data = ResourceUtils.stripTemplateParams(params);

	            return $http({
	                method: 'PUT',
	                url: ResourceUtils.resolveTemplates(collectionUrl, params),
	                data: data,
	                options: opts
	            })
                .then(function (response) {
                    return response;
                });
	            //return $http.put(ResourceUtils.resolveTemplates(collectionUrl, params), data)

	        };

	        Resource.save = function (params, data, opts) {

	            if (!data)
	                data = ResourceUtils.stripTemplateParams(params);

	            return $http({
	                method: 'POST',
	                url: ResourceUtils.resolveTemplates(collectionUrl, params),
	                data: data,
	                options: opts
	            })
				.then(function (response) {
					return response;
				});

	        };


	        Resource.remove = function (params, options) {
	            var bg = options && options.backgroundTask ? true : false;

                //http://tech.pro/tutorial/1238/angularjs-and-ie8-gotcha-http-delete
                return $http({ method: 'DELETE', url: ResourceUtils.resolveTemplates(collectionUrl, params) })
					.then(function (response) {
					    return response;
					});
	        };
            

	        Resource.removeWithData = function (params, data, options) {

	            var bei = options && options.bypassErrorInterceptor ? true : false,
	                bg = options && options.backgroundTask ? true : false,
	                opts = { bypassErrorsInterceptor: bei, backgroundTask: bg };

	            if (!data)
	                data = ResourceUtils.stripTemplateParams(params); 

	            //http://tech.pro/tutorial/1238/angularjs-and-ie8-gotcha-http-delete
	            return $http({
	                method: 'DELETE',
	                url: ResourceUtils.resolveTemplates(collectionUrl, params),
	                data: JSON.stringify(data),
	                headers: {
	                    "Content-Type": "application/json"
	                },
	                options: opts
	            })
				.then(function (response) {
				    return response;
				});

	        };
	        return Resource;
	    };
	}])
	.config(['$provide', '$httpProvider', function ($provide, $httpProvider) {

	    $httpProvider.defaults.useXDomain = true;

	    $provide.factory('ecsInterceptor', ['$q', 'Config', '$rootScope', 'Constants', 'Common', '$log', '$injector', '$location', function ($q, Config, $rootScope, Constants, Common, $log, $injector, $location) {
	        var itemsLoading = 0,
                genericErrorMessage = '200',

	            hideLoader = function () {

	                if ((itemsLoading -= 1) <= 0) {
	                    // Hide loader
	                    itemsLoading = 0;
	                    $rootScope.$broadcast("loader_hide");
	                    $rootScope.$broadcast("waiting_off");
	                }

	            };

	        return {

	            request: function (config) {

	                var showLoader = config.options && config.options.message ? config.options : undefined,
                        keywords = ['html', 'png', 'gif', 'jpg', 'home', 'js'],
	                    $http = $injector.get('$http'),
                        splitUrl = config.url.split(/[/\.\\]+/),

	                    isAssetRequest = splitUrl.length === 1 || $.inArray(splitUrl[splitUrl.length - 1].toLowerCase(), keywords),
	                    isApiCall = (App.Configuration.UseCORS === 'true') ? (splitUrl.length > 1 && splitUrl[1].indexOf('api') >= 0) : (splitUrl.length > 4 && splitUrl[4] === 'api'),

	                    deferred = $q.defer(),

	                    getQueryParam = function (name) {
	                    if (name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search))
	                        return decodeURIComponent(name[1]);
	                    };

	                

	                if (isAssetRequest === -1) {
	                    itemsLoading += 1;
	                    $rootScope.$broadcast("waiting_on");
	                }

	                if (showLoader) { 
	                    
	                    $rootScope.$broadcast('loader_show', showLoader.message);// Show loader
	                };


	                if (!isApiCall || isAssetRequest > -1) {
	                    return config || $q.when(config);
	                } else {

	                    var getService = function (config) {
	                        var servicePath = config.url.substr(config.url.indexOf(Config.API.path) + Config.API.path.length, config.url.length);
	                        return servicePath.substr(0, servicePath.indexOf("/"));
	                    },

                        url = App.Configuration.RootPath + ('Authentication/AuthorizationToken?apiUri=%URI%&apiServiceName=%SVC%').replace('%URI%', encodeURIComponent((config.url + (config.params ? decodeURIComponent($.param(config.params)) : '')).toLowerCase()));

	                    var requestedStoreCode = getQueryParam('storeCode');
	                    if (requestedStoreCode !== undefined)
	                        url += '&storeCode=' + requestedStoreCode;

	                    $http({
	                        method: 'GET',
	                        url: url.replace('%SVC%', getService(config)),
	                        headers: {
	                            "Referrer": $location.absUrl()
	                        }
	                    })
                            .then(function (response) {

                                var data = response.data,
                                    authorization = data.StoreCode + ' ' + data.PublicKey + ':' + data.Token;

                                config.headers['X-Date'] = data.Date;
                                config.headers['X-Authorization'] = authorization;
                                config.headers.Authorization = authorization;

                                if ($rootScope.user && $rootScope.user.ACT !== null & $rootScope.user.ACT !== '') {
                                    config.headers['X-AccessToken'] = $rootScope.user.ACT;
                                }

                                deferred.resolve(config);

                            }, function (rejection) {

                                Common.showMessage('danger', 'The call to acquire the token failed.');

                                deferred.reject(rejection);

                            });

	                    return deferred.promise;

	                }


	            },

	            // On request failure
	            requestError: function (rejection) {

	                Common.showMessage('danger', rejection.data.message || rejection.statusText || genericErrorMessage);

	                return $q.reject(rejection);
	            },

	            // On response success
	            response: function (response) {

	                hideLoader();
	                // Return the response or promise.
	                return response || $q.when(response);
	            },

	            // On response failture
	            responseError: function (rejection) {

	                try {
	                    var config = rejection.config,
	                    errCode = rejection.data ? rejection.data.errorCode : undefined,
						messageInData = rejection.data ? rejection.data.message : undefined,
						fieldName = rejection.data.additionalInfo ? rejection.data.additionalInfo : undefined,  
						message = errCode ? errCode : messageInData || (rejection.statusText || genericErrorMessage);

	                    if (config && config.options && config.options.bypassErrorsInterceptor) {
	                        hideLoader();
	                        return $q.reject(rejection);
	                    }
	                } catch (e) {
	                    $log.error('ecsResource.js > responseError = ', e)
	                }

					if (fieldName && errCode) {
						Common.showMessageNew('danger', 'None', errCode, { replace: '%additionalInfo%', value: [fieldName] })
					} else {
						Common.showMessage('danger', message, { errorCode: errCode });
					}
	               
	                hideLoader();

	                return $q.reject(rejection);
	            }
	        };
	    }]);

	    $httpProvider.interceptors.push('ecsInterceptor');

	}]);

;'use strict';

angular
    .module('ecs.service.security', [])
    .factory('AuthenticationStateCheck', ['$http', '$q', '$location', '$rootScope', function ($http, $q, $location, $rootScope) {
        var factory = {
            isAuthenticated: false,
            checkAuthenticationState: function () {
                var url = App.Configuration.RootPath + 'Authentication/IsAuthenticated';
                $http.get(url).then(function (response) {
                    factory.isAuthenticated = response.data.IsAuthenticated;

                    //validate that we have the information to compare to the response back from the server
                    if ($rootScope.user && $rootScope.user.IsAnonymous !== null) {
                        var shouldBeAnonymous = $rootScope.user.IsAnonymous;

                        if (!factory.isAuthenticated && !shouldBeAnonymous) {
                            //append in a querystring in case we want to message
                            if (location.href.indexOf('?') == -1) {
                                window.location.href += "?auth=anonymous";
                            }
                            else {
                                window.location.href += "&auth=anonymous";
                            }
                            
                            window.location.reload();
                        }
                    }
                });
            }
        };

        factory.checkAuthenticationState();

        return factory;
    }]);;'use strict';

angular
    .module('ecs.service.store', [])
    .factory('StoreCache', ['$cacheFactory', function ($cacheFactory) {
        return $cacheFactory('Store');
    }])
    .service('StoreService', [
        '$log',
        '$http',
        '$q',
        'StoreCache',
        function ($log, $http, $q, StoreCache) {
            var self = this;

            self.getStore = function () {
                var url = App.Configuration.RootPath + 'Store/Info';
                return $http.get(url, { cache: false });
            };
        }]);;'use strict';

angular
    .module('ecs.service.user', [])
    .service('UserService', [
        '$log',
        '$http',
        '$q',
        function ($log, $http, $q) {
            this.getUser = function () {
                var url = App.Configuration.RootPath + 'User/Info';

                return $http.get(url, { cache: false });
            };
        }]);;'use strict';

angular
    .module('ecs.service.importfileprogress', [])
    .factory('ImportFileProgress', ['$rootScope', function ( $rootScope) {
        return {
            onRowImport: function (fileid, progressCallback) {
                //Getting the connection object
                var connection = $.hubConnection(App.Configuration.RootPath + 'signalr', {useDefaultPath: false});
                connection.qs = { 'fileid': fileid };
                var proxy = connection.createHubProxy('importFileRowProgressHub');

                //Attaching a callback to handle acceptGreet client call
                proxy.on('importFileRowStatus', function (importRowProgressMessage) {
                    $rootScope.$apply(function () {
                        progressCallback(importRowProgressMessage);
                    });
                });

                //Starting connection
                connection.start();
            },
            
        }
    }]);;angular
    .module('ecs.service.ecs-locale', [])
    .factory('EcsLocale', ['Constants', '$sce', '$filter',
        function EcsLocale(Constants, $sce, $filter) {


            var getRateObject = function (baseCurrency, exchangeRates) {

                var hasExchangeRate = exchangeRates && exchangeRates.length > 0,

                    defaultBaseCurrency = baseCurrency || {
                        BundleTaxes: false,
                        CurrencyCode: "USD",
                        CurrencyName: "US Dollars",
                        Rate: 1,
                        TaxRate: 0,
                        ShowCode: false,
                        Points: false,
                    };

                return hasExchangeRate ? exchangeRates[0] : defaultBaseCurrency;
            },

                getPrice = function (input, rateObj, isBudget) {
                    let price = input * rateObj.Rate;

                    if (rateObj.Points) {
                        if (rateObj.PointsValue && !isBudget) {
                            price = Math.round(input);
                        }
                        else {
                            price = price < 1 ? Math.ceil(price) : Math.round(price);
                        }
                    }

                    return price;
                },

                getTotalPrice = function (cartItems, rateObj, isBudget) {
                    let totalAmount = 0;

                    if (rateObj.Points) {
                        cartItems.forEach(ci => {
                            let points = ci.Amount < 1 ? Math.ceil(ci.Amount) : Math.round(ci.Price * rateObj.Rate) * ci.Qty; 
                            totalAmount += points;
                        });
                    }

                    return totalAmount;
                },

                getSymbol = function (code) {
                    //add points
                    var codeArr = Constants.CURRENCY_SYMBOLS[code] || Constants.CURRENCY_SYMBOLS['USD'];

                    return codeArr.join('');
                },

                getExchangedValue = function (input, baseCurrency, exchangeRates) {

                    // Ensure that we are working with a number
                    if (isNaN(input)) {
                        return input;
                    } else {

                        var rateObj = getRateObject(baseCurrency, exchangeRates),
                            price = getPrice(input, rateObj);

                        return price;
                    }
                },

                convertDate = function (date) {

                    if (date && date.length < 10) {
                        return 'Invalid Date';
                    }

                    var newDate = new Date(Date.parse(date)),
                        localeDate = newDate.toLocaleString(),
                        noAt = localeDate.replace('at ', ''),
                        cleanedDate = new Date(localeDate);

                    return $filter('date')(newDate, 'MM/dd/yyyy');
                },

                formatCurrency = function (input, baseCurrency, exchangeRates) {

                    // Ensure that we are working with a number
                    if (isNaN(input)) {
                        return input;
                    } else {

                        var rateObj = getRateObject(baseCurrency, exchangeRates),
                            symbol = getSymbol(rateObj.CurrencyCode);

                        return $filter('currency')(input, symbol, 2) + (rateObj.ShowCode ? ' ' + rateObj.CurrencyCode : '');
                    }
                },

                getExchangedTotalWithSymbol = function (cartItems, baseCurrency, exchangeRates, isBudget) {
                        let localIsBudget = (isBudget !== null && isBudget) || false;

                        var rateObj = getRateObject(baseCurrency, exchangeRates),
                            symbol = getSymbol(rateObj.CurrencyCode),
                            price = getTotalPrice(cartItems, rateObj, localIsBudget);

                        if (rateObj.PointsValue && price < 0) {
                            return "";
                        }

                        return (rateObj.Points) ?
                            price + ' ' + rateObj.CurrencyCode :
                            $filter('currency')(price, symbol, 2) + (rateObj.ShowCode ? ' ' + rateObj.CurrencyCode : '');
                },

                getExchangedValueWithSymbol = function (input, baseCurrency, exchangeRates, isBudget) {

                    // Ensure that we are working with a number
                    if (isNaN(input)) {
                        return input;
                    } else {
                        let localIsBudget = (isBudget !== null && isBudget) || false;

                        var rateObj = getRateObject(baseCurrency, exchangeRates),
                            symbol = getSymbol(rateObj.CurrencyCode),
                            price = getPrice(input, rateObj, localIsBudget);

                        if (rateObj.PointsValue && price < 0) {
                            return "";
                        }

                        return (rateObj.Points) ?
                             price + ' ' + rateObj.CurrencyCode :
                            $filter('currency')(price, symbol, 2) + (rateObj.ShowCode ? ' ' + rateObj.CurrencyCode : '');
                    }
                };

            function bundledTaxes(baseCurrency, exchangeRates) {
                try {
                    return baseCurrency.BundleTaxes || (exchangeRates.length && exchangeRates[0].BundleTaxes);
                } catch (er) {
                    return false;
                }
            };

            function bundledTaxesFromCart(order) {
                try {
                    return order.BaseCurrency.BundleTaxes || (order.CurrencyExchangeRates.length && order.CurrencyExchangeRates[0].BundleTaxes);
                } catch (er) {
                    return false;
                }
            };

            function bundledTaxesFromOrder(cart) {
                try {
                    return cart.BaseCurrency.BundleTaxes || (cart.CurrencyExchangeRates.length && cart.CurrencyExchangeRates[0].BundleTaxes);
                } catch (er) {
                    return false;
                }
            };

            return {
                exchangeRateTotalSymb: getExchangedTotalWithSymbol,
                exchangeRateSymb: getExchangedValueWithSymbol,
                exchangeRate: getExchangedValue,
                convertDate: convertDate,
                formatCurrency: formatCurrency,
                bundledTaxes: bundledTaxes,
                bundledTaxesFromCart: bundledTaxesFromCart,
                bundledTaxesFromOrder: bundledTaxesFromOrder
            }

            /*
                             
            - BaseCurrency will be provided by the API. This will be the current amount in the DTO. Will be USD.
            
            Example:
            baseCurrency = 
            BundleTaxes: false
            CurrencyCode: "USD"
            CurrencyName: "US Dollars"
            Rate: 1
            TaxRate: 0
            ShowCode: false
            
            
            - CurrencyExchangeRates will be provided by the API. This will be an array that has zero or one entry. If zero items in the array, no need to convert the currency.
            
            Example: 
            
            BundleTaxes: true
            CurrencyCode: "EUR"
            CurrencyName: "EURO"
            Rate: 1.3073
            TaxRate: 0.24
            ShowCode: true
            
            - The Exchange Rate is based on the MS Subsidiary of the EPP Employee as specified in the MSEPP.epp.Customer table, CompanyCode column.
            -The CompanyCode is a LookUp to the MSEPP.epp.SubsidiaryExchRate table. This table provides use the CountryCode, the CurrencyCode, the ExchangeRate, 
            and hopefully the VAT tax rate. If the CompanyCode is set then we will provide the ExchangeRate info for that Subsidiary.
            - For the UI:
            - If there is no items in the ExchangeRate array in the DTO, format the currency in the BaseCurrency.
            - If there is at least 1 item in the array, use the first item to calculate and format the currency.
            - If BaseCurrency is NULL or Undefined, default to USD
            */

        }]);;'use strict';

angular
    .module('ecs.service.gcCheckout', [])
    .service('GCCheckoutService', [
        'Common',
        'Constants',
        '$rootScope',
        '$uibModal',
        '$log',
        '$q',
    function (Common, Constants, $rootScope, $uibModal, $log, $q) {

        this.gcCheckout = undefined;

        this.setGCCheckoutInfo = function (gc) {
            var self = this;

            self.gcCheckout = gc;
        };
    }]);
;'use strict';

angular
    .module('ecs.service.reward', [])
    .service('RewardService', [
        '$log',
        '$http',
        '$q',
        '$location',
        '$timeout',
        '$uibModal',
        '$sce',
        '$window',
        'Config',
        'Products',
        'Common',
        'Rewards',
        'ProductUrlService',
        'Campaign',
        function ($log, $http, $q, $location, $timeout, $uibModal, $sce, $window, appConfig, Products, Common, Rewards, ProductUrlService, Campaign) {

            var self = this;
            self.isGiftCodeValidated = false;
            self.redeemed = false;
            self.redeeming = false;
            self.readyToPlaceOrder = false;
            self.paymentRequired = false;
            self.reward = null;
            self.giftCodeReward;
            self.remainingRedemptions = null;
            self.selectedProducts = null;
            self.products = null;
            self.shipToAddress = null;
            self.storeCode = null;
            self.scope = null;
            self.loadingProduct = false;

            self.updateRemainingRedemptions = (product) => {
                if (!product.Quantity) product.Quantity = 1;
                const remainingQty = self.reward.NumberOfRemainingProductsToRedeem;
                const totalQty = self.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                if (totalQty <= remainingQty) {
                    self.remainingRedemptions = remainingQty - totalQty;
                } else {
                    const excessQty = totalQty - remainingQty;
                    product.Quantity = product.Quantity - excessQty;
                    self.remainingRedemptions = 0;
                    Common.showMessage('danger', 'The quantity you entered exceeded your total remaining redemptions, the quantity was set to your total remaining redemptions');
                }
                $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(self.remainingRedemptions));
                $window.sessionStorage.setItem("products", JSON.stringify(self.products));
            };

            self.removeSelectedProduct = (product) => {
                const idx = self.products.indexOf(product);
                self.products.splice(idx, 1);

                const remainingQty = self.reward.NumberOfRemainingProductsToRedeem;
                const totalQty = self.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                self.remainingRedemptions = remainingQty - totalQty;
                $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(self.remainingRedemptions));

                var productsWithVariations = self.products.filter(pr => !!pr.ChildProductOptions && pr.ChildProductOptions.length > 0);
                self.readyToPlaceOrder = productsWithVariations.every(pr => !!pr.selectedProductOption && !!pr.ChildProductOptions && pr.ChildProductOptions.length > 0);
                $window.sessionStorage.setItem("products", JSON.stringify(self.products));

                if (self.products.length == 0) {
                    $window.sessionStorage.clear();
                    self.linkTo('/select-catalog-award/' + self.reward.RewardId);
                }
            };

            self.setStoreCode = function (storeCode) {
                self.storeCode = storeCode;
            };

            self.setScope = function (scope) {
                self.scope = scope;
            };

            self.validateGiftCode = function (giftCode) {
                return Rewards.getGiftCodeReward(giftCode).then(function (response) {
                    self.isGiftCodeValidated = true;
                    self.giftCodeReward = response.data;
                });
            };

            self.addToSelectedProduct = function (selectedProducts) {
                self.selectedProducts = selectedProducts;
            };

            self.setSelectedProducts = function (remainingRedemptions, selectedProducts) {
                self.remainingRedemptions = remainingRedemptions;
                self.redeemed = false;

                //storing selectedProducts data in sessionStorage to persist when user reloads the page
                $window.sessionStorage.setItem("products", JSON.stringify(selectedProducts));
                $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(remainingRedemptions));
            };

            self.getProducts = function (productSlug) {
                self.loadingProduct = true;
                Common.showLoader('104');
                if (!!productSlug) {
                    Products.getProduct({ ':sku': productSlug })
                        .then(function (response) {
                            let products = [];
                            products.push(response.data);
                            self.initializeProducts(true, products, 0);
                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/awards/error/');
                            } else {
                                Common.showMessage('danger', 'Cannot load selected product, please refresh your browser and try again.');
                            }
                        });
                } else {
                    self.getSelectedProducts().then(() => {
                        self.initializeProducts(false);
                    }, function (err) {
                        console.log(err);
                        Common.showMessage('error', 'Error retrieving products');
                    });
                }
            };

            self.getSelectedProducts = function () {
                //this is to handle if user normal/hard reload the page
                if (!self.selectedProducts || !self.remainingRedemptions) {
                    self.selectedProducts = JSON.parse($window.sessionStorage.getItem("products"));
                    self.remainingRedemptions = JSON.parse($window.sessionStorage.getItem("remainingRedemptions"));
                }
                var productSlugs = self.selectedProducts.map(sp => sp.ProductSlug);
                return Products.getSelectedProducts(productSlugs)
                    .then(function (response) {
                        self.products = response.data;
                    });

            };

            self.getCampaignTypeText = function (campaignTypeId) {
                switch (campaignTypeId) {
                    case 158:
                        return 'Email';
                        break;
                    case 159:
                        return 'Gift Code';
                        break;
                }
            };

            self.initializeProducts = function (isCustomRewards, products, remainingRedemptions) {
                if (isCustomRewards) {
                    self.remainingRedemptions = remainingRedemptions;
                    self.products = products;
                }
                //setup other properties needed on product
                angular.forEach(self.products, function (product) {
                    if (product.Images.length > 0) {
                        product.Image = product.Images[0];
                        product.Image.urls = {};
                        product.Image.urls.lg = self.getProductImage(product, 'l');
                        product.Image.urls.md = self.getProductImage(product, '');

                        self.renderZoomableMultiImage(product);
                    }

                    if (product.ChildProductOptions && product.ChildProductOptions.length > 0) {
                        product.selectedProductOption = null; //this is used for selecting a variation that will change the ProductNumber of the product
                        self.readyToPlaceOrder = !!product.selectedProductOption && !!product.ChildProductOptions && product.ChildProductOptions.length > 0;
                        angular.forEach(product.ChildProductOptions, function (productOption, i) {

                            //Set the default selected option for top-level products options (i.e. if color & size option, we won't select the size for you) 
                            if (productOption.Order < product.ChildProductOptions.length) {
                                //check if this is the current product we are viewing.
                                angular.forEach(productOption.Values, function (option, i) {
                                    if (option.IsThisProduct) {
                                        productOption.selectedOption = option;
                                    }
                                });
                            }
                        });
                    }

                    //Check for additional info attributes
                    if (product.Attributes && product.Attributes.length > 0) {
                        angular.forEach(product.Attributes, function (productAttribute, i) {
                            if (!!productAttribute.Type && productAttribute.Type.toLowerCase() === "rewardadditionalinfo") {
                                productAttribute.objJsonConfig = JSON.parse(productAttribute.Value);

                            }
                        });
                    }

                });

                self.readyToPlaceOrder = self.products.every(p => !p.ChildProductOptions);

                if (!isCustomRewards) {
                    let copyProducts = Common.deepCopy(self.products);
                    //apply Quantity in self.products
                    angular.forEach(self.products, function (product, productIdx) {
                        if (!product.hasOwnProperty('Quantity')) {
                            product.Quantity = self.selectedProducts[productIdx].Quantity;
                        }
                    });
                    var productsWithVariation = self.products.filter(dp => !!dp.ChildProductOptions && !!dp.ChildProductOptions.length > 0); //with product options
                    var productsWithoutVariation = self.products.filter(dp => !dp.ChildProductOptions || dp.ChildProductOptions == null);
                    var copyProductsWithoutVariation = copyProducts.filter(dp => !dp.ChildProductOptions || dp.ChildProductOptions == null);

                    copyProductsWithoutVariation = copyProductsWithoutVariation.filter((value, index, self) =>
                        index === self.findIndex((t) => (
                            t.ProductNumber === value.ProductNumber
                        ))
                    ); // remove duplicates

                    var productNumbersWithoutVariation = productsWithoutVariation.map(pwv => pwv.ProductNumber);
                    productNumbersWithoutVariation = productNumbersWithoutVariation.filter((value, index, self) =>
                        index === self.findIndex((t) => (
                            t === value
                        ))
                    );; // remove duplicates

                    angular.forEach(productNumbersWithoutVariation, function (pwv) {
                        var sumQuantity = productsWithoutVariation.filter(p => pwv == p.ProductNumber).map(q => q.Quantity).reduce((prev, next) => prev + next);
                        copyProductsWithoutVariation.find(sp => {
                            if (sp.ProductNumber == pwv) {
                                sp.Quantity = sumQuantity;
                            }
                        });
                    });

                    self.products = Common.deepCopy(productsWithVariation);

                    angular.forEach(copyProductsWithoutVariation, function (x) {
                        self.products = [].concat(self.products, x);
                    });
                }

                // timeout hack to deal with this issue: https://github.com/angular/angular.js/issues/16586
                $timeout(function () {
                    self.loadingProduct = false;
                }, 500);
            };

            self.renderZoomableMultiImage = function (product) {
                var imageZoomOptions = {
                    zoomEnable: product.SupportZoom,
                    defaultIndex: 0,
                    style: "box",
                    boxPos: "right-top",
                    boxW: 400,
                    boxH: 400,
                    method: "lens",
                    cursor: "zoom-in",
                    lens: true,
                    zoomLevel: 3,
                    immersiveMode: "769",
                    immersiveModeOptions: {},
                    immersiveModeMessage: 'Tap to Zoom', // Immersive mode message
                    prevThumbButton: "&#9665;",
                    nextThumbButton: "&#9655;",
                    thumbsPos: "bottom",
                    thumbCol: 10,
                    thumbColPadding: 4,
                    images: []
                }

                if (!product.Images) {
                    product.selectedImageModel = {}
                } else {
                    for (var i = 0; i < product.Images.length; i++) {
                        var img = product.Images[i];
                        var basepath = appConfig.ProductImageBaseURL;

                        imageZoomOptions.images[imageZoomOptions.images.length] = {
                            thumb: basepath + img.FileName + '-TT' + img.Extension,
                            medium: basepath + img.FileName + '-l' + img.Extension,
                            large: product.SupportZoom ?
                                basepath + img.FileName + '-xl' + img.Extension :
                                basepath + img.FileName + '-l' + img.Extension
                        };
                    }

                    product.selectedImageIndex = 0;
                    product.selectedImageModel = imageZoomOptions.images[0]
                    product.zoomoptions = imageZoomOptions;
                }
            };

            self.updateToSelectedProduct = function (productOption, product) {
                let supportMultiImage = false;
                if (self.loadingProduct)
                    return;

                if (!product.selectedProductOption || product.selectedProductOption.ProductSlug !== productOption.selectedOption.ProductSlug) {
                    //Make sure we've consider multiple levels, if it's the last level, which is the actual product, then update the selected option)
                    Common.showLoader('104');
                    if (product.ChildProductOptions && product.ChildProductOptions.length == productOption.selectedOption.Level) {
                        product.selectedProductOption = productOption.selectedOption;
                        self.getSelectedChildProduct(productOption.selectedOption, product, supportMultiImage);
                    }
                    else {
                        //If it's not the last level, it's a parent product. We need to get the product info so we can load the different options and image
                        //Only do this if we are changing
                        supportMultiImage = true;
                        self.getSelectedChildProduct(productOption.selectedOption, product, supportMultiImage);
                    }
                }
            };

            self.getSelectedChildProduct = function (selectedOption, product, supportMultiImage) {
                product.selectedProductOption = selectedOption; //this is used to check if the user still haven't selected any product options/variations
                Products.getProduct({ ':sku': selectedOption.ProductSlug })
                    .then(function (response) {
                        product.ProductNumber = response.data.ProductNumber;
                        product.PurchaseProductNumber = response.data.PurchaseProductNumber;
                        product.ProductSlug = response.data.ProductSlug;
                        product.selectedProductOption.productNumber = response.data.ProductNumber;
                        product.selectedProductOption.purchaseProductNumber = response.data.PurchaseProductNumber;
                        angular.forEach(response.data.ChildProductOptions, function (option, i) {
                            option.selectedOption = option.Values.filter(v => v.IsThisProduct)[0];
                        });
                        product.ChildProductOptions = response.data.ChildProductOptions;
                        //If it's a different color, change the image
                        if (selectedOption.Option.toUpperCase() === 'COLOR' && response.data.Images.length > 0) {
                            product.Images = response.data.Images;
                            product.Image = response.data.Images[0];
                            product.Image.urls = {};
                            product.Image.urls.lg = self.getProductImage(product, 'l');
                            product.Image.urls.md = self.getProductImage(product, '');

                            if (supportMultiImage) {
                                self.renderZoomableMultiImage(product);

                                // timeout hack to deal with this issue: https://github.com/angular/angular.js/issues/16586
                                $timeout(function () {
                                    self.loadingProduct = false;
                                }, 500);
                            }
                        }

                        //check if all product variations or options have been selected
                        var productsWithVariations = self.products.filter(pr => !!pr.ChildProductOptions && pr.ChildProductOptions.length > 0);
                        self.readyToPlaceOrder = productsWithVariations.every(pr => !!pr.selectedProductOption && !!pr.ChildProductOptions && pr.ChildProductOptions.length > 0);

                    },
                        function (reason) {
                            Common.showMessage('danger', 'Cannot load selected product, please refresh your browser and try again.');
                        });
            };

            self.getNoImageurl = function (size) {
                return ProductUrlService.getNoImageUrl(size);
            };

            self.getProductImage = function (product, size) {
                if (!product)
                    return;

                return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
            };

            self.getReward = function (rewardid) {
                Rewards.getReward(rewardid).
                    then(function (reward) {

                        if (reward.data.Status != 1) {
                            Common.goHome();
                            return;
                        }

                        self.reward = reward.data;
                        self.shipToAddress = self.reward.DefaultShippingAddress;
                        self.reward.termsConfigObj = JSON.parse(reward.data.TermsJson);
                        if (!!self.reward.termsConfigObj) {
                            self.reward.termsConfigObj.Message = $sce.trustAsHtml(self.reward.termsConfigObj.Message);
                        }

                        self.paymentRequired = self.reward.PaymentRequired;

                    }, function (reason) {
                        if (reason.status == '400' || reason.status == '401') {
                            $location.path('/awards/error/');
                        } else {
                            var errCode = reason.data ? reason.data.errorCode : undefined;
                            var messageInData = reason.data ? reason.data.message : undefined
                            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                            Common.showMessage('danger', message, { errorCode: errCode });
                        }
                    });
            };

            self.linkAttributeFilter = function (attribute) {

                if (attribute.Type && attribute.Type.toLowerCase() === 'pdppopuplink') {
                    return true;
                } else {
                    return false;
                }
            };

            self.additionalInfoAttributeFilter = function (attribute) {

                if (attribute.Type && attribute.Type.toLowerCase() === 'rewardadditionalinfo') {
                    return true;
                } else {
                    return false;
                }
            };

            self.openRetirementDatePicker = function ($event, attributeConfigObj) {
                $event.preventDefault();
                $event.stopPropagation();
                attributeConfigObj.retirementDatePickerOpened = true;
            };

            self.isRedeemed = function () {
                // There is no OrderNumber created for trophies yet, so we need to also track via
                // the redeemed variable.
                return !!self.reward && (!!self.reward.OrderNumber || self.reward.Status != 1 || self.redeemed);
            };

            self.shippingChecks = function () {
                if (!self.shipToAddress.Address1) {
                    Common.showMessage('error', 'Please be sure to provide your shipping address before redeeming your reward.');
                    return false;
                }

                const poboxRegEx = /p[o|\s|.]+(?:box)/i;
                var poboxInAddress = poboxRegEx.test(self.shipToAddress.Address1);
                if (poboxInAddress) {
                    Common.showMessage('error', 'We cannot ship to PO boxes, please update your address.');
                    return false;
                }

                if (self.reward.TermsRequired && self.reward.termsConfigObj.RequireSignature && (!self.reward.termsAgreement || !self.reward.termsAgreement === "")) {
                    Common.showMessage('error', 'Please be provide your ' + self.reward.termsConfigObj.SignatureLabel + ' to redeem your reward.');
                    return false;
                }

                if (self.shipToAddress.Country !== 'US' && (!self.reward.ContactPhone || self.reward.ContactPhone === "")) {
                    Common.showMessage('error', 'Please be provide a valid contact phone number for your order.');
                    return false;
                }
                return true;
            }

            self.redeemReward = function () {
                if (!self.shippingChecks()) {
                    return;
                }

                var additionalInfoList = [];
                angular.forEach(self.products, function (product) {
                    if (product.ChildProductOptions && product.ChildProductOptions.length > 0 && (!product.selectedProductOption || !product.selectedProductOption.productNumber)) {
                        Common.showMessage('error', 'Please select your desired product option before redeeming your reward.');
                        return;
                    }
                    if (product.Attributes && product.Attributes.length > 0) {
                        for (var i = 0; i < product.Attributes.length; i++) {
                            var productAttribute = product.Attributes[i];
                            if (!!productAttribute.objJsonConfig) {

                                if (productAttribute.objJsonConfig.ViewTemplate.toLowerCase() === 'instructions') {
                                    if (!productAttribute.objJsonConfig.instructionsValue || productAttribute.objJsonConfig.instructionsValue === '') {
                                        Common.showMessage('error', productAttribute.objJsonConfig.Caption);
                                        return;
                                    }
                                    else {
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Instructions', Value: productAttribute.objJsonConfig.instructionsValue });
                                    }
                                }
                                else if (productAttribute.objJsonConfig.ViewTemplate.toLowerCase() === 'retirementmembership') {
                                    if (!productAttribute.objJsonConfig.rewardRetirementMembershipName || productAttribute.objJsonConfig.rewardRetirementMembershipName === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipAddress || productAttribute.objJsonConfig.rewardRetirementMembershipAddress === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipCity || productAttribute.objJsonConfig.rewardRetirementMembershipCity === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipState || productAttribute.objJsonConfig.rewardRetirementMembershipState === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipZip || productAttribute.objJsonConfig.rewardRetirementMembershipZip === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipPhone || productAttribute.objJsonConfig.rewardRetirementMembershipPhone === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipEmail || productAttribute.objJsonConfig.rewardRetirementMembershipEmail === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipRetirementDate || productAttribute.objJsonConfig.rewardRetirementMembershipRetirementDate === ''
                                        || !productAttribute.objJsonConfig.rewardRetirementMembershipRetirementOption || productAttribute.objJsonConfig.rewardRetirementMembershipRetirementOption === ''
                                    ) {
                                        Common.showMessage('error', productAttribute.objJsonConfig.Caption);
                                        return;
                                    }
                                    else {
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Name', Value: productAttribute.objJsonConfig.rewardRetirementMembershipName });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Current Address', Value: productAttribute.objJsonConfig.rewardRetirementMembershipAddress });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'City', Value: productAttribute.objJsonConfig.rewardRetirementMembershipCity });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'State', Value: productAttribute.objJsonConfig.rewardRetirementMembershipState });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'ZIP', Value: productAttribute.objJsonConfig.rewardRetirementMembershipZip });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Phone', Value: productAttribute.objJsonConfig.rewardRetirementMembershipPhone });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Email', Value: productAttribute.objJsonConfig.rewardRetirementMembershipEmail });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Retirement Date', Value: productAttribute.objJsonConfig.rewardRetirementMembershipRetirementDate });
                                        additionalInfoList.push({ Type: productAttribute.Attribute, Name: 'Member Type', Value: productAttribute.objJsonConfig.rewardRetirementMembershipRetirementOption });
                                    }
                                }

                            }
                        }
                    }
                });


                //// Check if gift code is still valid.
                //// This is needed in case the user redeemed the code in another instance of a browser.
                //// https://cic.my.workfront.com/task/view?ID=61ae36d2000f7666968c51a2072d77cc
                Common.showLoader('119');

                var selectedProducts = [];

                //redemption/redeemed products
                selectedProducts = self.products.map(p => {
                    let redeemedAs = p.Name;
                    if (p.ChildProductOptions && p.ChildProductOptions.length > 0 && p.selectedProductOption) {
                        angular.forEach(p.ChildProductOptions, function (o) {
                            if (o.Option == "Color") {
                                redeemedAs = redeemedAs + " " + o.selectedOption.Value;
                            }
                            if (o.Option == "Size") {
                                redeemedAs = redeemedAs + " " + o.selectedOption.Value;
                            }
                            if (o.Option != "Color" && o.Option != "Size") {
                                redeemedAs = redeemedAs + " " + o.selectedOption.Value;
                            }
                        });
                    }
                    return {
                        ProductName: p.Name,
                        ProductGroup: p.MaterialGroup,
                        ProductNumber: p.ProductNumber,
                        RedeemedAs: redeemedAs,
                        Quantity: p.Quantity,
                    }
                });

                // Note: Not needed here. Shipping address is assigned via API 
                //var shippingAddress = {
                //    Name : self.shipToAddress.Name,
                //    Email : self.shipToAddress.Email,
                //    Phone : self.shipToAddress.Phone,
                //    Extension : self.shipToAddress.Extension,
                //    CompanyName : self.shipToAddress.CompanyName,
                //    Address1 : self.shipToAddress.Address1,
                //    Address2 : self.shipToAddress.Address2,
                //    //Address3 : null,
                //    City : self.shipToAddress.City,
                //    State : self.shipToAddress.State,
                //    PostalCode : self.shipToAddress.PostalCode,
                //    Country : self.shipToAddress.Country
                //};


                var rewardRedemptionDTO = {
                    'RewardId': self.reward.RewardId,
                    'Type': 4, //Catalog Item
                    'RedeemedProducts': selectedProducts, //RedeemedAs to be included inside of RedeemedProducts
                    'AdditionalInfo': additionalInfoList,
                    // 'ShippingAddress': shippingAddress,
                    'IsExpired': false
                };

                if (self.reward.TermsRequired && self.reward.termsConfigObj.RequireSignature) {
                    rewardRedemptionDTO.TermsSignature = self.reward.termsAgreement;
                }

                if (self.shipToAddress.Country !== 'US') {
                    rewardRedemptionDTO.ContactPhone = self.reward.ContactPhone;
                    rewardRedemptionDTO.ContactPhoneExtension = self.reward.ContactPhoneExtension;
                }

                self.redeeming = true;

                Rewards.redeemRewards(self.reward.RewardId, rewardRedemptionDTO, '100')
                    .then(function (response) {
                        $log.log(response);
                        self.reward.OrderNumber = !!response.data.RedeemedProducts && response.data.RedeemedProducts.length > 0 ? response.data.RedeemedProducts[0].OrderNumber : null; //since all of the selected products will be placed together in a single OrderNumber, I think it is safe to just get the first index of the OrderNumber
                        self.redeemed = true;
                        self.redeeming = false;
                        self.isGiftCodeValidated = false;
                        $window.sessionStorage.clear();
                        self.scope.$scrollTop(0);
                    },
                        function (message) {
                            self.redeeming = false;
                            Common.showMessage('error', 'Error redeeming the reward.');
                            $log.log('Error redeeming product', message);
                        });
            };

            self.linkTo = function (path) {
                return Common.linkTo(path);
            };

            self.convertDate = function (date) {
                return Common.convertJsonDateString(date);
            };

            //required for displaying shipping address in 2 columns
            self.segmentize = function (data, columns) {
                var newData = [];

                for (var i = 0; i < data.length; i = i + columns) {
                    newData.push(data.slice(i, i + columns));
                }

                return newData;
            };



            self.showAddressForm = function (isShowAdditionalShipToAddressFields) {

                var reward = self.reward,
                    modalInstance = $uibModal.open({
                        templateUrl: 'AddEditRewardShippingAddress.html',
                        controller: 'rewardShippingAddressCatalogCtrl as ctrl',
                        size: 'lg',
                        resolve: {
                            campaign: function () {
                                return Campaign;
                            },
                            storeCode: function () {
                                return self.storeCode;
                            },
                            reward: function () {
                                return {
                                    OverrideAddress: reward.OverrideAddress,
                                    EmailReplyToAddress: reward.EmailReplyToAddress,
                                    Name: reward.Name,
                                    ShipToAddress: self.shipToAddress,
                                    CustomerId: reward.CustomerId,
                                    RewardId: reward.RewardId
                                };
                            },
                            scope: function () {
                                return self.scope;
                            },
                            showAdditionalShipToAddressFields: function () {
                                return isShowAdditionalShipToAddressFields;
                            }
                        }

                    }).result.then(function (shipToAddress) {
                        Common.showMessage('success', 'Address has been updated.');
                        self.shipToAddress = shipToAddress;
                    });
            };
        }
    ])

    .controller('rewardShippingAddressCatalogCtrl', [
        'Rewards',
        'Common',
        'Stores',
        'Objects',
        '$uibModalInstance',
        '$scope',
        'campaign',
        'storeCode',
        'reward',
        'scope',
        'showAdditionalShipToAddressFields',
        function (Rewards, Common, Stores, Objects, $uibModalInstance, $scope, campaign, storeCode, reward, scope, showAdditionalShipToAddressFields) {

            var ctrl = this,

                init = function () {

                    //Do we actually have an address (just look at Address 1 to determine that)
                    if (!!reward.ShipToAddress && !!reward.ShipToAddress.Address1)
                        newAddress = angular.copy(reward.ShipToAddress);

                    exposeSelf();

                },

                newAddress = {
                    Name: '',
                    FirstName: '',
                    LastName: '',
                    Address1: '',
                    Address2: '',
                    City: '',
                    State: '',
                    PostalCode: '',
                    County: '',
                    Country: 'US',
                    Email: '',
                    Phone: '',
                    Extension: ''
                },

                apiStoreCode = storeCode,

                exposeSelf = function () {

                    ctrl.showAdditionalShipToAddressFields = showAdditionalShipToAddressFields;
                    ctrl.newAddress = newAddress;
                    ctrl.reward = reward || {};
                    ctrl.saveAndUseAddress = saveAndUseAddress;
                    ctrl.cancelChanges = closeModal;
                    ctrl.countries = [];
                    ctrl.countriesLoading = true;
                    Objects.getCountries({ type: 'Shipping' })
                        .then(function (response) {
                            ctrl.countriesLoading = false;
                            ctrl.countries = !!$scope.store.StoreCode && Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                        });

                    ctrl.states = [];
                    ctrl.originalCountry = ctrl.newAddress.Country;
                    Objects.getStateOrRegions({ country: ctrl.originalCountry })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    ctrl.onCountryChanged = onCountryChanged;
                    ctrl.selectOffice = selectOffice;
                    ctrl.close = closeModal;
                    ctrl.scope = scope;
                    ctrl.updateInProgress = false; //I'm doing this because $waiting isn't the best solution for this form.

                    //AR - Leaving in case we ever need to support the address lookup again.
                    ctrl.offices = [];
                    ctrl.officesLoading = false;
                    ctrl.officesPageNum = 1;
                    ctrl.officesTotalNum = 0;
                    ctrl.officesItemsPerPage = 6;
                },

                hideForm = function () {
                    closeModal();
                    ctrl.newAddress = newAddress;
                },

                onCountryChanged = function () {

                    //AR - 78050: All user to enter any address, not just US. I will leave this original code here in case this is something we need to add back in.
                    ctrl.newAddress.State = '';
                    Objects.getStateOrRegions({ country: ctrl.newAddress.Country })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    //AR - Leaving code that toggles between Address Entery form and Address Lookup. In case we ever need to support this again.
                    //if (ctrl.newAddress.Country != 'US') {
                    //    ctrl.officesLoading = true;
                    //    ctrl.officesPageNum = 1;
                    //    ctrl.officesTotalNum = 0;
                    //    Stores.searchAddresses(apiStoreCode, 'Office', "Country=" + ctrl.newAddress.Country)
                    //    .then(function (response) {
                    //        ctrl.officesLoading = false;
                    //        ctrl.officesTotalNum = response.data.length;
                    //        ctrl.offices = segmentize(response.data, ctrl.officesItemsPerPage);
                    //    });
                    //}
                    //else {
                    //    if (ctrl.originalCountry !== 'US')
                    //    {
                    //        //If the original address that we loaded was not US, then clear out the address fields
                    //        ctrl.newAddress = {
                    //            Address1: '',
                    //            Address2: '',
                    //            City: '',
                    //            State: '',
                    //            PostalCode: '',
                    //            County: '',
                    //            CompanyName: '',
                    //            Country: 'US',
                    //            Email: '',
                    //            Phone: '',
                    //            Extension: ''
                    //        }

                    //    }
                    //}

                },

                //AR - Leaving in case we ever need to support the address lookup again.
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },

                closeModal = function () {
                    $uibModalInstance.dismiss('cancel');
                },

                //AR - Leaving in case we ever need to support the address lookup again.
                selectOffice = function (selectedAddress) {

                    ctrl.updateInProgress = true;
                    var model = angular.copy(selectedAddress);
                    //Specify that it is a shipping address and use the existing ShipToName 
                    model.AddressType = 'Shipping';
                    model.CompanyName = model.Name;
                    model.Name = reward.ShipToAddress.Name;
                    updateRewardAddress(reward, model);

                },

                saveAndUseAddress = function (form, newAddress) {
                    ctrl.updateInProgress = true;
                    campaign.getTaxJurisdiction(newAddress, form)
                        .then(function () {
                            if (form.$valid) {

                                var model = {
                                    'AddressType': 'Shipping',
                                    'Name': newAddress.FirstName + ' ' + newAddress.LastName, //newAddress.Name,
                                    'FirstName': newAddress.FirstName,
                                    'LastName': newAddress.LastName,
                                    'Address1': newAddress.Address1,
                                    'Address2': newAddress.Address2,
                                    'Country': newAddress.Country,
                                    'City': newAddress.City,
                                    'State': newAddress.State,
                                    'PostalCode': newAddress.PostalCode,
                                    'Email': newAddress.Email,
                                    'Phone': newAddress.Phone
                                    //'Extension': newAddress.Extension
                                };

                                updateRewardAddress(reward, model);

                            } else {
                                Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                                ctrl.updateInProgress = false;
                                //Common.hideLoader();
                            }
                        }, function () {
                            Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                            ctrl.updateInProgress = false;
                            //Common.hideLoader();
                        });
                },

                updateRewardAddress = function (reward, address) {
                    Rewards.updateRewardShippingAddress(reward.RewardId, address)
                        .then(function (response) {
                            $uibModalInstance.close(address);
                        },
                            function (message) {
                                ctrl.updateInProgress = false;
                                Common.showMessage('error', 'Error saving address.');
                            });

                };



            init();
        }
    ]);
    ;'use strict';

angular
    .module('ecs.service.chili', [])
    .service('ChiliService', [
        '$http',
        'Common',
        '$log',
        '$window',
        function ($http, Common, $log, $window) {

            this.getRenderPDF = function (guid, stayInTab, callback) {
                Common.showLoader('110');

                var url = App.Configuration.RootPath + 'Personalization/RenderFromDocument';
                var params = JSON.stringify({
                    documentId: guid
                });

                let xhr = new XMLHttpRequest();
                xhr.open('POST', url, true);

                xhr.setRequestHeader("Content-type", "application/json; charset=utf-8");

                xhr.responseType = 'arraybuffer';
                xhr.onload = function (e) {
                    if (this.status == 200) {
                        let blob = new Blob([this.response], { type: "application/pdf" });
                        const blobURL = window.URL.createObjectURL(blob);
                        Common.hideLoader();

                        if (stayInTab) {
                            window.location.href = blobURL;
                        }
                        else {
                            var tabOpen = window.open("about:blank", 'newtab');
                            tabOpen.location.href = blobURL;
                        }
                    }
                    else {
                        Common.hideLoader();
                        $log.log('There was a problem loading PDF data.');
                        Common.showMessage('danger');
                        if (callback != null) {
                            callback(this.status);
                        }
                    }
                };
                xhr.send(params);
            };
        }]);

;angular
    .module('ecs.service.impl.objects', [])
    .constant('ObjectsCallData', {

        taxJurisdictions: 'objects/taxjurisdictions/',
        countries: 'objects/countries/',
        stateOrRegions: 'objects/regions/',
        campaigntemplatecategories: 'objects/campaigntemplatecategories/',
        campaigntrophies: 'objects/campaigntrophies/',
        creditCardTokenizeIFrameURL: 'objects/CCTokenizeIFrameURL/'
    })
    .factory('Objects', ['ObjectsCallData', 'EcsResource', '$log', function (ObjectsCallData, EcsResource, $log) {

        return {

            getTaxJurisdictions: function (params) {
                try {

                    return new EcsResource(ObjectsCallData.taxJurisdictions)
                                .query(params, {bypassErrorInterceptor: true});


                } catch (e) {

                    $log.warn('taxJurisdictions () :: Error ', e);

                }

            },

            getCountries: function (params) {
                try {

                    return new EcsResource(ObjectsCallData.countries)
                                .query(params);

                } catch (e) {

                    $log.warn('getCountries () :: Error ', e);

                }

            },

            getStateOrRegions: function (params) {
                try {

                    return new EcsResource(ObjectsCallData.stateOrRegions)
                                .query(params);


                } catch (e) {

                    $log.warn('getStateOrRegions () :: Error ', e);

                }

            },

            getCampaignTemplateCategories: function () {
                try {

                    return new EcsResource(ObjectsCallData.campaigntemplatecategories)
                                .query();


                } catch (e) {

                    $log.warn('getCampaignTemplateCategories () :: Error ', e);

                }
            },

            getCampaignTrophies: function () {
                try {
                    return new EcsResource(ObjectsCallData.campaigntrophies)
                                .query();
                } catch (e) {
                    $log.warn('getCampaigntrophies () :: Error ', e);
                }
            },

            getCreditCardTokenizeIFrameURL: function () {
                try {
                    return new EcsResource(ObjectsCallData.creditCardTokenizeIFrameURL).query();
                } catch (e) {
                    $log.warn('getCreditCardTokenizeIFrameURL () :: Error ', e);
                }
            }
        }

    }]);;angular
    .module('ecs.service.impl.stores', [])
    .constant('StoreCallData', {
        getAddressNames: 'stores/dkr/addressnames/supervisor/',
        saveBillingAddress: 'stores/dkr/addresses/Supervisor/',
        getAddresses: 'stores/dkr/addresses/:type/:id/',
        getAddressById: 'stores/:storecode/addresses/:type/:id/',
        searchAddresses: 'stores/:storecode/addresses/:addresstype/',
        getPurchaseReasonCodes: 'stores/:storecode/purchasereasoncodes/',
        validateCustomShippingAccountNumber: 'stores/:storecode/customshippingaccount/:customshippingaccountnumber/',
        getShippingMethods: 'stores/:storecode/shippingmethods/'
    })
    .factory('Stores', ['StoreCallData', 'EcsResource', '$log', function (StoreCallData, EcsResource, $log) {
        return {


            getAddressNames: function () {

                try {

                    return new EcsResource(StoreCallData.getAddressNames)
                            .query();


                } catch (e) {

                    $log.warn('getAddressNames () :: Error ', e);

                }

            },

            getAddress: function (id, type) {

                try {

                    return new EcsResource(StoreCallData.getAddresses)
                            .query({ ':id': id, ':type': type });


                } catch (e) {

                    $log.warn('getAddress () :: Error ', e);

                }

            },
            getAddressByAddressId: function (storeCode, type, id) {

                try {

                    return new EcsResource(StoreCallData.getAddressById)
                            .query({ ':storecode': storeCode, ':id': id, ':type': type });


                } catch (e) {

                    $log.warn('getAddress () :: Error ', e);

                }

            },
            saveBillingAddress: function (data) {

                try {

                    return new EcsResource(StoreCallData.saveBillingAddress)
                            .save(data);


                } catch (e) {

                    $log.warn('getAddress () :: Error ', e);

                }

            },

            searchAddresses: function (storeCode, type, query) {

                try {

                    return new EcsResource(StoreCallData.searchAddresses)
                                   .query({
                                       'skip': 0,
                                       'top': 999,
                                       'q': query,
                                       ':storecode' : storeCode,
                                       ':addresstype': type,
                                   });


                } catch (e) {

                    $log.warn('searchAddresses () :: Error ', e);

                }

            },

            getPurchaseReasonCodes: function (storeCode) {

                try {

                    return new EcsResource(StoreCallData.getPurchaseReasonCodes)
                        .query({
                            ':storecode': storeCode,
                        });


                } catch (e) {

                    $log.warn('getPurchaseReasonCodes () :: Error ', e);

                }
            },

            validateCustomShippingAccountNumber: function (storeCode, customShippingAccountNumber) {

                try {

                    return new EcsResource(StoreCallData.validateCustomShippingAccountNumber)
                        .query({
                            ':storecode': storeCode,
                            ':customshippingaccountnumber': customShippingAccountNumber,
                        });


                } catch (e) {

                    $log.warn('validateCustomShippingAccountNumber () :: Error ', e);

                }
            },

            getShippingMethods: function (storeCode) {

                try {

                    return new EcsResource(StoreCallData.getShippingMethods)
                        .query({
                            ':storecode': storeCode,
                        });


                } catch (e) {

                    $log.warn('getShippingMethods () :: Error ', e);

                }
            }

        }
    }]);;angular
    .module('ecs.service.impl.orders', [])
    .constant('OrdersCallData', {
        searchOrders: 'orders/',
        getOrder: 'orders/:orderid/',
        prepareOrder: 'orders/prepare',
        cancelOrderItem: 'orders/:orderId/lineitems/:itemid/',
        confirmationEmail: 'orders/:orderId/confirmationemail',
        getCopyrightLevyFeeByOrder: 'orders/:orderId/copyrightlevyfeebyorder/'
    })
    .factory('Orders', ['OrdersCallData', 'EcsResource', '$log', function (OrdersCallData, EcsResource, $log) {
        return {
          
          getCopyrightLevyFeeByOrder: function (orderNumber) {
                try {
                    var params = {};
                    params[':orderId'] = orderNumber;

                  return new EcsResource(OrdersCallData.getCopyrightLevyFeeByOrder)
                                .query(params);
                } catch (e) {
                  $log.warn('getCopyrightLevyFeeByOrder () :: Error ', e);
                }
            },

            searchOrders: function (params) {
                try {
                    return new EcsResource(OrdersCallData.searchOrders)
                        .query(params);
                } catch (e) {
                    $log.warn('searchOrders () :: Error ', e);
                }
            },

            getOrder: function (params) {
                try {
                    return new EcsResource(OrdersCallData.getOrder)
                        .query(params);
                } catch (e) {
                    $log.warn('getOrder () :: Error ', e);
                }
            },

            prepareOrder: function (model) {
                try {
                    return new EcsResource(OrdersCallData.prepareOrder)
                        .save(model);
                } catch (e) {
                    $log.warn('prepareOrder () :: Error ', e);
                }
            },

            cancelOrderItem: function (model) {
                try {
                    return new EcsResource(OrdersCallData.cancelOrderItem)
                        .remove(model);
                } catch (e) {
                    $log.warn('cancelOrderItem () :: Error ', e);
                }
            },

            confirmationEmail: function (model) {
                try {
                    return new EcsResource(OrdersCallData.confirmationEmail)
                        .save(model);
                } catch (e) {
                    $log.warn('confirmationEmail () :: Error ', e);
                }
            }
        }
    }]);;angular
    .module('ecs.service.impl.customers', [])
    .constant('CustomersCallData', {
        activateGiftCertificate: 'customers/:customerId/giftcertificates/activate/',
        addresses: {
            'shipping': 'customers/:customerId/shippingaddresses/:addressId/',
            'billing': 'customers/:customerId/billingaddresses/:addressId/'
        },
        address: {
            'shipping': 'customers/:customerId/shippingaddress/:addressId/',
            'billing': 'customers/:customerId/billingaddress/:addressId/'
        },
        createOrder: 'customers/:customerId/orders/',
        requestCartApproval: 'customers/:customerId/cartapprovals/',
        createShoppingCart: 'customers/:customerId/shoppingcarts/',
        customers: 'customers/:customerId/',
        getAwards: 'customers/:customerId/rewards/',
        getGiftCertificates: 'customers/:customerId/giftcertificates/',
        getShoppingCarts: 'customers/:customerId/shoppingcarts/',
        getShippingMethods: 'orders/shippingmethods',
        getPaymentMethods: 'orders/paymentmethods',
        getPurchaseBalances: 'customers/:customerId/purchasebalances/',
        getStartingBalance: 'customers/:customerId/budgetbalances/',
        paymentCards: 'customers/:customerId/paymentcards/',
        notificationPreferences: 'customers/:customerId/notificationpreferences/',
        searchCustomers: 'customers/',
        searchElectronicPurchases: 'customers/:customerId/electronicpurchases/',
        transferShoppingCart: 'customers/:customerId/shoppingcarts/:cartGuid/transfer/',
        searchCustomerApprovalCarts: 'customers/:customerId/approvalcarts/',
        searchOrders: 'customers/:customerId/orders/',
        searchBudgetHistories: 'customers/:customerId/budgethistory/',
        wishList: 'customers/:customerId/wishlist/:itemId/',
        authorizeCreditCards: 'customers/:customerId/paymentcardauthorize/',
        getLocations: 'customers/:customerId/locations/',
        setLocation: 'Shop/SelectLocation',
        storePasses: 'customers/:customerId/passes/:passType/',
        linkSSO: 'customers/linksso/',
        
    })
    .factory('Customers', ['CustomersCallData', 'EcsResource', '$log', function (CustomersCallData, EcsResource, $log) {

        return {


            getAwards: function (custId) {
                try {

                    return new EcsResource(CustomersCallData.getAwards)
                                .query({ ':customerId': custId });


                } catch (e) {

                    $log.warn('getAwards () :: Error ', e);

                }

            },

            getLocations: function (custId) {
                try {

                    return new EcsResource(CustomersCallData.getLocations)
                                .query({ ':customerId': custId });


                } catch (e) {

                    $log.warn('getLocations () :: Error ', e);

                }

            },

            setLocation: function (params) {
                try {

                    return new EcsResource(CustomersCallData.setLocation)
                                .save(params);


                } catch (e) {

                    $log.warn('setLocation () :: Error ', e);

                }

            },
            // activateGiftCertificate method

            activateGiftCertificate: function (custId, model) {

                try {
                    model[':customerId'] = custId;
                    return new EcsResource(CustomersCallData.activateGiftCertificate)
                            .save(model);



                } catch (e) {

                    $log.warn('activateGiftCertificate () :: Error ', e);

                }

            },




            // creatOrder method

            createOrder: function (model, message) {

                try {

                    model[':customerId'] = model.SoldToCustomerId;

                    return new EcsResource(CustomersCallData.createOrder)
                            .save(model, undefined, { 'message': message });



                } catch (e) {

                    $log.warn('createOrder () :: Error ', e);

                }

            },

            // requestCartApproval method

            requestCartApproval: function (model, message) {

                try {

                    model[':customerId'] = model.SoldToCustomerId;

                    return new EcsResource(CustomersCallData.requestCartApproval)
                            .save(model, undefined, { 'message': message });



                } catch (e) {

                    $log.warn('createOrder () :: Error ', e);

                }

            },

            // createShoppingCart

            createShoppingCart: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.createShoppingCart)
                                .save(model);


                } catch (e) {

                    $log.warn('createShoppingCart () :: Error ', e);

                }


            },


            getGiftCertificates: function (params) {
                try {

                    return new EcsResource(CustomersCallData.getGiftCertificates)
                                .query(params);


                } catch (e) {

                    $log.warn('getGiftCertificates () :: Error ', e);

                }

            },

            // getShoppingCarts

            getShoppingCarts: function (custId) {

                try {

                    var params = {};

                    params[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.getShoppingCarts)
                                .query(params);


                } catch (e) {

                    $log.warn('getShoppingCarts () :: Error ', e);

                }


            },

            getShippingMethods: function (params) {
                try {

                    return new EcsResource(OrdersCallData.getOrder)
                                .query(params);


                } catch (e) {

                    $log.warn('getShippingMethods () :: Error ', e);

                }

            },


            getPaymentMethods: function (params) {
                try {

                    return new EcsResource(OrdersCallData.getPaymentMethods)
                                .query(params);


                } catch (e) {

                    $log.warn('getPaymentMethods () :: Error ', e);

                }

            },

            

            // login method

            login: function (model) {

                try {

                    return new EcsResource(CustomersCallData.login)
                            .save(model);



                } catch (e) {

                    $log.warn('login () :: Error ', e);

                }

            },


            // Search Customers

            searchCustomers: function(params) {

                try {

                    return new EcsResource(CustomersCallData.searchCustomers)
                                .query(params);


                } catch (e) {

                    $log.warn('searchCustomers () :: Error ', e);

                }

            },

            // Search Orders

            searchCustomerApprovalCarts: function (params) {

                try {

                    return new EcsResource(CustomersCallData.searchCustomerApprovalCarts)
                        .query(params);


                } catch (e) {

                    $log.warn('searchCustomerApprovalCarts () :: Error ', e);

                }

            },

            // Search Orders

            searchOrders: function (params) {

                try {

                    return new EcsResource(CustomersCallData.searchOrders)
                        .query(params);


                } catch (e) {

                    $log.warn('searchOrders () :: Error ', e);

                }

            },


            // Search Budget Balance History Entries

            searchBudgetHistories: function (params) {

                try {

                    return new EcsResource(CustomersCallData.searchBudgetHistories)
                        .query(params);


                } catch (e) {

                    $log.warn('searchBudgetHistories () :: Error ', e);

                }

            },


            // transferShoppingCart

            transferShoppingCart: function (custId, cartGuid) {

                try {

                    var params = {};

                    params[':customerId'] = custId;
                    params[':cartGuid'] = cartGuid;

                    return new EcsResource(CustomersCallData.transferShoppingCart)
                                .query(params);


                } catch (e) {

                    $log.warn('createShoppingCart () :: Error ', e);

                }


            },

            // friendsandFamilypasses

            getCustomerStorePasses: function (customerId, passType) {

                try {

                    var params = {};

                    params[':customerId'] = customerId;
                    params[':passType'] = passType;

                    return new EcsResource(CustomersCallData.storePasses)
                                .query(params);
                }
                catch (e) {

                    $log.warn('getCustomerStorePasses() :: Error ', e);

                }


            },





            




            // update login method

            updateLogin: function (model) {

                model[':customerId'] = model.CustomerId;

                try {

                    return new EcsResource(CustomersCallData.updateLogin)
                            .update(model);



                } catch (e) {

                    $log.warn('updateLogin () :: Error ', e);

                }

            },


            linkSSO: function (model) {

                try {

                    return new EcsResource(CustomersCallData.linkSSO)
                            .save(model);



                } catch (e) {

                    $log.warn('linkSSO () :: Error ', e);

                }


            },








            // Customer crud (-d) methods
            // 


            getCustomer: function (custId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.customers)
                                .query(params);


                } catch (e) {

                    $log.warn('getCustomer () :: Error ', e);

                }
            },

            createCustomer: function (model) {

                try {

                    return new EcsResource(CustomersCallData.customers)
                            .save(model);



                } catch (e) {

                    $log.warn('createCustomer () :: Error ', e);

                }


            },

            updateCustomer: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.customers)
                            .update(model);


                } catch (e) {

                    $log.warn('updateCustomer ():: Error ', e);

                }



            },




            // CC auths methods
            authorizeCreditCards: function (custId, model) {
                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.authorizeCreditCards)
                            .save(model);



                } catch (e) {

                    $log.warn('authorizeCreditCards () :: Error ', e);

                }


            },



            //Notification preferences
            getNotificationPreferences: function (custId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.notificationPreferences)
                                .query(params);


                } catch (e) {

                    $log.warn('getNotificationPreferences () :: Error ', e);

                }
            },


            updateNotificationPreferences: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.notificationPreferences)
                            .update(model);


                } catch (e) {

                    $log.warn('updateNotificationPreferences ():: Error ', e);

                }



            },



            // Payment cards methods
            // leave itemId empty to get all items...



            getPaymentCards: function (custId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.paymentCards)
                                .query(params);


                } catch (e) {

                    $log.warn('getPaymentCards () :: Error ', e);

                }
            },

            addPaymentCard: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.paymentCards)
                            .save(model);



                } catch (e) {

                    $log.warn('addPaymentCard () :: Error ', e);

                }


            },

            updatePaymentCard: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.paymentCards)
                            .update(model);


                } catch (e) {

                    $log.warn('updatePaymentCard ():: Error ', e);

                }



            },

            removePaymentCard: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.paymentCards)
                            .removeWithData(model);

                } catch (e) {

                    $log.warn('removePaymentCard () :: Error ', e);

                }



            },







            //Wish list methods
            // leave itemId empty to get all items...

            getWishList: function (custId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;


                    return new EcsResource(CustomersCallData.wishList)
                                .query(params);


                } catch (e) {

                    $log.warn('getWishList :: Error ', e);

                }
            },

            getWishListItem: function (custId, itemId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;

                    if (itemId) {
                        params['itemId'] = itemId;
                    }

                    return new EcsResource(CustomersCallData.wishList)
                                .query(params);


                } catch (e) {

                    $log.warn('getWishList :: Error ', e);

                }
            },

            addWishListItem: function (custId, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.wishList)
                            .save(model);



                } catch (e) {

                    $log.warn('addWishList :: Error ', e);

                }


            },

            updateWishListItem: function (custId, model) {

                try {

                    model[':customerId'] = custId;
                    model[':itemId'] = model.ItemId;

                    return new EcsResource(CustomersCallData.wishList)
                            .update(model);


                } catch (e) {

                    $log.warn('getWishList ():: Error ', e);

                }



            },

            removeWishListItem: function (custId, model) {

                try {

                    model[':customerId'] = custId;
                    model[':itemId'] = model.ProductNumber;

                    return new EcsResource(CustomersCallData.wishList)
                            .remove(model);


                } catch (e) {

                    $log.warn('removeWishListItem () :: Error ', e);

                }



            },



            //History of Electronic Purchases
            searchElectronicPurchases: function (params) {

                try {

                    return new EcsResource(CustomersCallData.searchElectronicPurchases)
                                .query(params);


                } catch (e) {

                    $log.warn('searchElectronicPurchases () :: Error ', e);

                }

            },

            //Address methods

            getAddress: function (custId, addressType, addressId) {
                try {

                    var params = {};

                    params[':customerId'] = custId;

                    if (addressId) {
                        params[':addressId'] = addressId;
                    }

                    return new EcsResource(CustomersCallData.address[addressType]).query(params);


                } catch (e) {

                    $log.warn('getShippingAddress :: Error ', e);

                }
            },

            getAddresses: function (custId, addressType, mode) {
                try {

                    var params = {};

                    params[':customerId'] = custId;
                    //If mode is provided, send it in the params
                    if (mode) {
                        params['m'] = mode;
                    }

                    return new EcsResource(CustomersCallData.addresses[addressType]).query(params);


                } catch (e) {

                    $log.warn('getShippingAddresses :: Error ', e);

                }
            },

            addAddress: function (custId, addressType, model) {

                try {

                    model[':customerId'] = custId;

                    return new EcsResource(CustomersCallData.addresses[addressType.toLowerCase()])
                            .save(model);



                } catch (e) {

                    $log.warn('addShippingAddresses :: Error ', e);

                }


            },

            updateAddress: function (custId, model) {

                try {

                    model.AddressType = model.AddressType || 'shipping';

                    model[':customerId'] = custId;
                    model[':addressId'] = model.AddressId;

                    return new EcsResource(CustomersCallData.addresses[model.AddressType.toLowerCase()])
                            .update(model);


                } catch (e) {

                    $log.warn('getShippingAddresses ():: Error ', e);

                }



            },

            removeAddress: function (custId, model) {

                try {

                    model[':customerId'] = custId;
                    model[':addressId'] = model.AddressId;

                    model.AddressType = model.AddressType || 'shipping';

                    return new EcsResource(CustomersCallData.addresses[model.AddressType.toLowerCase()])
                            .remove(model);


                } catch (e) {

                    $log.warn('removeShippingAddresses() :: Error ', e);

                }



            },

            //get purchase Balances
            getPurchaseBalances: function (customerId) {
                try {

                    var params = {};

                    params[':customerId'] = customerId;
                    return new EcsResource(CustomersCallData.getPurchaseBalances)
                        .query(params);


                } catch (e) {

                    $log.warn('customers.getPurchaseBalances () :: Error ', e);

                }

            },


            //Retrieves the budget balance based on a date's month.
            getStartingBalance: function (params) {
                try {
                    return new EcsResource(CustomersCallData.getStartingBalance)
                        .query(params);


                } catch (e) {

                    $log.warn('customers.getStartingBalance () :: Error ', e);

                }

            }

        }


    }]);;angular
    .module('ecs.service.impl.promoCodes', [])
    .constant('PromoCodesCallData', {

        promoCodes: 'promocodes/:promocode/',

    })
    .factory('PromoCodes', ['PromoCodesCallData', 'EcsResource', '$log', function (PromoCodesCallData, EcsResource, $log) {

        return {

            searchPromoCodes: function (params) {

                try {

                    return new EcsResource(PromoCodesCallData.promoCodes)
                                .query(params);


                } catch (e) {

                    $log.warn('searchPromoCodes () :: Error ', e);

                }

            },

            verifyPromoCode: function (params) {

                try {

                    return new EcsResource(PromoCodesCallData.promoCodes)
                                .query(params);


                } catch (e) {

                    $log.warn('verifyPromoCode () :: Error ', e);

                }

            },
            // see http://stackoverflow.com/questions/4474352/send-jquery-json-to-wcf-rest-using-date for date info
            createPromoCode: function (model) {
                try {

                    return new EcsResource(PromoCodesCallData.promoCodes)
                                .save(model);


                } catch (e) {

                    $log.warn('createPromoCode () :: Error ', e);

                }

            },
            updatePromoCode: function (params) {
                try {

                    return new EcsResource(PromoCodesCallData.promoCodes)
                                .update(params);


                } catch (e) {

                    $log.warn('updatePromoCode () :: Error ', e);

                }

            }


        }

    }]);;angular
    .module('ecs.service.impl.products', [])
    .constant('ProductsCallData', {

        getProduct: 'products/:sku/',
        getSelectedProducts: 'products/',
        productMetaData: 'products/:sku/metadata',
        searchProducts: 'products/',
        getRelatedProducts: 'products/:sku/relatedproducts/',
        shareProduct: 'products/:sku/social/:shareType/',
        getChildProducts: 'products/:sku/childproducts/',
        getBackendChildProducts: 'products/backend/:sku/childproducts/',
        sendBulkOrderRequest: 'products/:sku/bulkorders/',
        getQRCode: 'getQRCode.ashx',
        getOutstandingPOs: 'products/:sku/purchaseorders/',
        getPersonalizationLite: 'products/:sku/personalizationlite/',
        getPersonalizationLiteLookups: 'products/:personalizationliteid/personalizationlitelookups/',
    })
    .factory('Products', ['ProductsCallData', 'EcsResource', '$log','Config', function (ProductsCallData, EcsResource, $log, Config) {

        return {

            getQRCode: function(params) {

                try {

                    return new EcsResource(ProductsCallData.getQRCode)
                                .query(params);


                } catch (e) {

                    $log.warn('getQRCode () :: Error ', e);

                }
            },

            getProduct: function (params) {
                try {

                    return new EcsResource(ProductsCallData.getProduct)
                                .query(params);


                } catch (e) {

                    $log.warn('getProduct () :: Error ', e);

                }

            },

            getSelectedProducts: function (productSlugs) {
                try {
                    return new EcsResource(ProductsCallData.getSelectedProducts)
                        .save('', productSlugs);


                } catch (e) {

                    $log.warn('getProduct () :: Error ', e);

                }

            },

            getPersonalizationLite: function (params) {
                try {

                    return new EcsResource(ProductsCallData.getPersonalizationLite)
                        .query(params);


                } catch (e) {

                    $log.warn('getPersonalizationLite () :: Error ', e);

                }

            },

            getPersonalizationLiteLookup: function (params) {
                try {

                    return new EcsResource(ProductsCallData.getPersonalizationLiteLookups)
                        .query(params);


                } catch (e) {

                    $log.warn('getPersonalizationLiteLookups () :: Error ', e);

                }

            },


            productMetaData: function (params) {
                try {

                    return new EcsResource(ProductsCallData.productMetaData)
                                .query(params);


                } catch (e) {

                    $log.warn('productMetaData () :: Error ', e);

                }

            },

            searchProducts: function (params) {
                try {

                    return new EcsResource(ProductsCallData.searchProducts)
                                .query(params);


                } catch (e) {

                    $log.warn('searchProducts () :: Error ', e);

                }

            },

            getRelatedProducts: function (params) {
                try {

                    return new EcsResource(ProductsCallData.getRelatedProducts)
                                .query(params);


                } catch (e) {

                    $log.warn('getRelatedProducts () :: Error ', e);

                }

            },

            shareProduct: function (sku, shareType, model) {
                try {

                    model[':sku'] = sku;
                    model[':shareType'] = shareType;

                    return new EcsResource(ProductsCallData.shareProduct)
                                .save(model);


                } catch (e) {

                    $log.warn('shareProduct () :: Error ', e);

                }

            },

            getChildProducts: function (sku) {
                try {

                    var params = {};
                    params[':sku'] = sku;

                    return new EcsResource(ProductsCallData.getChildProducts)
                                .query(params);


                } catch (e) {

                    $log.warn('getChildProducts () :: Error ', e);

                }

            },

            getBackendChildProducts: function (sku) {
                try {

                    var params = {};
                    params[':sku'] = sku;

                    return new EcsResource(ProductsCallData.getBackendChildProducts)
                                .query(params);


                } catch (e) {

                    $log.warn('getBackendChildProducts () :: Error ', e);

                }

            },

            sendBulkOrderRequest: function (sku, model) {
                try {

                    model[':sku'] = sku;
                    return new EcsResource(ProductsCallData.sendBulkOrderRequest)
                                .save(model);

                } catch (e) {

                    $log.warn('getProduct () :: Error ', e);
                }
            },

            getOutstandingPOs: function (sku) {
                try {

                    var params = {};
                    params[':sku'] = sku;

                    return new EcsResource(ProductsCallData.getOutstandingPOs)
                                .query(params);
                } catch (e) {

                    $log.warn('getOutstandingPOs () :: Error ', e);
                }
            }
        }

    }]).service('ProductUrlService', ['Config', function (Config) {
            var self = this;

            self.getUrl = function (productSlug) {
                return "#/product/" + productSlug;
            };

            self.getImageUrl = function (productFileName, productFileExtension, size) {
                if (!size) size = ""; else size = "-" + size;

                if (productFileName.indexOf('.') !== -1) {
                    var fileNameParts = productFileName.split('.');
                    return (Config.ProductImageBaseURL + fileNameParts[0] + size + productFileExtension);
                }
                else {
                    return (Config.ProductImageBaseURL + productFileName + size + productFileExtension);
                }

                
            };

            self.getNoImageUrl = function (size) {
                if (!size) size = ""; else size = "-"+size;

                return Config.ProductImageBaseURL + size +".jpg";
            };
    }]).service('ProductUIService', ['Config', '$uibModal', function (Config, $uibModal) {
        var self = this;

        self.isLinkAttribute = function (attribute) {
            // data either comes from RootProductAdditionalInfo table or Facet/FacetValue tables            
            if (attribute.TypeName && (attribute.TypeName.toLowerCase() === 'external link' || attribute.TypeName.toLowerCase() === 'spec sheet')) {
                return true;
            } else if (attribute.Type && attribute.Type.toLowerCase() === 'pdplink') {
                return true;
            } else {
                return false;
            }
        };

        self.isPopupLinkAttribute = function (attribute) {
            // data either comes from RootProductAdditionalInfo table or Facet/FacetValue tables
            if (attribute.TypeName && attribute.TypeName.toLowerCase() === 'size chart') {
                return true;
            } else if (attribute.Type && attribute.Type.toLowerCase() === 'pdppopuplink') {
                return true;
            } else {
                return false;
            }
        };

        self.showProductAdditionalInfo = function (product, info) {
            $uibModal.open({
                //templateUrl: App.Configuration.RootPath+'Content/app/html/ProductInfoPopup.html',
                templateUrl: 'ProductInfoPopup.html',
                controller: 'productInfoPopupCtrl',
                size: 'lg',
                resolve: {
                    product: function () {
                        return product;
                    },
                    info: function () {
                        return info;
                    }
                }
            });
        };
    }]).controller('productInfoPopupCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'product',
        'info',
        function ($scope, Common, $uibModalInstance, product, info) {

            $scope.product = product;
            $scope.info = info;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };
        }
    ]);;;angular
    .module('ecs.service.impl.catalogs', [])
    .constant('CatalogsCallData', {

        getCatalogs: 'catalogs/', //?show={showAllOrActive}
        getCatalog: 'catalogs/:catalogId',
        updateCatalog: 'catalogs/:catalogId',
        getCatalogProducts: 'catalogs/:catalogId/products/' //?top={top}&skip={skip}&q={query}

        
    })
    .factory('Catalogs', ['CatalogsCallData', 'EcsResource', '$log', function (CatalogsCallData, EcsResource, $log) {

        return {

            getCatalogs: function (params) {
                try {

                    return new EcsResource(CatalogsCallData.getCatalogs)
                                .query(params);


                } catch (e) {

                    $log.warn('getCatalogs () :: Error ', e);

                }

            },

            getCatalog: function (params) {
                try {

                    return new EcsResource(CatalogsCallData.getCatalog)
                                .query(params);


                } catch (e) {

                    $log.warn('getCatalog () :: Error ', e);

                }

            },

            updateCatalog: function (params) {
                try {

                    return new EcsResource(CatalogsCallData.updateCatalog)
                                .query(params);


                } catch (e) {

                    $log.warn('updateCatalog () :: Error ', e);

                }

            },

            getCatalogProducts: function (params) {
                try {

                    return new EcsResource(CatalogsCallData.getCatalogProducts)
                                .query(params);


                } catch (e) {

                    $log.warn('getCatalogProducts () :: Error ', e);

                }

            }

        }

    }]);;angular
    .module('ecs.service.impl.shoppingCarts', [])
    .constant('ShoppingCartAPITemplates', {
        cart: 'shoppingcarts/:cartId/',
        cartByGuid: 'shoppingcarts/:cartGuid/',
        cartItem: 'shoppingcarts/:cartId/items/:productNumber/',
        multipleCartItems: 'shoppingcarts/:cartId/multipleitems/',
        cartCheckout: 'shoppingcarts/:cartId/checkout/',
        cartCheckoutByGuid: 'shoppingcarts/:cartGuid/checkout/',
        getCartDetailsByGuid: 'shoppingcarts/:cartGuid/details/',
        cartPromoCode: 'shoppingcarts/:cartId/promocodes/:promoCode/',
        cartPunchout: 'shoppingcarts/:punchoutSessionId/punchout/', // Punchout stories EST 164,167,166,168
        cartRelatedProducts: 'shoppingcarts/:cartId/relatedProducts/',
        checkoutpromocodes: 'shoppingcarts/:cartId/checkoutpromocodes/:promoCode/',
        getShippingMethods: 'shoppingcarts/:cartId/shippingmethods/',
        getPaymentMethods: 'shoppingcarts/:cartId/paymentmethods/',
        getApproverGroups: 'shoppingcarts/approvergroups',
        emailCart: 'shoppingcarts/:cartId/emails/',
        getCopyrightLevyFeeByCart: 'shoppingcarts/:cartId/copyrightlevyfeebycart/',
        updateCartBillingAddress: 'shoppingcarts/:cartGuid/guestcheckout/billingaddress',
        updateCartShippingAddress: 'shoppingcarts/:cartGuid/guestcheckout/shippingaddress',
        searchCarts: 'shoppingcarts/storeOrders/',
    })
    .factory('ShoppingCarts', ['ShoppingCartAPITemplates', 'EcsResource', '$log', function (ShoppingCartAPITemplates, EcsResource, $log) {

        return {

            searchShoppingCarts: function (params) {
                try {
                    return new EcsResource(ShoppingCartAPITemplates.searchCarts).query(params);
                } catch (e) {
                    $log.warn('searchShoppingCarts () :: Error ', e);
                }
            },

            getCopyrightLevyFeeByCart: function (cartId) {
                try {
                    var params = {};
                    params[':cartId'] = cartId;

                    return new EcsResource(ShoppingCartAPITemplates.getCopyrightLevyFeeByCart)
                        .query(params);
                } catch (e) {
                    $log.warn('getCopyrightLevyFeeByCart () :: Error ', e);
                }
            },

            createAnonymousCart: function (model) {

                try {

                    return new EcsResource(ShoppingCartAPITemplates.cart)
                        .save(model);

                } catch (e) {

                    $log.warn('addCartItem :: Error ', e);

                }
            },

            addCartItem: function (cartid, model) {

                try {

                    model[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cartItem)
                        .save(model);



                } catch (e) {

                    $log.warn('addCartItem :: Error ', e);

                }
            },
            addMultipleCartItem: function (cartid, dataArray) {

                try {

                    var params = {};
                    params[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.multipleCartItems)
                        .save(params, dataArray);



                } catch (e) {

                    $log.warn('addCartItem :: Error ', e);

                }
            },

            updateCartItem: function (cartid, model) {

                try {

                    model[':cartId'] = cartid;
                    model[':productNumber'] = model.ProductNumber;

                    return new EcsResource(ShoppingCartAPITemplates.cartItem)
                        .update(model);



                } catch (e) {

                    $log.warn('updateCartItem :: Error ', e);

                }
            },

            removeCartItem: function (cartid, model) {

                try {

                    model[':cartId'] = cartid;
                    model[':productNumber'] = model.ProductNumber;

                    return new EcsResource(ShoppingCartAPITemplates.cartItem)
                        .remove(model);



                } catch (e) {

                    $log.warn('removeCartItem :: Error ', e);

                }
            },
            removePromoCode: function (cartid, model) {

                try {

                    var params = {};

                    params[':cartId'] = cartid;
                    params[':promoCode'] = model.Code;

                    return new EcsResource(ShoppingCartAPITemplates.cartPromoCode)
                        .remove(params);



                } catch (e) {

                    $log.warn('removePromoCode :: Error ', e);

                }
            },
            applyPromoCode: function (cartid, model) {

                try {

                    model[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cartPromoCode)
                        .save(model);



                } catch (e) {

                    $log.warn('applyPromoCode :: Error ', e);

                }
            },

            emailCart: function (cartId, model) {
                try {

                    model[':cartId'] = cartId;

                    return new EcsResource(ShoppingCartAPITemplates.emailCart)
                        .update(model);


                } catch (e) {

                    $log.warn('emailCart () :: Error ', e);

                }

            },

            removePromoCodeOnCheckout: function (cartid, code) {

                try {

                    var params = {};

                    params[':cartId'] = cartid;
                    params[':promoCode'] = code;

                    return new EcsResource(ShoppingCartAPITemplates.checkoutpromocodes)
                        .remove(params);



                } catch (e) {

                    $log.warn('removePromoCodeOnCheckout :: Error ', e);

                }
            },
            applyPromoCodeOnCheckout: function (cartid, model) {

                try {

                    model[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.checkoutpromocodes)
                        .save(model);



                } catch (e) {

                    $log.warn('applyPromoCodeOnCheckout :: Error ', e);

                }
            },

            deleteCart: function (cartid) {

                try {

                    var params = {};

                    params[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cart)
                        .remove(params);



                } catch (e) {

                    $log.warn('deleteCart :: Error ', e);

                }
            },


            getRelatedProducts: function (cartid) {
                try {
                    var params = {};
                    params[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cartRelatedProducts)
                        .query(params);


                } catch (e) {

                    $log.warn('getRelatedProducts () :: Error ', e);

                }
            },


            getCheckout: function (cartid) {
                try {
                    var params = {};
                    params[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cartCheckout)
                        .query(params);


                } catch (e) {

                    $log.warn('getCheckout () :: Error ', e);

                }
            },

            getCheckoutByGuid: function (cartguid) {
                try {
                    var params = {};
                    params[':cartGuid'] = 'GUID-' + cartguid;
                    return new EcsResource(ShoppingCartAPITemplates.cartCheckoutByGuid).query(params);
                } catch (e) {
                    $log.warn('getCheckout () :: Error ', e);
                }
            },

            updateCheckout: function (model) {
                try {

                    model[':cartId'] = model.CartId;
                    return new EcsResource(ShoppingCartAPITemplates.cartCheckout)
                        .update(model);


                } catch (e) {

                    $log.warn('getCheckout () :: Error ', e);

                }
            },

            getCart: function (cartid) {
                try {
                    var params = {};
                    params[':cartId'] = cartid;

                    return new EcsResource(ShoppingCartAPITemplates.cart)
                        .query(params);


                } catch (e) {

                    $log.warn('getRelatedProducts () :: Error ', e);

                }
            },

            getCartByGuid: function (cartguid) {
                try {
                    var params = {};
                    params[':cartGuid'] = 'GUID-' + cartguid;

                    return new EcsResource(ShoppingCartAPITemplates.cartByGuid).query(params);
                } catch (e) {
                    $log.warn('getRelatedProducts () :: Error ', e);
                }
            },

            getCartDetailsByGuid: function (cartguid) {
                try {
                    var params = {};
                    params[':cartGuid'] = 'GUID-' + cartguid;
                    return new EcsResource(ShoppingCartAPITemplates.getCartDetailsByGuid).query(params);
                } catch (e) {
                    $log.warn('getCartDetailsByGuid () :: Error ', e);
                }
            },

            getShippingMethods: function (model) {
                try {
                    return new EcsResource(ShoppingCartAPITemplates.getShippingMethods)
                        .query(model);
                } catch (e) {
                    $log.warn('getShippingMethods () :: Error ', e);
                }
            },

            getPaymentMethods: function (cartid) {
                try {
                    var params = {};
                    params[':cartId'] = cartid;
                    return new EcsResource(ShoppingCartAPITemplates.getPaymentMethods).query(params);
                } catch (e) {
                    $log.warn('getPaymentMethods () :: Error ', e);
                }
            },

            getApproverGroups: function (paymentMethodCode) {
                try {
                    var params = {
                        paymentMethodCode: paymentMethodCode
                    }
                    return new EcsResource(ShoppingCartAPITemplates.getApproverGroups)
                        .query(params);
                }

                catch (e) {

                    $log.warn('getApprovalGroups () :: Error ', e);

                }
            },

            // Punchout stories EST 164,167,166,168
            getCartByPunchoutSessionId: function (punchoutSessionId) {
                try {
                    var params = {};
                    params[':punchoutSessionId'] = punchoutSessionId;

                    return new EcsResource(ShoppingCartAPITemplates.cartPunchout)
                        .query(params);

                } catch (e) {

                    $log.warn('getCartByPunchoutSessionId () :: Error ', e);

                }
            },

            updateCartBillingAddress: function (cartGuid, address) {
                try {
                    var params = {
                        ':cartGuid': cartGuid
                    };

                    return new EcsResource(ShoppingCartAPITemplates.updateCartBillingAddress).update(params, address);
                } catch (e) {
                    $log.warn('updateCartBillingAddress () :: Error ', e);
                }
            },

            updateCartShippingAddress: function (cartGuid, address) {
                try {
                    var params = {
                        ':cartGuid': cartGuid
                    };

                    return new EcsResource(ShoppingCartAPITemplates.updateCartShippingAddress).update(params, address);
                } catch (e) {
                    $log.warn('updateCartShippingAddress () :: Error ', e);
                }
            }
        }
    }]);;angular
    .module('ecs.service.impl.employees', [])
    .constant('EmployeesCallData', {
        verifyEmployee: 'employees/verify/',
        searchEmployees: 'employees/',
        getEmployeeTypes: 'employees/employeetypes/',
        getEmployee: 'employees/:employeeid/',
        addEmployee: 'employees/',
        updateEmployee: 'employees/:employeeid/',
        getPurchaseBalances: 'employees/:employeeid/purchasebalances/',
        SearchPurchaseTransactionHistory: 'employees/:employeeid/purchasetransactions/',
        AddPurchaseBalanceAdjustment: 'employees/:employeeid/purchasebalanceadjustments/'

    })
    .factory('Employees', ['EmployeesCallData', 'EcsResource', '$log', function (EmployeesCallData, EcsResource, $log) {

        return {




            //verify Employee
            verifyEmployee: function (model) {

                try {

                    return new EcsResource(EmployeesCallData.verifyEmployee)
                            .save(model);



                } catch (e) {

                    $log.warn('verifyEmployee () :: Error ', e);

                }

            },



            //search Employees
            searchEmployees: function (params) {

                try {

                    return new EcsResource(EmployeesCallData.searchOrders)
                            .query(params);



                } catch (e) {

                    $log.warn('searchEmployees () :: Error ', e);

                }

            },

            //get employee Types
            getEmployeeTypes: function (model) {

                try {

                    return new EcsResource(EmployeesCallData.verifyEmployee)
                            .save(model);



                } catch (e) {

                    $log.warn('getEmployeeTypes () :: Error ', e);

                }

            },



            //get a particular order
            getEmployee: function (id) {
                try {

                    return new EcsResource(EmployeesCallData.getEmployee)
                                .query({ ':employeeid': id });


                } catch (e) {

                    $log.warn('getEmployee () :: Error ', e);

                }

            },

            //add Employee
            addEmployee: function (model) {

                try {

                    return new EcsResource(EmployeesCallData.addEmployee)
                            .save(model);



                } catch (e) {

                    $log.warn('addEmployee () :: Error ', e);

                }

            },



            //update employee
            updateEmployee: function (model) {

                try {

                    return new EcsResource(EmployeesCallData.updateEmployee)
                            .save(model);



                } catch (e) {

                    $log.warn('updateEmployee () :: Error ', e);

                }

            },

            //get purchase Balances
            getPurchaseBalances: function (employeeid) {
                try {

                    var params = {};

                    params[':employeeid'] = employeeid;
                    return new EcsResource(EmployeesCallData.getPurchaseBalances)
                                .query(params);


                } catch (e) {

                    $log.warn('getPurchaseBalances () :: Error ', e);

                }

            },

            //search purchase Transaction History
            SearchPurchaseTransactionHistory: function (params) {
                try {

                    return new EcsResource(EmployeesCallData.SearchPurchaseTransactionHistory)
                                .query(params);


                } catch (e) {

                    $log.warn('SearchPurchaseTransactionHistory () :: Error ', e);

                }

            },

            //Add Purchase Balance Adjustment
            AddPurchaseBalanceAdjustment: function (params) {
                try {

                    return new EcsResource(EmployeesCallData.AddPurchaseBalanceAdjustment)
                                .query(params);


                } catch (e) {

                    $log.warn('AddPurchaseBalanceAdjustment () :: Error ', e);

                }

            }



        }


    }]);;angular
    .module('ecs.service.impl.electronicPurchases', [])
    .constant('ElectronicPurchasesCallData', {
        searchElectronicPurchases: 'electronicpurchases/',
        getElectronicPurchases: 'electronicpurchases/:purchaseid/',
        updateMemo: 'electronicpurchases/:purchaseid/memo',
        updateElectronicPurchases: 'electronicpurchases/:purchaseid/',
        addElectronicPurchasesEmail: 'electronicpurchases/:purchaseid/email/',
        refreshElectronicPurchaseLinks: 'electronicpurchases/:purchaseid/refreshlinks/',
        resendElectronicPurchase: 'electronicpurchases/:purchaseid/email'


    })
    .factory('ElectronicPurchases', ['ElectronicPurchasesCallData', 'EcsResource', '$log', function (ElectronicPurchasesCallData, EcsResource, $log) {

        return {

            //search Electronic Purchases
            searchElectronicPurchases: function (params) {

                try {

                    return new EcsResource(ElectronicPurchasesCallData.searchElectronicPurchases)
                            .query(params);



                } catch (e) {

                    $log.warn('searchElectronicPurchases () :: Error ', e);

                }

            },
            //get electronic purchases
            getElectronicPurchases: function (params) {
                try {

                    return new EcsResource(ElectronicPurchasesCallData.getElectronicPurchases)
                                .query(params);


                } catch (e) {

                    $log.warn('getElectronicPurchases () :: Error ', e);

                }

            },

            //update Electronic Purchases
            updateElectronicPurchases: function (params) {
                try {

                    return new EcsResource(ElectronicPurchasesCallData.updateElectronicPurchases)
                                .query(params);


                } catch (e) {

                    $log.warn('updateElectronicPurchases () :: Error ', e);

                }

            },

            //update Electronic Purchases
            updateMemo: function (model) {
                try {
                    model[':purchaseid'] = model.ElectronicPurchaseGuid;
                    return new EcsResource(ElectronicPurchasesCallData.updateMemo)
                                .update(model);


                } catch (e) {

                    $log.warn('updateMemo () :: Error ', e);

                }

            },

            //Add electronic purchases email.
            addElectronicPurchasesEmail: function (params) {
                try {

                    return new EcsResource(ElectronicPurchasesCallData.addElectronicPurchasesEmail)
                                .query(params);


                } catch (e) {

                    $log.warn('addElectronicPurchasesEmail () :: Error ', e);

                }

            },


            // Add refresh electronic purchases links
            refreshElectronicPurchaseLinks: function (params) {
                try {

                    return new EcsResource(ElectronicPurchasesCallData.refreshElectronicPurchaseLinks)
                                .query(params);


                } catch (e) {

                    $log.warn('refreshElectronicPurchaseLinks () :: Error ', e);

                }

            },

            // Resend electronic purchase
            resendElectronicPurchase: function (model) {
                try {

                    return new EcsResource(ElectronicPurchasesCallData.resendElectronicPurchase)
                                .update(model);


                } catch (e) {

                    $log.warn('resendElectronicPurchase () :: Error ', e);

                }

            }



        }


    }]);;angular
    .module('ecs.service.impl.notifications', [])
    .constant('NotificationsCallData', {
        searchNotifications: 'notifications/',
        createNotification: 'notifications/',
        getNotification: 'notifications/:notificationId/',
        resendNotification: 'notifications/:notificationId/resend/',
        updateNotification: 'notifications/:notificationId/'

    })
    .factory('Notifications', ['NotificationsCallData', 'EcsResource', '$log', function (NotificationsCallData, EcsResource, $log) {

        return {

            
             //search notifications
            searchNotifications: function (params) {

                try {

                    return new EcsResource(NotificationsCallData.searchNotifications)
                            .query(params);



                } catch (e) {

                    $log.warn('searchNotifications () :: Error ', e);

                }

            },

            


            //get notification
            getNotification: function (params) {
                try {

                    return new EcsResource(NotificationsCallData.getNotification)
                                .query(params);


                } catch (e) {

                    $log.warn('getNotification () :: Error ', e);

                }

            },

            //create notification
            createNotification: function (model) {

                try {

                    return new EcsResource(NotificationsCallData.createNotification)
                            .save(model);



                } catch (e) {

                    $log.warn('createNotification () :: Error ', e);

                }

            },



            //update employee
            updateNotification: function (model) {

                try {

                    return new EcsResource(NotificationsCallData.updateNotification)
                            .save(model);



                } catch (e) {

                    $log.warn('updateNotification () :: Error ', e);

                }

            },

            //resend notifications
            resendNotification: function (params) {
                try {

                    return new EcsResource(NotificationsCallData.resendNotification)
                                .query(params);


                } catch (e) {

                    $log.warn('resendNotification () :: Error ', e);

                }

            }

         }


    }]);;angular
    .module('ecs.service.impl.storePasses', [])
    .constant('StorePassesCallData', {
        verifyStorePass: 'storepasses/verify/',
        createStorePass: 'storepasses/',
        storePass: 'storepasses/:passid/',
        storePassApprovers: 'storepasses/passtypes/:passType/approvers/',
        storePassEvents: 'storepasses/events/',
        storePassEvent: 'storepasses/events/:eventid/',
        storePassEventApprovals: 'storepasses/events/:eventid/approvals/',
        storePassEventNotifications: 'storepasses/events/:eventid/notifications/',

    })
    .factory('StorePasses', ['StorePassesCallData', 'EcsResource', '$log', function (StorePassesCallData, EcsResource, $log) {

        return {



            
            //verify StorePass
            verifyStorePass: function (model) {

                try {

                    return new EcsResource(StorePassesCallData.verifyStorePass)
                            .save(model);



                } catch (e) {

                    $log.warn('verifyStorePass () :: Error ', e);

                }

            },
            
            //create StorePass
            createStorePass: function (model) {

                try {

                    return new EcsResource(StorePassesCallData.createStorePass)
                            .save(null, model);



                } catch (e) {

                    $log.warn('createStorePass() :: Error ', e);

                }

            },


            //delete StorePass
            deleteStorePass: function (passid) {

                try {

                    return new EcsResource(StorePassesCallData.storePass)
                            .remove({
                                ':passid': passid
                            });



                } catch (e) {

                    $log.warn('deleteStorePass() :: Error ', e);

                }

            },

            
            //Update StorePass
            updateStorePass: function (passid, model) {

                try {
                    var params = {};

                    params[':passid'] = passid;

                    return new EcsResource(StorePassesCallData.storePass)
                            .update(params, model);



                } catch (e) {

                    $log.warn('updateStorePass() :: Error ', e);

                }

            },
            searchStorePassEvents: function (params) {
                try {

                    return new EcsResource(StorePassesCallData.storePassEvents)
                                .query(params);


                } catch (e) {

                    $log.warn('searchStorePassEvents () :: Error ', e);

                }

            },

            getStorePassEvent: function (eventId) {
                    try {
                        var params = {};

                        params[':eventid'] = eventId;

                        return new EcsResource(StorePassesCallData.storePassEvent)
                                    .query(params);


                    } catch (e) {

                        $log.warn('getStorePassEvent () :: Error ', e);

                    }

            },
            searchStorePassApprovers: function (passType, searchTerm) {
                try {
                    var params = {};
                    params[':passType'] = passType;
                    params['q'] = searchTerm;

                    return new EcsResource(StorePassesCallData.storePassApprovers)
                                .query(params);


                } catch (e) {

                    $log.warn('searchStorePassApprovers () :: Error ', e);

                }

            },

            createStorePassEvent: function (model) {
                try {
                    return new EcsResource(StorePassesCallData.storePassEvents).save(model);
                } catch (e) {
                    $log.warn('createStorePassEvent () :: Error ', e);
                }
            },

            approveStorePassEvent: function (eventid, model) {
                try {
                    model[':eventid'] = eventid;
                    return new EcsResource(StorePassesCallData.storePassEventApprovals).save(model);
                } catch (e) {
                    $log.warn('approveStorePassEvent () :: Error ', e);
                }
            },

            resendStorePassEventApproval: function (eventid) {
                try {
                    var model = {};
                    model[':eventid'] = eventid;
                    return new EcsResource(StorePassesCallData.storePassEventNotifications).save(model);
                } catch (e) {
                    $log.warn('approveStorePassEvent () :: Error ', e);
                }
            },

        }


    }]);;angular
    .module('ecs.service.impl.rewards', [])
    .constant('RewardsCallData', {
        rewards: 'rewards/',
        reward: 'rewards/:rewardid/',
        getGiftCodeReward: 'rewards/rewardgiftcodes/:giftCode/',
        rewardShippingAddress: 'rewards/:rewardid/shippingaddress/',
        redeemRewards: 'rewards/:rewardid/redeem/',
        createCampaign: 'rewards/campaigns/',
        createGiftCodes: 'rewards/rewardgiftcodes/generate/',
        validateRewardGiftCode: 'rewards/rewardgiftcodes/:promoCode/validate/',
        resetReward: 'rewards/:rewardid/reset/',
        resendReward: 'rewards/:rewardid/:updatedemail/resend/'
    })
    .factory('Rewards', ['RewardsCallData', 'EcsResource', '$log', function (RewardsCallData, EcsResource, $log) {
    return {
        searchRewards: function (skip, top, query) {
            try {
                return new EcsResource(RewardsCallData.rewards)
                    .query({
                        'skip': skip,
                        'top': top,
                        'q': query
                    });
            } catch (e) {
                $log.warn('searchRewards () :: Error ', e);
            }
        },

        //Get a reward by ID
        getReward: function (rewardid) {
            try {
                return new EcsResource(RewardsCallData.reward)
                    .query({
                        ':rewardid': rewardid
                    }, {
                        bypassErrorInterceptor: true
                    });
            } catch (e) {
                $log.warn('getRewards () :: Error ', e);
            }
        },

        //Get a reward by giftCode
        getGiftCodeReward: function (giftCode) {
            try {
                return new EcsResource(RewardsCallData.getGiftCodeReward)
                    .query({
                        ':giftCode': giftCode
                    }, {
                        bypassErrorInterceptor: true
                    });
            } catch (e) {
                $log.warn('getGiftCodeReward () :: Error ', e);
            }
        },

        //Redeem a reward
        redeemRewards: function (rewardid, model, message) {
            try {
                model[':rewardid'] = rewardid;

                return new EcsResource(RewardsCallData.redeemRewards)
                            .save(model, undefined, { 'message': message });
            } catch (e) {
                $log.warn('redeemRewards () :: Error ', e);
            }
        },

        //Update a reward
        updateReward: function (rewardid, model) {
            try {
                model[':rewardid'] = rewardid;

                return new EcsResource(RewardsCallData.reward)
                            .save(model);
            } catch (e) {
                $log.warn('updateRewards () :: Error ', e);
            }
        },

        //Reset a reward
        resetReward: function (rewardid) {
            try {
                return new EcsResource(RewardsCallData.resetReward)
                    .save({
                        ':rewardid': rewardid
                    });
            } catch (e) {
                $log.warn('resetReward () :: Error ', e);
            }
        },

        //Resend a reward email
        resendReward: function (rewardid, updatedemail) {
            try {
                return new EcsResource(RewardsCallData.resendReward)
                    .save({
                        ':rewardid': rewardid,
                        ':updatedemail': updatedemail
                    });
            } catch (e) {
                $log.warn('resendReward () :: Error ', e);
            }
        },

        //Update a reward Shipping Address
        updateRewardShippingAddress: function (rewardid, model) {
            try {
                model[':rewardid'] = rewardid;

                return new EcsResource(RewardsCallData.rewardShippingAddress)
                            .update(model);
            } catch (e) {
                $log.warn('updateRewards () :: Error ', e);
            }
        },

        //Create reward campaign
        createCampaign: function (data) {
            try {
            
                return new EcsResource(RewardsCallData.createCampaign)
                            .save(data);
            } catch (e) {
                $log.warn('createCampaign () :: Error ', e);
            }
        },

        //Create reward gift codes
        createGiftCodes: function (data) {
            try {

                return new EcsResource(RewardsCallData.createGiftCodes)
                    .save(data);
            } catch (e) {
                $log.warn('createGiftCodes () :: Error ', e);
            }
        },

        validateRewardGiftCode: function (data) {
            try {

                return new EcsResource(RewardsCallData.validateRewardGiftCode)
                    .query({ ':promoCode': data });
            } catch (e) {
                $log.warn('validateRewardGiftCode () :: Error ', e);
            }
        }
    }
}]);;'use strict';

angular
    .module('ecs.service.impl.rewardsAddress', [])
    .service('RewardsAddress', [
        'Objects',
        '$log',
    function (Objects, $log) {
        var getCountries = function (type) {
            try {
                return Objects.getCountries({ type: type })
                    .then(function (response) {
                        return response;
                    });
            }
            catch (e) {
                $log.warn('getCountries() :: Error ', e);
            }
        };

        var getStatesOrRegions = function (country) {
            try {
                return Objects.getStateOrRegions({ country: country })
                      .then(function (response) {
                          return response;
                      });
            }
            catch (e) {
                $log.warn('getStateOrRegions() :: Error ', e);
            }
        };

        var getTaxJuridictions = function (city, postalCode, country) {
            try {
                var hasCity = !!city,
                    hasPostalCode = !!postalCode,
                    isCountryUS = country === 'US';

                if (hasCity && hasPostalCode && isCountryUS) {
                    var params = {};

                    params.city = city;
                    params.postalcode = postalCode;

                    return Objects.getTaxJurisdictions(params)
                       .then(function (response) {
                           return response;
                       });
                }
            }
            catch (e) {
                $log.warn('getTaxJurisdiction() :: Error ', e);
            }

        };

        return {
            getCountries: getCountries,
            getStatesOrRegions: getStatesOrRegions,
            getTaxJurisdictions: getTaxJuridictions
        };
    }]);;angular
    .module('ecs.service.impl.campaigns', [])
    .constant('CampaignAPICallData', {
        campaigns: 'campaigns/',
        campaign: 'campaigns/:campaignid/',
        campaignClones: 'campaigns/:campaignid/clones/',
        campaignRecipients: 'campaigns/:campaignid/recipients/',
        campaignRecipient: 'campaigns/:campaignid/recipients/:recipientid/',
        campaignOwners: 'campaigns/:campaignid/owners/',
        campaignOwner: 'campaigns/:campaignid/owners/:ownerid/',
        //campaignPack: 'campaigns/:campaignid/packs/',
        campaignOwner: 'campaigns/:campaignid/owners/:ownerid/',
        campaignPacks: 'campaigns/:campaignid/packs/',
        campaignPack: 'campaigns/:campaignid/packs/:packid/',
        campaignExtensions: 'campaigns/:campaignid/extensions/',
        campaignActions: 'campaigns/:campaignid/actions/',
        campaignFees: 'campaigns/:campaignid/fees/',
        campaignExceptions: 'campaigns/:campaignid/exceptions/'
    })
.factory('Campaigns', ['CampaignAPICallData', 'EcsResource', '$log', function (CampaignAPICallData, EcsResource, $log) {
    return {
        searchCampaigns : function(skip, top, query) {
            try {
                return new EcsResource(CampaignAPICallData.campaigns)
                    .query({
                        'skip': skip,
                        'top': top,
                        'q': query
                    });
            } catch (e) {
                $log.warn('searchCampaigns () :: Error ', e);
            }
        },

        getCampaign : function(campaignId) {
            try {
                var params = {};

                params[':campaignid'] = campaignId;

                return new EcsResource(CampaignAPICallData.campaign).query(params);
            } catch (e) {
                $log.warn('getCampaign () :: Error ', e);
            }
        },

        cloneCampaign : function(params, clone) {
            try {
                return new EcsResource(CampaignAPICallData.campaignClones)
                    .save({ ':campaignid': params }, clone);
            } catch (e) {
                $log.warn('cloneCampaign () :: Error ', e);
            }
        },

        extendCampaign: function (campaignId, extension) {
            try {
                return new EcsResource(CampaignAPICallData.campaignExtensions)
                    .save({ ':campaignid': campaignId }, extension);
            }
            catch (e) {
                $log.warn('extendCampaign() :: Error ', e);
            }
        },

        createCampaign : function createCampaign(campaign) {
            try {
                return new EcsResource(CampaignAPICallData.campaigns)
                    .save(campaign);
            } catch (e) {
                $log.warn('createCampaign () :: Error ', e);
            }
        },

        updateCampaign: function updateCampaign(campaignId, campaign) {
            try {
                var params = {};
                params[':campaignid'] = campaignId;
                return new EcsResource(CampaignAPICallData.campaign)
                    .update(params, campaign);
            } catch (e) {
                $log.warn('updateCampaign () :: Error ', e);
            }
        },

        searchCampaignRecipients : function searchCampaignRecipients(campaignid, skip, top, query) {
            try {
                return new EcsResource(CampaignAPICallData.campaignRecipients)
                    .query({
                        'skip': skip,
                        'top': top,
                        'q': query,
                        ':campaignid' : campaignid
                    });
            } catch (e) {
                $log.warn('searchCampaignRecipients () :: Error ', e);
            }
        },
        addCampaignRecipient: function addCampaignRecipient(campaignid, recipient) {
            try {
                return new EcsResource(CampaignAPICallData.campaignRecipients)
                    .save({':campaignid': campaignid }, recipient);
            } catch (e) {
                $log.warn('addCampaignRecipient () :: Error ', e);
            }
        },
        updateCampaignRecipient: function updateCampaignRecipient(campaignid, recipientid, recipient) {
            try {
                return new EcsResource(CampaignAPICallData.campaignRecipient)
                    .update({
                        ':campaignid': campaignid,
                        ':recipientid': recipientid
                    }, recipient);
            } catch (e) {
                $log.warn('updateCampaignRecipient () :: Error ', e);
            }
        },
        deleteCampaignRecipient: function deleteCampaignRecipient(campaignid, recipientid) {
            try {
                return new EcsResource(CampaignAPICallData.campaignRecipient)
                    .remove({
                        ':campaignid': campaignid,
                        ':recipientid': recipientid
                    });
            } catch (e) {
                $log.warn('deleteCampaignRecipient () :: Error ', e);
            }
        },
        getCampaignOwners: function (campaignId) {
            try {
                var params = {};

                params[':campaignid'] = campaignId;

                return new EcsResource(CampaignAPICallData.campaignOwners).query(params);
            } catch (e) {
                $log.warn('getCampaignOwners () :: Error ', e);
            }
        },

        addCampaignOwner: function addCampaignOwner(campaignId, owner) {
            try {
                var params = {};
                params[':campaignid'] = campaignId;
                return new EcsResource(CampaignAPICallData.campaignOwners)
                    .save(params, owner);
            } catch (e) {
                $log.warn('addCampaignOwner () :: Error ', e);
            }
        },

        removeCampaignOwner: function removeCampaignOwner(campaignid, ownerid) {
            try {
                var params = {};
                
                return new EcsResource(CampaignAPICallData.campaignOwner)
                    .remove({
                        ':campaignid': campaignid,
                        ':ownerid': ownerid
                    });
            } catch (e) {
                $log.warn('removeCampaignOwner () :: Error ', e);
            }
        },

        //getCampaignPack: function campaignPack(campaignId) {
        //    try {
        //        var params = {};
        //        params[':campaignid'] = campaignId;
        //        return new EcsResource(CampaignAPICallData.campaignPack).query(params);
        //    } catch (e) {
        //        $log.warn('getCampaignPack () :: Error ', e);
        //    }
        //},

        getCampaignPacks: function (campaignId) {
            try {
                var params = {};

                params[':campaignid'] = campaignId;

                return new EcsResource(CampaignAPICallData.campaignPacks).query(params);
            } catch (e) {
                $log.warn('getCampaignPacks () :: Error ', e);
            }
        },

        updateCampaignPack: function (campaignid, packid, pack) {
            try {
                return new EcsResource(CampaignAPICallData.campaignPack)
                    .update({
                        ':campaignid': campaignid,
                        ':packid': packid
                    }, pack);
            } catch (e) {
                $log.warn('updateCampaignPack () :: Error ', e);
            }
        },

        addCampaignPack: function (campaignid, pack) {
            try {
                return new EcsResource(CampaignAPICallData.campaignPacks)
                    .save({
                        ':campaignid': campaignid
                    }, pack);
            } catch (e) {
                $log.warn('addCampaignPack () :: Error ', e);
            }
        },
        
        addCampaignAction: function (campaignid, campaignAction) {
            try {
                return new EcsResource(CampaignAPICallData.campaignActions)
                    .save({ ':campaignid': campaignid }, campaignAction);
            } catch (e) {
                $log.warn('addCampaignAction () :: Error ', e);
            }
        },

        getCampaignFees: function (campaignId) {
            try {
                var params = {};

                params[':campaignid'] = campaignId;

                return new EcsResource(CampaignAPICallData.campaignFees).query(params);
            } catch (e) {
                $log.warn('getCampaignFees () :: Error ', e);
            }
        },

        addCampaignException: function addCampaignException(campaignid, campaignException) {
            try {
                return new EcsResource(CampaignAPICallData.campaignExceptions)
                    .save({ ':campaignid': campaignid }, campaignException);
            } catch (e) {
                $log.warn('addCampaignException () :: Error ', e);
            }
        }
    }
}]);;angular
    .module('ecs.services.impl.giftCertificates', [])
    .constant('GiftCertificatesCallData', {
        createGiftCertificateOrder: 'giftcertificates/',
        getGiftCertificate: 'giftcertificates/:giftCertificateId/',
        updateGiftCertificateEmail: 'giftcertificates/:giftCertificateId/recipient/',
        getGiftCertificatePaymentMethodDetails: 'giftcertificates/paymentmethod/:payerCustomerId/:paymentMethodCode/'
    })
    .factory('GiftCertificates', ['GiftCertificatesCallData', 'EcsResource', '$log', function (GiftCertificatesCallData, EcsResource, $log) {
        return {
            createGiftCertificateOrder: function (model, message) {
                try {
                    return new EcsResource(GiftCertificatesCallData.createGiftCertificateOrder)
                        .save(model, undefined, { 'message': message });

                } catch (e) {
                    $log.warn('createGiftCertificateOrder() :: Error', e);
                }
            },

            getGiftCertificate: function (giftCertificateId) {
                try {
                    return new EcsResource(GiftCertificatesCallData.getGiftCertificate)
                        .query({ ':giftCertificateId': giftCertificateId });

                } catch (e) {
                    $log.warn('getGiftCertificateOrderDetails() :: Error', e);
                }
            },

            updateGiftCertificateEmail: function (giftCertificateId, model) {
                try {
                    model[':giftCertificateId'] = giftCertificateId;

                    return new EcsResource(GiftCertificatesCallData.updateGiftCertificateEmail)
                        .update(model);
                } catch (e) {
                    $log.warn('updateGiftCertificateEmail() :: Error', e);
                }
            },

            getGiftCertificatePaymentMethodDetails: function (payerCustomerId, paymentMethodCode) {
                try {
                    return new EcsResource(GiftCertificatesCallData.getGiftCertificatePaymentMethodDetails)
                        .query({ ':payerCustomerId': payerCustomerId, ':paymentMethodCode': paymentMethodCode });

                } catch (e) {
                    $log.warn('getGiftCertificatePaymentMethodDetails() :: Error', e);
                }
            },


        }
    }]);angular
    .module('ecs.service.impl.petVetService', [])
    .constant('PetVetCallData', {

        searchClinics: 'petvet/petvet/searchclinic/',
        getActiveLookups: 'petvet/petvet/activelookups/',
        addCustomFields: 'petvet/petvet/customfield/',
        getCustomFieldByOrder: 'petvet/petvet/customfield/orders/:orderId/',
        getCustomFieldByCart: 'petvet/petvet/customfield/cart/:cartid/'
        
    })
    .factory('PetVetService', ['PetVetCallData', 'EcsResource', '$log', function (PetVetCallData, EcsResource, $log) {

        var pvData = {};
        var fetchPVData; //method to fetch PVData
        var onSetData; //method executed when data is set.

        toTitleCase = function (str) {
            str = str.toLowerCase();
            return str.replace(/[^\s]+/g, function (word) {
                return word.replace(/^./, function (first) {
                    return first.toUpperCase();
                });
            });
        };

        return {

            getPVData: function () {
                if (fetchPVData != null) {
                    fetchPVData();
                }

                return pvData;
            },

            setPVDataCallback: function (callbackFunction) {
                onSetData = callbackFunction;
            },

            setPVData: function (data) {
                pvData = data;
                if (onSetData != null) {
                    onSetData();
                }
            },

            setPVFetchFunction: function (fetchFunction) {
                fetchPVData = fetchFunction;
            },

            hasCompleteData: function () {
                if (fetchPVData != null) {
                    fetchPVData();
                }

                if (pvData != null) {
                    return pvData.selectedActivity != null && pvData.selectedActivity.Obj.Id != null
                        && pvData.selectedObjective != null && pvData.selectedObjective.Obj.Id != null
                        && pvData.selectedMeasurement != null && pvData.selectedMeasurement.Obj.Id != null
                        && pvData.selectedDistrict != null && pvData.selectedDistrict.Obj.Id != null
                        && pvData.selectedClinic != null && pvData.selectedClinic.Id != null
                        && pvData.programStartDate != null
                        && pvData.programEndDate != null;
                }
                return false;
            },

            getCustomField: function () {
                return {
                    Id: 0,
                    ObjectiveId: pvData.selectedObjective.Obj.Id,
                    ClinicId: pvData.selectedClinic.Id,
                    ActivityId: pvData.selectedActivity.Obj.Id,
                    MeasurementId: pvData.selectedMeasurement.Obj.Id,
                    DistrictId: pvData.selectedDistrict.Obj.Id,
                    ProgramStart: pvData.programStartDate,
                    ProgramEnd: pvData.programEndDate
                };
            },

            //Converts state name and clinic site name to title case.

            setClinicDisplayValues: function (clinic) {
                clinic.City = toTitleCase(clinic.City);
                clinic.SiteName = toTitleCase(clinic.SiteName);
                return clinic;
            },

            // Search Clinics

            searchClinics: function (params) {

                try {

                    return new EcsResource(PetVetCallData.searchClinics)
                        .query(params);


                } catch (e) {

                    $log.warn('searchClinics () :: Error ', e);

                }

            },


            // Get list of active lookups

            getActiveLookups: function (params) {

                try {

                    return new EcsResource(PetVetCallData.getActiveLookups)
                        .query(params);


                } catch (e) {

                    $log.warn('getActiveLookups () :: Error ', e);

                }

            },

            // Add a custom field model.

            addCustomFields: function (model) {

                try {

                    return new EcsResource(PetVetCallData.addCustomFields)
                        .save(model);



                } catch (e) {

                    $log.warn('addCustomFields () :: Error ', e);

                }

            },



            getCustomFieldByOrder: function (params) {

                try {

                    return new EcsResource(PetVetCallData.getCustomFieldByOrder)
                        .query(params);


                } catch (e) {

                    $log.warn('getCustomFieldByOrder () :: Error ', e);

                }

            },

            getCustomFieldByCart: function (params) {

                try {

                    return new EcsResource(PetVetCallData.getCustomFieldByCart)
                        .query(params);


                } catch (e) {

                    $log.warn('getCustomFieldByCart () :: Error ', e);

                }

            }


        }


    }]);;angular
    .module('ecs.ctrl.chili',[])
    .controller('chiliDocumentCtrl', [
        '$scope',
        'ChiliService',
        function ($scope, ChiliService) {
            $scope.error = "";
            $scope.getRenderPDF = function (guid, callback) {
                ChiliService.getRenderPDF(guid, true, callback);
            }

            isUUID = function (uuid) {
                let s = "" + uuid;

                s = s.match('^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$');
                if (s === null) {
                    return false;
                }
                return true;
            },

            onResponse = function (status) {
                if (status == null)
                    return;

                $scope.error = status;
            },

            $scope.init = function (DocumentId) {
                var isGUID = isUUID(DocumentId);
                if (isGUID) {
                    $scope.getRenderPDF(DocumentId, onResponse);
                }
                else {
                    $scope.error = "404";
                }
            };
        }]);;angular
    .module('ecs.ctrl.product.detail', [])
    .controller('productDetailCtrl', [
        '$window',
        '$log',
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'Customers',
        'Products',
        '$timeout',
        'Common',
        '$uibModal',
        '$rootScope',
        '$sce',
        'ProductUrlService',
        'AddressService',
        'ProductUIService',
        '$q',
        function ($window, $log, $scope, $location, EcsResource, CartService, Customers, Products, $timeout, Common, $uibModal, $rootScope, $sce, ProductUrlService, AddressService, ProductUIService, $q) {

            const availability = {
                AVAILABLE: "Available",
                UNAVAILABLE: "Unavailable",
                ONORDER: "On Order",
                DISCONTINUED: "Discontinued",
                PREORDER: "Pre-Order",
            }

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.

            //this array is used to hold sort options for all child options. By specifying
            //the name of the option and how to sort the values within the function it will
            //be used to arrange the information for you.
            var childOptionSort = [];
            var imageZoomOptions = {};

            childOptionSort['color'] = function (arr) {
                return arr.sort(function (a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };
            childOptionSort['media'] = function (arr) {
                return arr.sort(function (a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };

            var getProductMainImageUrl = function (product) {
                var image;

                if (product.mainImage) //protect against no image available
                    image = ProductUrlService.getImageUrl(product.mainImage.FileName, product.mainImage.Extension, 'tt');
                else {
                    image = ProductUrlService.getNoImageUrl('tt');
                }

                return image;
            },

                getCurrentProduct = function () {
                    return ECSStores.CurrentProduct;

                },

                getPointsConfig = function () {
                    return ECSStores.PointsConfig || {};
                },

                //Bread crumbs now done via URL
                //setBreadCrumb = function () {
                //    var p = window.location.href.split("/"),
                //        catalogSlugArray = p[p.length - 1].split("-"),
                //        catalogHeading = p[p.length - 1].replace(/[0-9]/g, "").replace(/-/g, " ").trim(),
                //        breadcrumb = { heading: catalogHeading, last: Common.getPreviousLocationLabel() };

                //    $scope.breadcrumb = breadcrumb;

                //},

                getRelatedProducts = function () {

                    return ECSStores.RelatedProducts;
                },

                getProductSlug = function () {

                    var splitUrl = $location.absUrl().split(/\//).filter(function (e) { return e.trim().length > 0; }),
                        len = splitUrl.length,
                        id = splitUrl[len - 1];

                    if (id.slice(-1) === '#')
                        id = id.slice(0, -1);

                    return id;
                },

                loadProduct = function () {
                    var currentProduct = getCurrentProduct();

                    //check to see if we have current product data, and if that product data
                    //is still valid. Anything over 20 seconds old is cached on the page.
                    if (currentProduct) {
                        $log.log('Product loaded from page cache');

                        setUpProductData(currentProduct);
                    } else {
                        $log.log('Product fetch from API');

                        fetchProduct(getProductSlug());
                    }
                },

                fetchProduct = function (productSlug) {

                    Products.getProduct({ ':sku': productSlug })
                        .then(function (response) {
                            setUpProductData(response.data);
                        });

                },

                getSavingsAmount = function (originalPrice, price, baseCurrency, currencyExchangeRates) {
                    var locale = $scope.locale,
                        cOriginalPrice = Number(locale.exchangeRate(originalPrice, baseCurrency, currencyExchangeRates)),
                        cPrice = Number(locale.exchangeRate(price, baseCurrency, currencyExchangeRates));

                    return locale.formatCurrency(cOriginalPrice - cPrice, baseCurrency, currencyExchangeRates);
                },

                loadRelatedProducts = function (product) {

                    Products.getRelatedProducts({ ':sku': product.ProductSlug })
                        .then(function (response) {
                            setUpRelatedProductData(response.data);
                        });
                },

                setUpProductData = function (product) {
                    var pointsConfig = getPointsConfig();
                    $scope.availability = availability;
                    $scope.isPointsValueNull = pointsConfig != null && pointsConfig.PointsValue && product.PointsValue == null;
                    var qtyAvailable = product.QtyAvailable,
                        //Show the Notify Me option if there is no quantity, the item is not discontinued, and it is a product that can't be backordered
                        showNotify = Number(qtyAvailable) <= 0 && !product.Discontinued && !product.AllowBackOrder && !product.IsPreOrder,

                        //Show Add to Cart if Allow Back Order is true or if the qty available is > 0
                        showAddToCart = (product.AllowBackOrder || Number(qtyAvailable) > 0 || product.IsPreOrder),

                        //Set the avail flag. 1 = Unavailable, 2 = On Order, 3 = Discontinued
                        availFlag = $scope.isPointsValueNull ? availability.DISCONTINUED : Number(qtyAvailable) <= 0 ? (!product.Discontinued ? (showNotify ? availability.UNAVAILABLE : availability.ONORDER) : availability.DISCONTINUED) : availability.AVAILABLE,

                        hasImages = product.Images.length > 0,
                        hasOptions = product.ChildProductOptions && product.ChildProductOptions.length > 0,
                        relatedProducts = getRelatedProducts(),
                        showMinQntyLmt = (product.MinimumQuantityLimit != undefined);

                    if (product.IsPreOrder)
                        availFlag = availability.PREORDER;

                    if (relatedProducts) {
                        setUpRelatedProductData(relatedProducts);
                    } else {
                        loadRelatedProducts(product);
                    };

                    var isApparel = false;
                    if (hasOptions) {
                        angular.forEach(product.ChildProductOptions, function (productOption, i) {
                            //check if we have a sort for this type of data...
                            var sortFunc = childOptionSort[productOption.Option.toLowerCase()];
                            if (sortFunc !== undefined) {
                                productOption.Values = sortFunc(productOption.Values);
                            }
                            //check if this is the current product we are viewing.
                            angular.forEach(productOption.Values, function (option, i) {
                                if (option.IsThisProduct) {
                                    productOption.selectedOption = option.ProductSlug;
                                    option.selectedIndex = i;
                                }

                                if (option.Option.toLowerCase() === 'media') {
                                    $scope.isMedia = true;
                                } else {
                                    $scope.isMedia = false;
                                }

                                if (option.Option.toLowerCase() === 'size') {
                                    isApparel = true;
                                }

                            });
                            if (!productOption.selectedOption) {
                                productOption.selectedOption = productOption.Values[i].ProductSlug
                            }
                        });
                    }


                    $scope.currentProduct = product;
                    $scope.currentProduct.availFlag = availFlag;
                    switch (availFlag) {
                        case availability.UNAVAILABLE, availability.DISCONTINUED:
                            $scope.currentProduct.availability = 'Unavailable';
                            break;
                        case availability.ONORDER:
                            $scope.currentProduct.availability = 'On Order';
                            break;
                        case availability.PREORDER:
                            $scope.currentProduct.availability = 'Pre-Order';
                            break;
                        default:
                            $scope.currentProduct.availability = (product.ShowAvailableQty) ? qtyAvailable : (Number(qtyAvailable) <= 10) ? 'Only ' + qtyAvailable + ' left in stock' : 'In stock';
                    }
                    $scope.currentProduct.showNotify = showNotify;
                    $scope.currentProduct.showAddToCart = availFlag !== availability.DISCONTINUED && showAddToCart;
                    $scope.currentProduct.hasImages = hasImages;
                    $scope.currentProduct.desiredQty = 1; //Math.min(product.QtyAvailable, 1);
                    $scope.currentProduct.showMinQntyLmt = showMinQntyLmt;
                    $scope.currentProduct.minQntyLmt = showMinQntyLmt ? product.MinimumQuantityLimit.PurchaseLimit : 1;
                    $scope.currentProduct.isTemplate = showMinQntyLmt ? product.MinimumQuantityLimit.IsTemplate : false;
                    $scope.currentProduct.displaySKU = product.PurchaseProductNumber !== null ? product.PurchaseProductNumber : product.ProductNumber;

                    if (!!product.TemplateProductNumber)
                        $scope.currentProduct.displaySKU = product.TemplateProductNumber;

                    var productTextArray = $scope.currentProduct.Text;
                    for (var i = 0, len = productTextArray.length; i < len; i += 1) {
                        productTextArray[i].htmlText = $sce.trustAsHtml(productTextArray[i].Text);
                    }

                    $scope.currentProduct.personalizationLites = product.PersonalizationLites;
                    $scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo(product);
                    $scope.currentProduct.personalizationLiteInfoInstructions = [];
                    angular.forEach(product.personalizationLites, function (litesInfo) {
                        litesInfo.CharacterLimit = litesInfo.CharacterLimit <= 0 ? "" : litesInfo.CharacterLimit;
                        litesInfo.isFieldTypeDropdown = litesInfo.FieldType == 'Dropdown';
                        litesInfo.isFieldTypeValidatedText = litesInfo.FieldType == 'Text with validation';
                    });

                    $scope.currentProduct.isPersonalized = false;
                    $scope.currentProduct.PersonalizedInfo = null;
                    angular.forEach(product.Attributes, function (attribute, i) {

                        if (attribute.Type && attribute.Type.toLowerCase() === 'productpersonlization') {
                            $scope.currentProduct.isPersonalized = true;
                            $scope.currentProduct.PersonalizedInfo = {};
                            $scope.currentProduct.personalizationConfig = JSON.parse(attribute.Value);
                        }

                    });

                    $scope.newProductSlug = {};

                    setUpImages();
                    checkForShowAllOptions();
                },

                checkForShowAllOptions = function () {
                    var showAllProductOptions = ECSStores.ShowAllProductOptions,
                        optionsArray = $scope.currentProduct.ChildProductOptions;

                    if (showAllProductOptions) {

                        if (optionsArray) {

                            for (var i = 0, len = optionsArray.length; i < len; i += 1) {
                                if (optionsArray[i].CanShowAvailability) {
                                    showChildProductTable(undefined, i);
                                }
                            }
                        } else {
                            showAllProductOptions = false;
                        }

                        $scope.showAllProductOptions = showAllProductOptions;

                    }

                },

                setUpRelatedProductData = function (relatedProducts) {

                    $scope.relatedProducts = relatedProducts;
                },

                swapImage = function ($event, index) {
                    if ($event) {
                        $event.preventDefault();
                    }
                    $scope.currentProduct.mainImage = $scope.currentProduct.Images[index];
                    $log.log('ProductDetailCtrl > swapImage(i) ::', index);
                },

                /**
                    When the product page starts, display the first image in 
                    the big container and then iterate over the array displaying
                    the remainign images in the row below. 
        
                    when the user clicks on an image, display that image in the big area.
        
                    Extension: ".jpg"
                    FileName: "MIC/MIC30022100"
                    ImageGuid: "bdb52f65-33f7-4b4b-a9d8-83288fc27701"
                    IsDefault: true
                    ProductNumber: "MIC30022100"
                */
                setUpImages = function () {

                    $scope.currentProduct.mainImage = $scope.currentProduct.Images[0];

                },

                personalizationLiteValues = function (product) {
                    var personalizationLiteAttributes = [];
                    angular.forEach(product.personalizationLites, function (lites, i) {
                        for (var liteInfoKeys in product.personalizationLiteInfo) {
                            if (liteInfoKeys == lites.AttributeName && (!!product.personalizationLiteInfo[liteInfoKeys] || product.personalizationLiteInfo[liteInfoKeys] !== '')) {
                                personalizationLiteAttributes.push({
                                    PersonalizationLiteAttributeId: lites.Id,
                                    Value: product.personalizationLiteInfo[liteInfoKeys]
                                })
                            }
                        }

                    });

                    if (product.IsPersonalizationLite && !!product.personalizationLites && product.personalizationLites.length > 0 && !!personalizationLiteAttributes && personalizationLiteAttributes.length > 0) {
                        return [{
                            ProductNumber: product.ProductNumber,
                            Quantity: product.desiredQty || 1,
                            PersonalizationLiteAttributes: personalizationLiteAttributes,
                        }]
                    } else {
                        return null;
                    }

                },

                convertProductToCartItem = function (product) {
                    var toReturn = {
                        Name: product.Name,
                        ProductSlug: product.ProductSlug,
                        ProductNumber: product.ProductNumber,
                        Image: getProductMainImageUrl(product),
                        Qty: product.desiredQty || 1,
                        Price: product.Price,
                        DisplayPrice: product.DisplayPrice,
                        Url: ProductUrlService.getUrl(product.ProductSlug),
                        PurchaseProductNumber: product.PurchaseProductNumber,
                        IsDownload: product.IsDownload,
                        IsOnBackorder: product.desiredQty > product.QtyAvailable && product.AllowBackOrder && !product.IsDownload,
                        PersonalizedInfo: product.PersonalizedInfo,
                        ThirdPartyPersonalizations: product.ThirdPartyPersonalizations,
                        CartItemPersonalizationLites: !!product.PersonalizationLite && product.PersonalizationLite.length > 0 ? product.PersonalizationLite : personalizationLiteValues(product),
                        IsPreOrder: product.IsPreOrder,
                        BOGOProductNumber: $scope.bogoOptionSelected,
                        ExpectedLeadTime: $scope.currentProduct.ExpectedLeadTime
                    }
                    return toReturn
                },

                updateToSelectedProduct = function (slug, prev, catprev) {
                    var productPathBuilder = ['product'];
                    if (catprev !== undefined && catprev !== null && catprev !== 'null' && catprev != '')
                        productPathBuilder.push(catprev);
                    if (prev !== undefined && prev !== null && prev !== 'null' && prev != '')
                        productPathBuilder.push(prev);
                    productPathBuilder.push(slug);
                    $location.path('/' + productPathBuilder.join('/'));
                    //$location.path('/product/' + slug);
                },

                resetAddToCart = function () {
                    $scope.addToCartSubmitted = false;
                },

                validatePersonalizedInfo = function (product) {

                    if (product.personalizationConfig.Name && (!product.PersonalizedInfo.Name || product.PersonalizedInfo.Name === ''))
                        return false;
                    if (product.personalizationConfig.Phone && (!product.PersonalizedInfo.Phone || product.PersonalizedInfo.Phone === ''))
                        return false;
                    if (product.personalizationConfig.Email && (!product.PersonalizedInfo.Email || product.PersonalizedInfo.Email === ''))
                        return false;

                    return true;
                },

                validatePersonalizationLite = function (product) {
                    var toReturn = true;
                    angular.forEach(product.personalizationLites, function (litesInfo) {
                        if (!!product.personalizationLiteInfo && litesInfo.Required && (!product.personalizationLiteInfo[litesInfo.AttributeName] || product.personalizationLiteInfo[litesInfo.AttributeName] === '')) {
                            toReturn = false;
                        }
                    });

                    return toReturn;
                },

                validatePersonalizationLiteOptions = function (product) {
                    toReturn = true;
                    angular.forEach(product.personalizationLites, function (litesInfo) {
                        litesInfo.invalidOption = false;
                        if (litesInfo.FieldType == "Text with validation" && !litesInfo.Options.some(o => o.Value.toUpperCase() == product.personalizationLiteInfo[litesInfo.AttributeName].toUpperCase())) {
                            litesInfo.invalidOption = true;
                            toReturn = false;
                        }
                    });
                    return toReturn;
                },

                getDefaultPersonalizationLiteInfo = function (product) {
                    var personalizationLiteInfo;
                    if (product.IsPersonalizationLite && !!product.personalizationLites && product.personalizationLites.length > 0) {
                        angular.forEach(product.personalizationLites, function (litesInfo) {
                            personalizationLiteInfo = {
                                ...personalizationLiteInfo,
                                [litesInfo.AttributeName]: ""
                            };

                        });
                    } else {
                        personalizationLiteInfo = null;
                    }

                    return personalizationLiteInfo;
                },

                addToCart = function (product) {

                    var desiredQty = Number(product.desiredQty),
                        self = this;

                    $scope.addedToCart = true;
                    $scope.addToCartSubmitted = true;
                    $scope.currentProduct.invalidOptions = [];

                    if (!desiredQty || desiredQty === 0) {
                        Common.showMessage('danger', '610');
                        resetAddToCart();
                    }
                    else if (product.isPersonalized && !validatePersonalizedInfo(product)) {
                        Common.showMessage('danger', '629');
                        resetAddToCart();
                    }
                    else if (product.IsPersonalizationLite && !!product.personalizationLites && product.personalizationLites.length > 0 && !validatePersonalizationLite(product)) {
                        Common.showMessage('danger', '629');
                        resetAddToCart();
                    }
                    else if (!product.IsPersonalizable && !!product.personalizationLites && product.personalizationLites.length > 0 && !validatePersonalizationLiteOptions(product)) {
                        Common.showMessage('danger', '629');
                        resetAddToCart();
                    }

                    else if (product.showMinQntyLmt && !product.isTemplate && product.minQntyLmt > product.desiredQty) {
                        Common.showMessage('danger', '448');
                        resetAddToCart();
                    }
                    else {
                        if (!product.IsPreOrder && product.AllowBackOrder === false && Number(product.desiredQty) > Number(product.QtyAvailable)) {
                            //They can't order more than what's available if AllowBackOrder is false
                            Common.showMessage('danger', '605');
                            product.desiredQty = product.QtyAvailable;
                            resetAddToCart();
                        }
                        else if (product.AvailableRegions && product.AvailableRegions.length > 0 && !product.selectedRegion) {
                            $scope.selectedRegionRequiredError = true;
                            resetAddToCart();
                        }
                        else {
                            if (product.BOGOWithOptionsProductSlug && product.BOGOWithOptionsProductSlug !== '' && !$scope.bogoOptionSelected && !CartService.isItemInCart(product.ProductNumber)) {
                                showBOGOSelect(addToCart, product);
                            }
                            else {
                                CartService.addCartItem(convertProductToCartItem(product))
                                    .then(function (res) {
                                        $scope.currentProduct.personalizationLiteInfo = {};
                                        resetAddToCart();
                                    }, function (res) {
                                        /*  mic28, mic29, mic30
                                            415 416, 417 or 418... when adding an item to the cart from product detail.
                                            set desired qty back to 1
                                        */
                                        if (res && res.config && res.config.data && res.config.data.ProductNumber) {

                                            var product = res.config.data.ProductNumber,
                                                productArray = ["mic28", "mic29", "mic30"];

                                            if ($.inArray(product.substr(0, 5).toLowerCase(), productArray) !== -1) {
                                                if (res && res.data) {
                                                    var softwareProductRelatedErrors = ["415", "416", "417", "418"],
                                                        errorCode = res.data.errorCode;

                                                    if ($.inArray(errorCode, softwareProductRelatedErrors) !== -1) {
                                                        $scope.currentProduct.desiredQty = 1;
                                                    }

                                                }
                                            }

                                        }

                                        $scope.currentProduct.personalizationLiteInfo = {};
                                        resetAddToCart();
                                    });
                            }
                        }
                    }
                },

                addChildProductsToCart = function () {
                    var productsToAdd = [];
                    var errorToShow = '';

                    angular.forEach($scope.childProducts, function (childProduct, i) {

                        if (childProduct.desiredQty && Number(childProduct.desiredQty) > 0) {

                            if (childProduct.IsDiscontinued && Number(childProduct.desiredQty) > Number(childProduct.QtyAvailable)) {
                                errorToShow = '607';
                                childProduct.desiredQty = childProduct.QtyAvailable;
                                childProduct.hasError = true;
                                return;
                            }

                            let currentProduct = $scope.currentProduct;
                            currentProduct.ProductNumber = childProduct.ProductNumber;
                            currentProduct.desiredQty = childProduct.desiredQty;

                            if (currentProduct.isPersonalized && !validatePersonalizedInfo(currentProduct)) {
                                errorToShow = '629';
                                childProduct.hasError = true;
                                return;
                            }
                            else if (currentProduct.IsPersonalizationLite && !!currentProduct.personalizationLites && currentProduct.personalizationLites.length > 0 && !validatePersonalizationLite(currentProduct)) {
                                errorToShow = '629';
                                childProduct.hasError = true;
                                return;
                            }
                            else if (!currentProduct.IsPersonalizable && !!currentProduct.personalizationLites && currentProduct.personalizationLites.length > 0 && !validatePersonalizationLiteOptions(currentProduct)) {
                                errorToShow = '629';
                                childProduct.hasError = true;
                                return;
                            }

                            childProduct.PersonalizationLite = personalizationLiteValues(currentProduct);
                            productsToAdd.push(convertProductToCartItem(childProduct));
                        }
                    });

                    if (errorToShow !== '') {
                        Common.showMessage('danger', errorToShow);
                        resetAddToCart();
                    }
                    else if (productsToAdd.length === 0) {
                        Common.showMessage('danger', '608');
                        resetAddToCart();
                    }
                    else {
                        if ($scope.currentProduct.BOGOWithOptionsProductSlug && $scope.currentProduct.BOGOWithOptionsProductSlug !== '' && !$scope.bogoOptionSelected && !CartService.isAnyItemInCart(productsToAdd)) {
                            showBOGOSelect(addChildProductsToCart, $scope.currentProduct);
                        }
                        else {
                            CartService.addMultipleCartItems(productsToAdd, { parent: convertProductToCartItem($scope.currentProduct) })
                                .finally(function () {
                                    $scope.currentProduct.personalizationLiteInfo = {};
                                    resetAddToCart();
                                });
                        }
                    }
                },

                showBOGOSelect = function (callback, product) {
                    var modalInstance = $uibModal.open({
                        templateUrl: 'BOGOProductOptionSelect.html',
                        controller: 'bogoOptionSelectModalCtrl',
                        size: 'lg',
                        backdrop: 'static',
                        resolve: {
                            currentProduct: function () {
                                return product;
                            },
                            appConfig: function () {
                                return $scope.$appConfig;
                            }
                        }
                    });

                    modalInstance.result.then(function (bogoProduct) {
                        $scope.bogoOptionSelected = bogoProduct.ProductNumber;
                        callback($scope.currentProduct);
                    }, function () {
                        Common.showMessage('danger', '639');
                        resetAddToCart();
                    });


                },

                showSendToFriend = function () {
                    //$scope.$emit('showSendToFriendModal', $scope.currentProduct);
                    var modalInstance = $uibModal.open({
                        templateUrl: 'SendToFriendModalContent',
                        controller: 'SendToFriendModalCtrl',
                        resolve: {
                            currentProduct: function () {
                                return $scope.currentProduct;
                            }
                        }
                    });

                    modalInstance.result.then(
                        function (data) {
                            Products.shareProduct($scope.currentProduct.ProductSlug, 'Email', data)
                                .then(function (response) {
                                    var product = $scope.currentProduct;
                                    Common.showMessageNew('share', 'SendToFriend', '604', null, {
                                        product: {
                                            name: product.Name,
                                            productSlug: product.ProductSlug,
                                            productNumber: product.ProductNumber,
                                            image: getProductMainImageUrl(product),
                                            qty: product.Qty,
                                            price: product.Price,
                                            displayPrice: product.DisplayPrice,
                                            url: ProductUrlService.getUrl(product.ProductSlug)
                                        },
                                        friend: {
                                            name: data.SendTo,
                                            email: data.SendToEmail
                                        },
                                        customer: {
                                            name: data.SharedBy,
                                            email: data.SharedByEmail
                                        }
                                    });


                                });

                        });

                },

                showInStockInfo = function ($event, child) {
                    if ($event) {
                        $event.preventDefault();
                    }

                    //$scope.$emit('showSendToFriendModal', $scope.currentProduct);
                    var modalInstance = $uibModal.open({
                        templateUrl: 'ProductInStockInfoModalContent',
                        controller: 'productInStockModalCtrl',
                        resolve: {
                            currentProduct: function () {
                                return $scope.currentProduct;
                            },
                            childProduct: function () {
                                if (child)
                                    return child;
                                else
                                    return null;
                            }
                        }
                    });

                    modalInstance.result.then(
                        function (data) {
                            if (child)
                                notifyMe($event, child, $scope.currentProduct.Name);
                            else
                                notifyMe($event, $scope.currentProduct);
                        });

                },

                showChildProductTable = function ($event, index) {
                    if ($event) {
                        $event.preventDefault();
                    }


                    //If we've already loaded them, just show it
                    if ($scope.childProducts && $scope.childProducts.length > 0) {

                        $scope.childProductTableVisible = !$scope.isPointsValueNull;
                        //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                        $scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                    } else {
                        //Load the Child Options
                        showLoadingChildProducts(true);

                        //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                        $scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                        var optionToShow = $scope.currentProduct.ChildProductOptions[index];
                        Products.getChildProducts(optionToShow.ParentProductSlug)
                            .then(function (response) {
                                if (response.data.length > 0) {
                                    //check if we have a sort for this type of data...
                                    var sortFunc = childOptionSort[optionToShow.Option.toLowerCase()];
                                    if (sortFunc === undefined) {
                                        $scope.childProducts = response.data;
                                    } else {
                                        $scope.childProducts = sortFunc(response.data);
                                    }

                                    $scope.childProductOptionShown = optionToShow.Option;
                                    $scope.childProductTableVisible = !$scope.isPointsValueNull;
                                }
                                else {
                                    $scope.childProductTableVisible = false;
                                    Common.showMessage('danger', '606', { replace: '%product%', value: optionToShow.Option });
                                }

                                showLoadingChildProducts(false);
                            },
                                function () {
                                    showLoadingChildProducts(false);
                                });
                    }
                },

                showLoadingChildProducts = function (bool) {
                    $scope.loadingChildProducts = bool;
                },

                loadBulkOrderOptions = function ($event) {
                    //Common.showMessage('success', 'Loading Bulk Order Options...Please wait');

                    getCustomer();

                    if (!!$scope.currentProduct) {
                        $scope.boQuantity = 1;
                        $scope.boContactMethod = "Email";
                        $scope.boHasTemplate = false;
                        $scope.boTemplateThumbnailUrl = "http://store.ecompanystore.com/ECS_ProductImages/" + $scope.currentProduct.mainImage.FileName.substring(0, 3) + "/templates/" + $scope.currentProduct.ProductNumber + "_template.jpg";
                        //$scope.boTemplateThumbnailUrl = "http://store.ecompanystore.com/ECS_PRODUCTIMAGES/IRM/IRM19000100.jpg";
                        $scope.boTemplateLinkUrl = "http://store.ecompanystore.com/ECS_ProductImages/" + $scope.currentProduct.mainImage.FileName.substring(0, 3) + "/templates/" + $scope.currentProduct.ProductNumber + "_template.pdf";

                        isImage($scope.boTemplateThumbnailUrl);
                        //$scope.boHasTemplate = isImage($scope.boTemplateThumbnailUrl);

                        if ($scope.currentProduct.ChildProductOptions == undefined) {
                            $scope.showAttributeTable = false;
                            $scope.showQuantitySelection = true;
                            return;
                        }

                        var optionsArray = $scope.currentProduct.ChildProductOptions;
                        $scope.boProducts = [];

                        for (var i = 0, len = optionsArray.length; i < len; i += 1) {
                            if (optionsArray[i].CanShowAvailability) {
                                Products.getChildProducts(optionsArray[i].ParentProductSlug)
                                    .then(function (response) {
                                        if (response.data.length > 0) {
                                            //check if we have a sort for this type of data...
                                            var sortFunc = childOptionSort[optionsArray[i].Option.toLowerCase()];
                                            if (sortFunc === undefined) {
                                                $scope.boProducts = response.data;
                                            } else {
                                                $scope.boProducts = sortFunc(response.data);
                                            }

                                            $scope.boProductOptionShown = optionsArray[i].Option;
                                            $scope.showAttributeTable = true;
                                            $scope.showQuantitySelection = true;
                                        }
                                        else {
                                            $scope.showAttributeTable = false;
                                        }
                                    });

                                return;
                            }
                        }
                    }
                    else {
                        $log.log('Product not loaded yet, wait 2 seconds');
                        $timeout(function () {
                            loadBulkOrderOptions($event);
                        }, 2000);
                    }

                },

                validateEmail = function (email) {
                    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
                    return re.test(email);
                },

                validateUrl = function (url) {
                    $.ajax({
                        url: url,
                        type: 'HEAD',
                        error: function () {
                            $scope.boHasTemplate = false;
                        },
                        success: function () {
                            $scope.boHasTemplate = true;
                        }
                    });
                    //$.get(url)
                    //    .done(function () {
                    //        return true;
                    //    }).fail(function () {
                    //        return false;
                    //    })

                },

                isImage = function (url) {

                    var deferred = $q.defer();

                    var image = new Image();
                    image.onerror = function () {
                        $scope.boHasTemplate = false;
                    };
                    image.onload = function () {
                        $scope.boHasTemplate = true;
                    };
                    image.src = url;
                },

                bulkOrderRequestFormIsValid = function () {
                    var isValid = true;

                    // reset validation errors
                    $('#FullName').css('border-color', '#cccccc');
                    $('#Email').css('border-color', '#cccccc');
                    $('#Phone').css('border-color', '#cccccc');
                    $('#EventDate').css('border-color', '#cccccc');
                    $('#StreetAddress').css('border-color', '#cccccc');
                    $('#City').css('border-color', '#cccccc');
                    $('#State').css('border-color', '#cccccc');
                    $('#Country').css('border-color', '#cccccc');
                    $('#ZipCode').css('border-color', '#cccccc');
                    $('#boQuantitySelection').css('border', 'solid 1px #fff');
                    $('#boQuantitySelections').css('border', 'solid 1px #fff');
                    $('#RequestBytDate').css('border-color', '#cccccc');

                    if ($('#FullName').val() == '') {
                        isValid = false;
                        $('#FullName').css('border-color', 'red');
                    }

                    if ($('#Email').val() == '') {
                        isValid = false;
                        $('#Email').css('border-color', 'red');
                    }

                    if (!validateEmail($('#Email').val())) {
                        isValid = false;
                        $('#Email').css('border-color', 'red');
                    }

                    if ($('#Phone').val() == '') {
                        isValid = false;
                        $('#Phone').css('border-color', 'red');
                    }

                    if ($('#EventDate').val() == '') {
                        isValid = false;
                        $('#EventDate').css('border-color', 'red');
                    }

                    if ($('#RequestBytDate').val() == '') {
                        isValid = false;
                        $('#RequestBytDate').css('border-color', 'red');
                    }

                    var qtySelected = false;
                    var invalideInput = true;
                    if ($scope.boProducts != undefined && $scope.boProducts.length > 0) {// dynamic custom attributes
                        for (var i = 0; i < $scope.boProducts.length; i++) {
                            if ($scope.boProducts[i].desiredQty != undefined
                                && $scope.boProducts[i].desiredQty != 0) {
                                if ($scope.boProducts[i].desiredQty != '' && isNaN($scope.boProducts[i].desiredQty))
                                    invalideInput = false;
                                else
                                    qtySelected = true;
                            }
                        }

                        if (!qtySelected || !invalideInput) {
                            isValid = false;
                            $('#boQuantitySelections').css('border', 'solid 1px red');
                        }
                    } else {// no custom attributes
                        if ($scope.boQuantity == '' || $scope.boQuantity <= 0) {
                            isValid = false;
                            $('#boQuantitySelection').css('border', 'solid 1px red');
                        }
                    }

                    // shiping address - if one is populated
                    if ($('#StreetAddress').val() != ''
                        || $('#City').val() != ''
                        || $('#State').val() != ''
                        || $('#Country').val() != ''
                        || $('#ZipCode').val() != '') {
                        // then verify all are populated
                        if ($('#StreetAddress').val() == ''
                            || $('#City').val() == ''
                            || $('#State').val() == ''
                            || $('#Country').val() == ''
                            || $('#ZipCode').val() == '') {
                            isValid = false;
                            if ($('#StreetAddress').val() == '') {
                                $('#StreetAddress').css('border-color', 'red');
                            }
                            if ($('#City').val() == '') {
                                $('#City').css('border-color', 'red');
                            }
                            if ($('#State').val() == '') {
                                $('#State').css('border-color', 'red');
                            }
                            if ($('#Country').val() == '') {
                                $('#Country').css('border-color', 'red');
                            }
                            if ($('#ZipCode').val() == '') {
                                $('#ZipCode').css('border-color', 'red');
                            }
                        }
                    }

                    return isValid;
                },

                convertToJsonDateString = function (date) {

                    if (date) {
                        var _date;

                        if (typeof date === "string") {
                            _date = new Date(date);
                        } else if (typeof date === "object") {
                            _date = date;
                        } else {
                            return null;
                        }

                        var timeStamp = _date.getTime(),
                            jsonDate = "\/Date(%timestamp%)\/";

                        return jsonDate.replace('%timestamp%', timeStamp);

                    } else {

                        return null;
                    }
                },

                cancelBulkOrderRequest = function () {
                    $window.close();

                },

                submitBulkOrderRequest = function () {

                    if (!bulkOrderRequestFormIsValid()) {
                        Common.showMessage('danger', 'Please correct missing/invalid fields below');
                        return;
                    }

                    var boRequest =
                    {
                        CustomerName: $scope.customer.FullName,
                        CompanyName: $scope.customer.CompanyName,
                        Email: $scope.customer.Email,
                        Phone: $scope.customer.Phone,
                        Fax: $scope.customer.Fax,
                        Address: $scope.boStreetAddress,
                        City: $scope.boCity,
                        State: $scope.boState,
                        Country: $scope.boCountry,
                        PostalCode: $scope.boZipCode,
                        Notes: $scope.boNotes,
                        ContactMethod: $scope.boContactMethod,
                        EventDate: $scope.boEventDate,
                        RequestedByDate: $scope.boRequestBytDate,
                        CustomerLoggedIn: !$scope.user.IsAnonymous,
                        CustomerId: $scope.user.CustomerId,
                        CustomerCopy: $scope.boCopyMe,
                        Type: 'Bulk',
                        Items: []
                    };

                    if ($scope.boProducts != undefined && $scope.boProducts.length > 0) {// dynamic custom attributes
                        for (var i = 0; i < $scope.boProducts.length; i++) {
                            // only add items with a qty > 0 selected
                            if ($scope.boProducts[i].desiredQty != '' && $scope.boProducts[i].desiredQty > 0) {
                                var item = {
                                    ProductNumber: $scope.boProducts[i].ProductNumber,
                                    Option: $scope.boProducts[i].Name,
                                    Quantity: $scope.boProducts[i].desiredQty
                                }
                                boRequest.Items[boRequest.Items.length] = item;
                            }
                        }
                    } else {// no custom attributes
                        boRequest.Items[0] = {
                            ProductNumber: $scope.currentProduct.ProductNumber,
                            Option: '',
                            Quantity: $scope.boQuantity
                        }
                    }

                    Products.sendBulkOrderRequest($scope.currentProduct.ProductSlug, boRequest)
                        .then(function (response) {
                            Common.showMessage('success', 'Your bulk order request has been submitted.');
                            $scope.boSubmitted = true;
                            $timeout(function () {
                                $window.close();
                            }, 6000);
                        });
                },

                submitCustomizationRequest = function () {

                    if (!bulkOrderRequestFormIsValid()) {
                        Common.showMessage('danger', 'Please correct missing/invalid fields below');
                        return;
                    }

                    var boRequest =
                    {
                        CustomerName: $scope.customer.FullName,
                        CompanyName: $scope.customer.CompanyName,
                        Email: $scope.customer.Email,
                        Phone: $scope.customer.Phone,
                        Fax: $scope.customer.Fax,
                        Address: $scope.boStreetAddress,
                        City: $scope.boCity,
                        State: $scope.boState,
                        Country: $scope.boCountry,
                        PostalCode: $scope.boZipCode,
                        Notes: $scope.boNotes,
                        ContactMethod: $scope.boContactMethod,
                        RequestedByDate: $scope.boRequestBytDate,
                        CustomerLoggedIn: !$scope.user.IsAnonymous,
                        CustomerId: $scope.user.CustomerId,
                        CustomerCopy: $scope.boCopyMe,
                        Type: 'Customization',
                        Items: []
                    };

                    if ($scope.boProducts != undefined && $scope.boProducts.length > 0) {// dynamic custom attributes
                        for (var i = 0; i < $scope.boProducts.length; i++) {
                            // only add items with a qty > 0 selected
                            if ($scope.boProducts[i].desiredQty != '' && $scope.boProducts[i].desiredQty > 0) {
                                var item = {
                                    ProductNumber: $scope.boProducts[i].ProductNumber,
                                    Option: $scope.boProducts[i].Name,
                                    Quantity: $scope.boProducts[i].desiredQty
                                }
                                boRequest.Items[boRequest.Items.length] = item;
                            }
                        }
                    } else {// no custom attributes
                        boRequest.Items[0] = {
                            ProductNumber: $scope.currentProduct.ProductNumber,
                            Option: '',
                            Quantity: $scope.boQuantity
                        }
                    }

                    Products.sendBulkOrderRequest($scope.currentProduct.ProductSlug, boRequest)
                        .then(function (response) {
                            Common.showMessage('success', 'Your customization request has been submitted.');
                            $scope.boSubmitted = true;
                            $timeout(function () {
                                $window.close();
                            }, 6000);
                        });
                },

                hideChildProductTable = function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }

                    $scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct); //reset Personalization Lite section when shift from multiple to simple order
                    $scope.childProductTableVisible = false;
                },

                notifyMe = function ($event, product, productName) {
                    if ($event) {
                        $event.preventDefault();
                    }

                    try {
                        var customerId = $scope.user.CustomerId,
                            wishListItem = {};

                        if (customerId) {

                            wishListItem = {
                                ProductName: product.Name,
                                ProductNumber: product.ProductNumber,
                                CustomerId: customerId
                            };

                            wishListItem.NotificationSettings = [];
                            wishListItem.NotificationSettings.push({ Type: 'NotifyMe', Enabled: true });


                            Customers.addWishListItem(customerId, wishListItem)
                                .then(function (response) {
                                    var showProductName = productName || product.Name;
                                    Common.showMessageNew('success', 'None', '609', { replace: '%product%', value: showProductName });
                                    $log.log('Product added to wishlist for notify me.');
                                });
                        } else {
                            Common.showMessage('danger');
                        }

                    } catch (e) {
                        Common.showMessage('danger'); //will display generic error message... something went wrong. 
                    }

                },

                resetAddToFavorites = function () {
                    $scope.addToFavoritesSubmitted = false;
                },

                //added to work for new array - additional info types (external link and spec sheet)
                linkAttributeFilter = function (attribute) {

                    if (attribute.TypeName && (attribute.TypeName.toLowerCase() === 'external link' || attribute.TypeName.toLowerCase() === 'spec sheet')) {
                        return true;
                    } else {
                        return false;
                    }
                },

                //refactored to work for new array - additional info types (Size Chart)
                popupLinkAttributeFilter = function (attribute) {

                    if (attribute.TypeName && attribute.TypeName.toLowerCase() === 'size chart') {
                        return true;
                    } else {
                        return false;
                    }
                },

                childProductDiscontinuedFilter = function (child) {

                    if (child.IsDiscontinued && child.QtyAvailable <= 0) {
                        return false;
                    } else {
                        return true;
                    }

                },

                childOptionsMediaFilter = function (option) {

                    if (option.Option.toLowerCase() === 'media') {
                        return true;
                    } else {
                        return false;
                    }

                },

                childOptionsStandardFilter = function (option) {

                    if (option.Option.toLowerCase() === 'media') {
                        return false;
                    } else {
                        return true;
                    }

                },

                getCustomer = function () {

                    if ($scope.user.CustomerId) {
                        Customers.getCustomer($scope.user.CustomerId)
                            .then(function (response) {
                                setDefaults(response.data);
                            });
                    }
                },

                setDefaults = function (customer) {

                    $scope.customer = customer;
                    $scope.addressType = 'BillingAddress';
                    $scope.activeForm = 'myAccountBillingForm';

                    //AddressService.getCountries($scope, 'Billing');
                    //AddressService.getStateOrRegions($scope, customer[$scope.addressType].Country);
                },

                addToFavorites = function (product) {
                    $scope.addToFavoritesSubmitted = true;

                    try {
                        var customerId = $scope.user.CustomerId,
                            wishListItem = {};

                        if (customerId) {
                            wishListItem = {
                                ProductName: product.Name,
                                ProductNumber: product.ProductNumber,
                                CustomerId: customerId
                            };

                            Customers.addWishListItem(customerId, wishListItem)
                                .then(function (response) {
                                    //Common.showMessage('success', '', { replace: '%product%', value: product.Name }); //"Thank you!  %product% has been added to your wish list!",
                                    Common.showMessageNew('favorite', 'AddToFavorites', '603', { replace: '%product%', value: product.Name }, {
                                        product: {
                                            name: product.Name,
                                            productSlug: product.ProductSlug,
                                            productNumber: product.ProductNumber,
                                            image: getProductMainImageUrl(product),
                                            qty: product.Qty,
                                            price: product.Price,
                                            displayPrice: product.DisplayPrice,
                                            url: ProductUrlService.getUrl(product.ProductSlug)
                                        },
                                        customer: {
                                            name: $scope.user.Name,
                                            email: $scope.user.Email
                                        }
                                    });

                                    resetAddToFavorites();
                                }, function () { resetAddToFavorites(); });
                        }
                        else {
                            Common.showMessage('danger', '601'); // must be logged in to save wish list item
                            resetAddToFavorites();
                        }

                    }
                    catch (e) {
                        Common.showMessage('danger'); //will display generic error message... something went wrong. 
                        resetAddToFavorites();
                    }
                },

                goToPromotionInfo = function (anchorName) {
                    var productTextArray = $scope.currentProduct.Text,
                        searchText = 'promotions';

                    for (var i = 0, len = productTextArray.length; i < len; i += 1) {
                        if (productTextArray[i].TextName.toLowerCase() === searchText) {
                            productTextArray[i].tabActive = true;
                            break;
                        }

                    }

                    $scope.$scrollTop($('#' + anchorName).position().top);
                },

                addTotalDesiredQty = function (desiredQty, child) {                    
                    var newDesiredQty = 0;
                    if (child != null && desiredQty != null) {                        
                        if (!$scope.totalDesiredProducts.some(obj => child.ProductNumber == obj.productNumber)) {
                            $scope.totalDesiredProducts.push({
                                productNumber: child.ProductNumber,
                                desiredQty: desiredQty
                            })
                        } else if (!$scope.totalDesiredProducts.some(obj => child.productNumber == obj.productNumber && desiredQty != obj.desiredQty)) {
                            var index = $scope.totalDesiredProducts.findIndex(obj => obj.productNumber == child.ProductNumber)
                            if (index != -1) { $scope.totalDesiredProducts[index].desiredQty = desiredQty }
                        } else if (!$scope.totalDesiredProducts.some(obj => child.productNumber == obj.productNumber) && desiredQty == 0) {
                            var index = $scope.totalDesiredProducts.findIndex(obj => obj.productNumber == child.ProductNumber)
                            if (index != -1) { $scope.totalDesiredProducts.splice(index) }
                        }
                        $scope.totalDesiredProducts.forEach(obj => newDesiredQty += obj.desiredQty)
                        $scope.totalDesiredQty = newDesiredQty                        
                    }                    
                },

                getPriceToUse = function (useSellDisplayPrice, product) {
                    if ((useSellDisplayPrice === "True") && product.DisplayPrice) {
                        return product.DisplayPrice;
                    } else if (product.IsTieredPrice) {
                        var toReturn;
                        var tierToUse = product.PriceTiers[0];
                        product.PriceTiers.forEach(function (tier) {
                            if ($scope.totalDesiredQty >= tier.MinOrderQuantity && $scope.totalDesiredQty <= tier.MaxOrderQuantity) {
                                tierToUse = tier
                            }
                            else if ($scope.totalDesiredQty >= tier.MinOrderQuantity && tier.MaxOrderQuantity == 0 && $scope.totalDesiredQty != 0) {
                                tierToUse = tier
                            }
                        });
                        toReturn = tierToUse.Price;
                        return toReturn
                    } else {
                        return product.Price;
                    }
                },

                openPersonalizationEditor = function (product, child) {
                    //If passed, grab the ChildProduct model from the multi loop and assign its ProductNumber
                    if (child) {
                        product.ProductNumber = child.ProductNumber;
                    }
                    var modalInstance = $uibModal.open({
                        templateUrl: 'ChiliPersonalizationEditor.html',
                        controller: 'chiliPersonalizationEditorModalCtrl',
                        size: 'fillmost',
                        backdrop: 'static',
                        resolve: {
                            currentProduct: function () {
                                return product;
                            },
                            appConfig: function () {
                                return $scope.$appConfig;
                            }
                        }
                    });

                    modalInstance.result.then(function (result) {
                        var quantity = result.Quantity;
                        var personalization = result.Personalization;
                        if (quantity) {
                            product.desiredQty = quantity;
                            product.ThirdPartyPersonalizations =
                                [{
                                    Quantity: quantity,
                                    DocumentId: personalization.finalDocumentId,
                                    PersonalizationVariables: personalization.variables
                                }];
                            addToCart(product);
                        }
                    }, function () {
                        //Common.showMessage('danger', '639');
                    });
                };

            initialiseZoomOptions = function () {
                imageZoomOptions = {
                    zoomEnable: $scope.currentProduct.SupportZoom,
                    defaultIndex: 0,
                    style: "box",
                    boxPos: "right-top",
                    boxW: 400,
                    boxH: 400,
                    method: "lens",
                    cursor: "zoom-in",
                    lens: true,
                    zoomLevel: 3,
                    immersiveMode: "769",
                    immersiveModeOptions: {},
                    immersiveModeMessage: 'Tap to Zoom', // Immersive mode message
                    prevThumbButton: "&#9665;",
                    nextThumbButton: "&#9655;",
                    thumbsPos: "bottom",
                    thumbCol: 10,
                    thumbColPadding: 4,
                    images: []
                }

                for (var i = 0; i < $scope.currentProduct.Images.length; i++) {
                    var image = {
                        thumb: $scope.$appConfig.ProductImageBaseURL + $scope.currentProduct.Images[i].FileName + '-TT' + $scope.currentProduct.Images[i].Extension,
                        medium: $scope.$appConfig.ProductImageBaseURL + $scope.currentProduct.Images[i].FileName + '-l' + $scope.currentProduct.Images[i].Extension,
                        large: $scope.currentProduct.SupportZoom ? $scope.$appConfig.ProductImageBaseURL + $scope.currentProduct.Images[i].FileName + '-xl' + $scope.currentProduct.Images[i].Extension : $scope.$appConfig.ProductImageBaseURL + $scope.currentProduct.Images[i].FileName + '-l' + $scope.currentProduct.Images[i].Extension,
                    }
                    imageZoomOptions.images[imageZoomOptions.images.length] = image;
                }


                $scope.selectedIndex = 0;
                $scope.selectedModel = imageZoomOptions.images[0]
                $scope.zoomoptions = imageZoomOptions;

            }

            loadProduct();

            $scope.$scrollTop();
            //Bread crumbs now done via URL
            //setBreadCrumb();

            $scope.addToCartSubmitted = false;
            $scope.addToFavoritesSubmitted = false;
            $scope.personalizationComplete = false;
            $scope.goToPromotionInfo = goToPromotionInfo;
            $scope.swapImage = swapImage;
            $scope.addToCart = addToCart;
            $scope.openPersonalizationEditor = openPersonalizationEditor;
            $scope.addToFavorites = addToFavorites;
            $scope.updateToSelectedProduct = updateToSelectedProduct;
            $scope.showSendToFriend = showSendToFriend;
            $scope.showInStockInfo = showInStockInfo;
            $scope.notifyMe = notifyMe;

            $scope.actionButtonsVisible = !$scope.user.IsAnonymous;
            $scope.productUI = ProductUIService;

            $scope.getSavingsAmount = getSavingsAmount;
            $scope.childProductTableVisible = false;
            $scope.selectedRegionRequiredError = false;
            $scope.childProductOptionShown = "";
            $scope.showChildProductTable = showChildProductTable;
            $scope.hideChildProductTable = hideChildProductTable;
            $scope.addChildProductsToCart = addChildProductsToCart;
            $scope.childProducts = [];
            $scope.toggleHelp = Common.toggleHelp;
            $scope.childProductDiscontinuedFilter = childProductDiscontinuedFilter;
            $scope.childOptionsMediaFilter = childOptionsMediaFilter;
            $scope.childOptionsStandardFilter = childOptionsStandardFilter;
            $scope.loadProduct = loadProduct;
            $scope.loadBulkOrderOptions = loadBulkOrderOptions;
            $scope.submitBulkOrderRequest = submitBulkOrderRequest;
            $scope.submitCustomizationRequest = submitCustomizationRequest;
            $scope.cancelBulkOrderRequest = cancelBulkOrderRequest;
            $scope.getPriceToUse = getPriceToUse;
            $scope.addTotalDesiredQty = addTotalDesiredQty;
            $scope.totalDesiredProducts = [];
            $scope.totalDesiredQty = 0
            $scope.showQuantitySelection = false;
            $scope.boSubmitted = false;
            $scope.bogoOptionSelected = null;
            initialiseZoomOptions();
            $scope.zoomoptions
        }])
    .controller('bogoOptionSelectModalCtrl', [
        '$scope',
        'Products',
        '$uibModalInstance',
        'currentProduct',
        'appConfig',
        function ($scope, Products, $uibModalInstance, currentProduct, appConfig) {

            $scope.product = currentProduct;
            $scope.bogoProduct = null;
            $scope.appConfig = appConfig;
            $scope.waitingOnOptionChange = false;
            $scope.bogoProductNumber = null;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

            $scope.addToCart = function () {
                $uibModalInstance.close($scope.bogoProduct);
            };

            $scope.updateBOGOProduct = function (selectedOption) {
                $scope.waitingOnOptionChange = true;
                getProduct(selectedOption);
            };

            getProduct = function (productSlug) {
                Products.getProduct({ ':sku': productSlug })
                    .then(function (response) {
                        setUpProductData(response.data);
                        $scope.waitingOnOptionChange = false;
                    },
                        function () {
                            //Cancel out of it in case we get an error
                            $uibModalInstance.dismiss('cancel');
                        });
            };

            setUpProductData = function (product) {
                if (product.ChildProductOptions && product.ChildProductOptions.length > 0) {
                    angular.forEach(product.ChildProductOptions, function (productOption, i) {

                        //check if this is the current product we are viewing.
                        angular.forEach(productOption.Values, function (option, i) {
                            if (option.IsThisProduct) {
                                productOption.selectedOption = option.ProductSlug;
                                option.selectedIndex = i;
                            }
                        });
                    });
                }

                $scope.bogoProduct = product;

                //setUpImages();
                initialiseZoomOptions();
            };

            initialiseZoomOptions = function () {
                imageZoomOptions = {
                    zoomEnable: $scope.bogoProduct.SupportZoom,
                    defaultIndex: 0,
                    style: "box",
                    boxPos: "right-top",
                    boxW: 300,
                    boxH: 300,
                    method: "lens",
                    cursor: "zoom-in",
                    lens: true,
                    zoomLevel: 3,
                    immersiveMode: "769",
                    immersiveModeOptions: {},
                    immersiveModeMessage: 'Tap to Zoom', // Immersive mode message
                    prevThumbButton: "&#9665;",
                    nextThumbButton: "&#9655;",
                    thumbsPos: "bottom",
                    thumbCol: 10,
                    thumbColPadding: 4,
                    images: []
                }

                for (var i = 0; i < $scope.bogoProduct.Images.length; i++) {
                    var image = {
                        thumb: $scope.appConfig.ProductImageBaseURL + $scope.bogoProduct.Images[i].FileName + '-TT' + $scope.bogoProduct.Images[i].Extension,
                        medium: $scope.appConfig.ProductImageBaseURL + $scope.bogoProduct.Images[i].FileName + '-l' + $scope.bogoProduct.Images[i].Extension,
                        large: $scope.bogoProduct.SupportZoom ? $scope.appConfig.ProductImageBaseURL + $scope.bogoProduct.Images[i].FileName + '-xl' + $scope.bogoProduct.Images[i].Extension : $scope.appConfig.ProductImageBaseURL + $scope.bogoProduct.Images[i].FileName + '-l' + $scope.bogoProduct.Images[i].Extension,
                    }
                    imageZoomOptions.images[imageZoomOptions.images.length] = image;
                }


                $scope.selectedIndex = 0;
                $scope.selectedModel = imageZoomOptions.images[0]
                $scope.zoomoptions = imageZoomOptions;

            }

            getProduct(currentProduct.BOGOWithOptionsProductSlug);


        }])

    .controller('chiliPersonalizationEditorModalCtrl', [
        '$scope',
        '$http',
        '$sce',
        '$uibModalInstance',
        'Common',
        'currentProduct',
        'appConfig',
        function ($scope, $http, $sce, $uibModalInstance, Common, currentProduct, appConfig) {
            // https://chilipublishdocs.atlassian.net/wiki/spaces/CPDOC/pages/1412072/JavaScript+Events
            // https://chilipublishdocs.atlassian.net/wiki/spaces/CPDOC/pages/1413908/General+Document+and+Editor+functions

            var editor = null;

            $scope.loading = true;
            $scope.error = '';
            $scope.product = currentProduct;
            $scope.appConfig = appConfig;
            $scope.isfullyloaded = false;
            $scope.invalidData = true;
            $scope.editorUrl = '';
            $scope.minOrderQty = currentProduct.isTemplate ? 1 : currentProduct.minQntyLmt;
            $scope.product.desiredQty = currentProduct.minQntyLmt;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

            $scope.save = function () {
                validateEditorVariables();
                //Quantity must be above 0
                if (currentProduct.desiredQty > 0 && !$scope.invalidData) {
                    Common.showLoader('135');
                    editor.ExecuteFunction("document", "Save");
                }
            };

            $scope.onQuantityChange = function () {
                validateEditorVariables();
            };

            $scope.safeApply = function (fn) {
                var phase = this.$root.$$phase;
                if (phase == '$apply' || phase == '$digest') {
                    if (fn && (typeof (fn) === 'function')) {
                        fn();
                    }
                } else {
                    this.$apply(fn);
                }
            };

            function validateEditorVariables() {
                $scope.invalidData = $scope.product.desiredQty == null || $scope.product.desiredQty < 1;

                let variableCount = editor.GetObject("document.variables").length;
                for (var i = 0; i < variableCount; i++) {
                    let chiliVariable = editor.GetObject("document.variables[" + i + "]");
                    if (chiliVariable != null && (chiliVariable.required === "true" && chiliVariable.visible === "true" && !chiliVariable.value)) {
                        $scope.invalidData = true;
                        break;
                    }
                }
                $scope.safeApply();
            }

            function onDocumentSaved() {
                $http({
                    method: "post",
                    url: App.Configuration.RootPath + 'Personalization/FinalizeWorkingDocument',
                    data: JSON.stringify({
                        rootProductId: currentProduct.RootProductId
                    })
                }).success(function (response) {
                    Common.hideLoader();
                    var result =
                    {
                        Quantity: currentProduct.desiredQty,
                        Personalization: response
                    }

                    $uibModalInstance.close(result);
                }).error(function (response) {
                    Common.hideLoader();
                });
            };

            // setup the global chili event handler
            window.OnEditorEvent = function (type, targetID) {
                switch (type) {
                    case "DocumentSaved":
                        onDocumentSaved();
                        break;
                    case "DocumentFullyLoaded":
                        $scope.isfullyloaded = true;
                        $scope.$apply();
                        frameWindow = document.getElementById("chili-iframe").contentWindow;
                        editor = frameWindow.editorObject;
                        validateEditorVariables()
                        editor.AddListener("document", "DocumentSaved");
                        editor.AddListener("VariableValueChanged"); //Monitor for value changes.
                        break;
                    case "VariableValueChanged":
                        validateEditorVariables();
                        break;
                }
            }

            // call our api to setup working document and render the chili editor in iframe
            $http({
                method: "get",
                url: App.Configuration.RootPath + 'Personalization/ChiliEditor?rootProductId=' + currentProduct.RootProductId
            }).success(function (response) {
                $scope.loading = false;
                if (response.editorUrl) {
                    //workingDocumentId = response.workingDocumentId;

                    // rewrite editorUrl for iframe security (requires IIS to be setup with reverse proxy)
                    var editorUrl = new URL(response.editorUrl);
                    var proxyurl = window.location.origin + '/chiliproxy' + editorUrl.pathname + editorUrl.search;
                    $scope.editorUrl = $sce.trustAsResourceUrl(proxyurl);
                } else {
                    $scope.error = 'Something went wrong. Please try again later.';
                }
            }).error(function (response) {
                $scope.loading = false;
                $scope.error = 'Something went wrong. Please try again later.';
            });
        }]);;angular
    .module('ecs.ctrl.product.instock', [])
    .controller('productInStockModalCtrl', [
                '$scope',
                'Products',
                'Common',
                '$log',
                'currentProduct',
                'childProduct',
                'EcsLocale',
                '$uibModalInstance',
            function ($scope, Products, Common, $log, currentProduct, childProduct, EcsLocale, $uibModalInstance) {

                var cancel = function (form) {
                    $scope.$dismiss();
                }

                var notifyMe = function () {
                    $uibModalInstance.close();
                }

            initForm = function () {
                var productNumber = "";
                $scope.outstandingPOs = null;
                if (childProduct)
                    productNumber = childProduct.PurchaseProductNumber ? childProduct.PurchaseProductNumber : childProduct.ProductNumber;
                else
                    productNumber = currentProduct.PurchaseProductNumber ? currentProduct.PurchaseProductNumber : currentProduct.ProductNumber;

                $scope.productNumber = productNumber;
                $scope.currentProduct = childProduct ? childProduct : currentProduct;
                if (!childProduct)
                    $scope.currentProduct.IsDiscontinued = currentProduct.Discontinued;

                if (($scope.currentProduct.AllowBackOrder || !$scope.currentProduct.IsDiscontinued) && !$scope.currentProduct.IsOnDemand) {

                    Products.getOutstandingPOs(productNumber).then(
                        function (success) {
                            if (success.data.length > 0) {
                                angular.forEach(success.data, function (item) {
                                    item.EstimatedArrival = EcsLocale.convertDate(Common.convertJsonDateObject(item.EstimatedArrival));
                                });
                                $scope.outstandingPOs = success.data;
                                $scope.modalMessage = "This is the expected date that the shipment will arrive at our warehouse. The date is not guaranteed, and it is only an estimate based on supplier lead time.";
                            }
                            else if ($scope.currentProduct.QtyAvailable > 0)
                                $scope.modalMessage = "This product is currently in stock and available to ship. We currently do not have an available re-stock date for this item. If you require more than we currently have in stock, we will gladly accept your back order and make every effort possible to ship within 15 business days.";                            
                            else
                                $scope.modalMessage = "We currently do not have an available stock date for this item. However, we will gladly accept your back order and make every effort possible to ship within 15 business days.";
                            $scope.additionalModalMessage = "Sign into the site, then come back to this product, request More Info for the availability, then you will be able to request a notification for when the item is back in stock.";

                            $scope.modalData = success.data;
                        },
                        function (error) {
                            Common.showMessage('danger');
                        });
                } else if ($scope.currentProduct.IsOnDemand && $scope.currentProduct.IsOutOfStock) {
                    $scope.modalMessage = "Our suppliers are currently out of stock of this item. In an effort to ensure the other items in your order can be shipped to you as soon as possible, we cannot allow this item to be ordered at this time. ";
                    if (!!$scope.currentProduct.EstimatedAvailabilityDate) {
                        var estimatedAvailabilityDate = childProduct ? EcsLocale.convertDate(Common.convertJsonDateObject($scope.currentProduct.EstimatedAvailabilityDate)) : EcsLocale.convertDate($scope.currentProduct.EstimatedAvailabilityDate);
                        $scope.modalMessage = $scope.modalMessage + "Per our suppliers, the expected date this item will be available again is " + estimatedAvailabilityDate + ". ";
                    }
                    $scope.modalMessage = $scope.modalMessage + "We apologize for any inconvenience.";
                }
                Common.focusElement('#SendToName');
            },

            self = this;

                $scope.cancel = cancel;
                $scope.notifyMe = notifyMe;

                initForm();


                /*
                remove_showSendToFriendListener = $rootScope.$on('showSendToFriendModal', function (event, currentProduct) {
                    showModal(currentProduct);
                });

                */
            }]);;
angular
    .module('ecs.ctrl.catalog', [])
    .controller('catalogCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'Catalogs',
        '$log',
        'CartService',
        'Common',
        '$timeout',
        function ($scope, $location, EcsResource, Catalogs, $log, CartService, Common, $timeout) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the Catalog.

            var getCurrentCatalog = function () {
                //note: now returning products from the catalog.
                return ECSStores.Catalog;
            },

                showSpotlight = false,



                addItemToCart = function (product) {
                    $log.log('Item added to cart');
                    var cartItem = {}
                    var url = "/product/" + product.ProductSlug;
                    cartItem.ProductNumber = product.ProductNumber;
                    cartItem.Qty = 1;
                    cartItem.Price = product.Price;
                    if (product.IsGroup == false) {
                        CartService.addCartItem(cartItem);
                    }
                    else {

                        $location.path(url);
                    }

                },

                getSortLabel = function () {

                    var sortLabels = {
                        'NEWEST': 'Newest',
                        'PRICELOW-HI': 'Lowest Price',
                        'PRICEHI-LOW': 'Highest Price',
                        'NAMEA-Z': 'Alphabetical'

                    }

                    return sortLabels[$scope.sortOrder] || 'Sort Chosen';
                },

                getCatalogId = function () {

                    var splitUrl = $location.url().split(/\//),
                        len = splitUrl.length,
                        id = splitUrl[len - 1];

                    //Make sure we're not refining anything
                    if (len > 2) {
                        var refPath = splitUrl[len - 2];
                        if (refPath.toUpperCase() == 'RF')
                            id = splitUrl[len - 3];
                    }
                    return id;
                },

                //facetsObj,

                setFacets = function (facets) {

                    $scope.facets = facets;
                },

                refineSearch = function (scope, facetToRemove, value) {

                    Common.refineSearch($scope, facetToRemove, value);
                },


                loadCatalog = function () {

                    var currentCatalog = getCurrentCatalog();
                    //setBreadCrumb(); done via URL now

                    if (currentCatalog.Products) {
                        setFacets(currentCatalog.Facets);
                        $scope.currentCatalog = currentCatalog.Products;
                        Common.setActiveFacets($scope, null);

                    } else {
                        Catalogs.getCatalog({ ':catalogId': getCatalogId() })
                            .then(function (response) {
                                $scope.currentCatalog = response.data.Products;
                                setFacets(response.data.Facets);
                                Common.setActiveFacets($scope, null);
                            });
                    }



                },


                getSpotlightProducts = function () {
                    return ECSStores.SpotlightProducts;

                },


                loadSpotlightProducts = function () {

                    var spotlightProducts = getSpotlightProducts();

                    if (spotlightProducts) {
                        $scope.spotlightProducts = spotlightProducts;

                    } else {
                        Catalogs.getCatalog({ ':catalogId': getCatalogId() })
                            .then(function (response) {
                                $scope.spotlightProducts = response.data;
                            });
                    }



                },

                sortItems = function ($event, order, catalogName) {

                    $event.preventDefault();

                    var params = {
                        ':catalogId': getCatalogId(),
                        'order': order
                    },
                        facets = Common.getFacets($scope, true);

                    if (facets && facets.length > 0) {
                        angular.extend(params, { 'q': facets });
                    };


                    Catalogs.getCatalogProducts(params)
                        .then(function (response) {
                            $scope.sortOrder = order;
                            $scope.facets = response.data.Facets;
                            $scope.currentCatalog = response.data.Products;
                        });
                },


                getItems = function (a, b, catalogName) {
                    var order = $scope.sortOrder,
                        params = {
                            ':catalogId': getCatalogId(),
                            'order': order
                        },
                        facets = Common.getFacets($scope, true);

                    if (facets && facets.length > 0) {
                        angular.extend(params, { 'q': facets });
                    };

                    $scope.$scrollTop($('#sidebar').offset().top);
                    Common.showLoader('127');

                    Catalogs.getCatalogProducts(params)
                        .then(function (response) {
                            $scope.sortOrder = order;
                            $scope.facets = response.data.Facets;
                            $scope.currentCatalog = response.data.Products;

                        });
                },

                showProductGalleryInfo = function (event, product) {
                    $scope.productGalleryInfo.position = {
                        top: event.clientY + 'px',
                        left: event.clientX + 'px'
                    };

                    $scope.productGalleryInfo.product = product;
                    $scope.productGalleryInfo.showPopover = showStockOnGalleryView == 'True';
                },

                //Bread crumbs now done via URL
                //setBreadCrumb = function () {
                //    var p = window.location.href.split("/"),
                //        catalogSlugArray = p[p.length - 1].split("-"),
                //        catalogHeading = p[p.length - 1].replace(/[0-9]/g, "").replace(/-/g, " ").trim(),
                //        breadcrumb = { heading: catalogHeading, last: Common.getPreviousLocationLabel() };

                //    Common.setCurrentCatalogName(catalogHeading);

                //    $scope.breadcrumb = breadcrumb;

                //},

                loadCartInfo = function () {

                    $scope.cartInfo = CartService.getCart();

                },


                lookForFacets = function () {
                    $timeout(function () {
                        if ($(".facets .facet-title").filter(':visible').length !== 0)
                            $scope.noFacetsVisible = false;
                        else
                            $scope.noFacetsVisible = $(".facet-value").filter(':visible').length === 0;
                    }, 100);
                };

                

      

            $scope.addItemToCart = addItemToCart;
            $scope.sortItems = sortItems;
            $scope.addItemToCart = addItemToCart;
            $scope.showSpotlight = showSpotlight;
            $scope.sortOrder = 'NEWEST';

            $scope.getSortLabel = getSortLabel;
            $scope.refineSearch = refineSearch;
            $scope.activeFacets = [];
            $scope.facetHidden = {};
            $scope.getItems = getItems;
            $scope.toggleFacet = Common.toggleFacet;
            $scope.noFacetsVisible = false;
            $scope.showProductGalleryInfo = showProductGalleryInfo;
            $scope.productGalleryInfo = {
                templateUrl: 'ProductGalleryModalContent.html',
                position: { top: 0, left: 0 },
                product: null,
                showPopover: false
            };

            $scope.$on('onRepeatLast', lookForFacets); 



            $scope.changeFocus = Common.changeFocus;
            loadCatalog();
            //loadSpotlightProducts();
            loadCartInfo();


        }])
    .controller('ProductGalleryInfoCtrl', [
        '$scope',
        '$log',
        '$sce',
        'Products',
        function($scope, $log, $sce, Products) {

            //$scope.multipleBudgetCodes = false;
            //var firstBudgetCode = (balances.length > 0) ? balances[0].BudgetCode : '';
            //for (i = 0; i < balances.length; i++) {
            //    balances[i].descriptionHTML = $sce.trustAsHtml(balances[i].BudgetDescription);
            //    if (firstBudgetCode !== balances[i].BudgetCode)
            //        $scope.multipleBudgetCodes = true;
            //}
            const availability = {
                AVAILABLE: "Available",
                UNAVAILABLE: "Unavailable",
                ONORDER: "On Order",
                DISCONTINUED: "Discontinued",
                PREORDER: "Pre-Order",
            }
            var childOptionSort = [];
            //var imageZoomOptions = {};

            childOptionSort['color'] = function(arr) {
                return arr.sort(function(a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };
            childOptionSort['media'] = function(arr) {
                return arr.sort(function(a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };

            $scope.childProducts = [];



            loadProduct = function() {
                fetchProduct($scope.productGalleryInfo.product.ProductSlug);

                //var currentProduct = getCurrentProduct();

                ////check to see if we have current product data, and if that product data
                ////is still valid. Anything over 20 seconds old is cached on the page.
                //if (currentProduct) {
                //    $log.log('Product loaded from page cache');

                //    setUpProductData(currentProduct);
                //} else {
                //    $log.log('Product fetch from API');

                //    fetchProduct(getProductSlug());
                //}
            };

            fetchProduct = function(productSlug) {

                Products.getProduct({ ':sku': productSlug })
                    .then(function(response) {
                        setUpProductData(response.data);
                    });
            };

            getPointsConfig = function() {
                return ECSStores.PointsConfig || {};
            };

            setUpProductData = function(product) {
                var pointsConfig = getPointsConfig();
                $scope.availability = availability;
                $scope.isPointsValueNull = pointsConfig != null && pointsConfig.PointsValue && product.PointsValue == null;
                var qtyAvailable = product.QtyAvailable,
                    //Show the Notify Me option if there is no quantity, the item is not discontinued, and it is a product that can't be backordered
                    showNotify = Number(qtyAvailable) <= 0 && !product.Discontinued && !product.AllowBackOrder && !product.IsPreOrder,

                    //Show Add to Cart if Allow Back Order is true or if the qty available is > 0
                    showAddToCart = (product.AllowBackOrder || Number(qtyAvailable) > 0 || product.IsPreOrder),

                    //Set the avail flag. 1 = Unavailable, 2 = On Order, 3 = Discontinued
                    availFlag = $scope.isPointsValueNull ? availability.DISCONTINUED : Number(qtyAvailable) <= 0 ? (!product.Discontinued ? (showNotify ? availability.UNAVAILABLE : availability.ONORDER) : availability.DISCONTINUED) : availability.AVAILABLE,

                    hasImages = product.Images.length > 0,
                    hasOptions = product.ChildProductOptions && product.ChildProductOptions.length > 0,
                    //relatedProducts = getRelatedProducts(),
                    showMinQntyLmt = (product.MinimumQuantityLimit != undefined);

                if (product.IsPreOrder)
                    availFlag = availability.PREORDER;

                //if (relatedProducts) {
                //    setUpRelatedProductData(relatedProducts);
                //} else {
                //    loadRelatedProducts(product);
                //};

                var isApparel = false;
                if (hasOptions) {
                    angular.forEach(product.ChildProductOptions, function(productOption, i) {
                        //check if we have a sort for this type of data...
                        var sortFunc = childOptionSort[productOption.Option.toLowerCase()];
                        if (sortFunc !== undefined) {
                            productOption.Values = sortFunc(productOption.Values);
                        }
                        //check if this is the current product we are viewing.
                        angular.forEach(productOption.Values, function(option, i) {
                            if (option.IsThisProduct) {
                                productOption.selectedOption = option.ProductSlug;
                                option.selectedIndex = i;
                            }

                            if (option.Option.toLowerCase() === 'media') {
                                $scope.isMedia = true;
                            } else {
                                $scope.isMedia = false;
                            }

                            if (option.Option.toLowerCase() === 'size') {
                                isApparel = true;
                            }

                        });
                        if (!productOption.selectedOption) {
                            productOption.selectedOption = productOption.Values[i].ProductSlug
                        }
                    });
                }


                $scope.currentProduct = product;
                $scope.currentProduct.availFlag = availFlag;
                switch (availFlag) {
                    case availability.UNAVAILABLE, availability.DISCONTINUED:
                        $scope.currentProduct.availability = 'Unavailable';
                        break;
                    case availability.ONORDER:
                        $scope.currentProduct.availability = 'On Order';
                        break;
                    case availability.PREORDER:
                        $scope.currentProduct.availability = 'Pre-Order';
                        break;
                    default:
                        $scope.currentProduct.availability = (product.ShowAvailableQty) ? qtyAvailable : (Number(qtyAvailable) <= 10) ? 'Only ' + qtyAvailable + ' left in stock' : 'In stock';
                }
                $scope.currentProduct.showNotify = showNotify;
                $scope.currentProduct.showAddToCart = availFlag !== availability.DISCONTINUED && showAddToCart;
                $scope.currentProduct.hasImages = hasImages;
                $scope.currentProduct.desiredQty = 1; //Math.min(product.QtyAvailable, 1);
                $scope.currentProduct.showMinQntyLmt = showMinQntyLmt;
                $scope.currentProduct.minQntyLmt = showMinQntyLmt ? product.MinimumQuantityLimit.PurchaseLimit : 1;
                $scope.currentProduct.isTemplate = showMinQntyLmt ? product.MinimumQuantityLimit.IsTemplate : false;
                $scope.currentProduct.displaySKU = product.PurchaseProductNumber !== null ? product.PurchaseProductNumber : product.ProductNumber;

                if (!!product.TemplateProductNumber)
                    $scope.currentProduct.displaySKU = product.TemplateProductNumber;

                var productTextArray = $scope.currentProduct.Text;
                for (var i = 0, len = productTextArray.length; i < len; i += 1) {
                    productTextArray[i].htmlText = $sce.trustAsHtml(productTextArray[i].Text);
                }

                //$scope.currentProduct.personalizationLites = product.PersonalizationLites;
                //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo(product);
                //$scope.currentProduct.personalizationLiteInfoInstructions = [];
                //angular.forEach(product.personalizationLites, function (litesInfo) {
                //    litesInfo.CharacterLimit = litesInfo.CharacterLimit <= 0 ? "" : litesInfo.CharacterLimit;
                //    litesInfo.isFieldTypeDropdown = litesInfo.FieldType == 'Dropdown';
                //    litesInfo.isFieldTypeValidatedText = litesInfo.FieldType == 'Text with validation';
                //});

                //$scope.currentProduct.isPersonalized = false;
                //$scope.currentProduct.PersonalizedInfo = null;
                //angular.forEach(product.Attributes, function (attribute, i) {

                //    if (attribute.Type && attribute.Type.toLowerCase() === 'productpersonlization') {
                //        $scope.currentProduct.isPersonalized = true;
                //        $scope.currentProduct.PersonalizedInfo = {};
                //        $scope.currentProduct.personalizationConfig = JSON.parse(attribute.Value);
                //    }

                //});

                //$scope.newProductSlug = {};

                //setUpImages();
                checkForShowAllOptions();
            };

            checkForShowAllOptions = function() {
                var showAllProductOptions = ECSStores.ShowAllProductOptions,
                    optionsArray = $scope.currentProduct.ChildProductOptions;

                if (showAllProductOptions) {

                    if (optionsArray) {

                        for (var i = 0, len = optionsArray.length; i < len; i += 1) {
                            if (optionsArray[i].CanShowAvailability) {
                                showChildProductTable(undefined, i);
                            }
                        }
                    } else {
                        showAllProductOptions = false;
                    }

                    $scope.showAllProductOptions = showAllProductOptions;

                }

            };

            showChildProductTable = function($event, index) {
                if ($event) {
                    $event.preventDefault();
                }


                //If we've already loaded them, just show it
                if ($scope.childProducts && $scope.childProducts.length > 0) {

                    $scope.childProductTableVisible = !$scope.isPointsValueNull;
                    //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                    //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                    showLoadingChildProducts(false);
                } else {
                    //Load the Child Options
                    showLoadingChildProducts(true);

                    //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                    //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                    var optionToShow = $scope.currentProduct.ChildProductOptions[index];
                    Products.getChildProducts(optionToShow.ParentProductSlug)
                        .then(function(response) {
                            if (response.data.length > 0) {
                                //check if we have a sort for this type of data...
                                var sortFunc = childOptionSort[optionToShow.Option.toLowerCase()];
                                if (sortFunc === undefined) {
                                    $scope.childProducts = response.data;
                                } else {
                                    $scope.childProducts = sortFunc(response.data);
                                }

                                $scope.childProductOptionShown = optionToShow.Option;
                                $scope.childProductTableVisible = !$scope.isPointsValueNull;
                            }
                            else {
                                $scope.childProductTableVisible = false;
                                Common.showMessage('danger', '606', { replace: '%product%', value: optionToShow.Option });
                            }

                            showLoadingChildProducts(false);
                        },
                            function() {
                                showLoadingChildProducts(false);
                            });
                };
            }

            showLoadingChildProducts = function(bool) {
                $scope.loadingChildProducts = bool;
            }

            $scope.getPriceToUse = function(useSellDisplayPrice, product) {
                if ((useSellDisplayPrice === "True") && product.DisplayPrice) {
                    return product.DisplayPrice;
                } else if (product.IsTieredPrice) {
                    var toReturn;
                    var tierToUse = product.PriceTiers[0];
                    product.PriceTiers.forEach(function(tier) {
                        if ($scope.totalDesiredQty >= tier.MinOrderQuantity && $scope.totalDesiredQty <= tier.MaxOrderQuantity) {
                            tierToUse = tier
                        }
                        else if ($scope.totalDesiredQty >= tier.MinOrderQuantity && tier.MaxOrderQuantity == 0 && $scope.totalDesiredQty != 0) {
                            tierToUse = tier
                        }
                    });
                    toReturn = tierToUse.Price;
                    return toReturn
                } else {
                    return product.Price;
                }
            }
            //getProductAvailability = function () {

            //    Products.getProductAvailability(product.ProductSlug)
            //        .then(function (response) {
            //            if (response.data.length > 0) {
            //                $scope.childProducts = response.data;
            //            }
            //            else {
            //                $scope.showAttributeTable = false;
            //            }
            //        });
            //};


            //getProductAvailability();

            showLoadingChildProducts(true);
            loadProduct();

        }])
    .directive('onLastRepeat', function () {
        return function (scope, element, attrs) {
            if (scope.$last) setTimeout(function () {
                scope.$emit('onRepeatLast', element, attrs);
            }, 1);
        };
    });
;angular
    .module('ecs.ctrl.securecatalog', [])
    .controller('secureCatalogCtrl', [
        '$scope',
        'Common',
        '$log',
        '$http',
        '$window',
        function ($scope, Common, $log, $http, $window) {


            /*
            This method just populates dummy data into the $scope.

            */
           
            validateSecureCatalogAccess = function (catalogSlug, form) {

                var self = this;

                if (form.$valid) {

                    if ($scope.secureCatalogCredentials.failedAttempts >= 2)
                        validateCaptchaAndPassword(catalogSlug);
                    else
                        validatePassword(catalogSlug);
                }
            },

            validateCaptchaAndPassword = function (catalogSlug) {

                var captchaApi = App.Configuration.RootPath + 'User/CaptchaValidation',
                    captchaResponse = grecaptcha.getResponse(window.ECSStoresGreCaptchaID),
                    request,
                    data = {};

                data.GRCA = captchaResponse;

                request = $http({
                    method: "post",
                    url: captchaApi,
                    data: JSON.stringify(data)
                });

                request.success(function (response) {

                    if (response && response.IsVerified) {

                        validatePassword(catalogSlug);
                    }
                    else {
                        Common.showMessage('danger', '622');
                    }

                });

                request.error(function (response) {
                    Common.showMessage('danger', '622');
                });

            },

            validatePassword = function (catalogSlug) {

                var verifyCatalogPasswordApi = App.Configuration.RootPath + 'Shop/SecureCatalog',
                                                        request;

                var data = {};
                data.Password = $scope.secureCatalogCredentials.Password;
                data.CatalogSlug = catalogSlug;

                request = $http({
                    method: "post",
                    url: verifyCatalogPasswordApi,
                    data: JSON.stringify(data)
                });

                request.success(function (response) {

                    if (response && response.IsVerified) {
                        $scope.invalidAccessCode = false;
                        //Force entire page to reload which will then load the full catalog details
                        $window.location.reload();
                    }
                    else {
                        $scope.invalidAccessCode = true;
                        $scope.secureCatalogCredentials.failedAttempts += 1;
                        grecaptcha.reset();
                    }
                });

                request.error(function (response) {
                    $scope.invalidAccessCode = true;
                    grecaptcha.reset();
                });
            },

            setDefaults = function()
            {
                $scope.invalidAccessCode = false;
                $scope.secureCatalogCredentials = {};
                $scope.secureCatalogCredentials.failedAttempts = 0;
            };
            
            setDefaults();

            $scope.validateSecureCatalogAccess = validateSecureCatalogAccess;
        }]);

;
angular
    .module('ecs.ctrl.cart', [])
    .controller('cartCtrl', [
        '$scope',
        '$rootScope',
        'Common',
        '$uibModal',
        'CartService',
        'ChiliService',
        'ShoppingCarts',
        'Customers',
        '$log',
        'ProductUrlService',
        'Config',
        '$sce',
        '$timeout',
        function ($scope, $rootScope, Common, $uibModal, CartService, ChiliService, ShoppingCarts, Customers, $log, ProductUrlService, Config, $sce, $timeout) {
            var promoCodeToApply = "",
                promoCodeVisible = false;

            var init = function (cartItemIndex) {
                $scope.sampleMessageDate = $scope.cartInfo.cart.CartItems[cartItemIndex].MessageDate;
                $scope.updateMessageDate = $sce.trustAsHtml($scope.sampleMessageDate);
            };
            $scope.init = init;

            $timeout(function () {
                $('#cartMessageDate').addClass('text-primary');
            }, 200);

            updateCartItemQty = function ($event, itemIndex) {
                if ($event) {
                    $event.preventDefault();
                }

                //build in additional information for the image paths
                var data = $scope.cartInfo.cart.CartItems[itemIndex];
                data.Url = ProductUrlService.getUrl(data.ProductSlug);
                data.Image.Url = ProductUrlService.getImageUrl(data.Image.FileName, data.Image.Extension, 'tt');

                CartService.updateCartItem(data, true);
                $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();
            },

                changeCartItemQty = function (itemIndex) {
                    $scope.cartInfo.cart.CartItems[itemIndex].hasChanged = true;
                    $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();
                },

                editPersonalizedInfo = function (item) {
                    item.editablePersonalizedInfo = JSON.parse(JSON.stringify(item.PersonalizedInfo));
                    item.PersonalizedInfo.inEditMode = true;
                },

                updatePersonalizedInfo = function (item) {

                    //build in additional information for the image paths
                    var data = item;
                    data.Url = ProductUrlService.getUrl(item.ProductSlug);
                    data.Image.Url = ProductUrlService.getImageUrl(item.Image.FileName, item.Image.Extension, 'tt');
                    data.PersonalizedInfo = JSON.parse(JSON.stringify(item.editablePersonalizedInfo));

                    CartService.updateCartItem(data, false);
                },

                saveForLater = function ($event, itemIndex) {

                    if ($event) {
                        $event.preventDefault();
                    }

                    var cartItem = $scope.cartInfo.cart.CartItems[itemIndex];
                    cartItem.Url = ProductUrlService.getUrl(cartItem.ProductSlug);
                    cartItem.Image.Url = ProductUrlService.getImageUrl(cartItem.Image.FileName, cartItem.Image.Extension, 'tt');

                    CartService.removeCartItem(cartItem);

                    $log.log('Removing Cart Item:' + cartItem.ProductNumber);

                    //Also add it the customer's favorites
                    try {
                        var customerId = $scope.user.CustomerId,
                            wishListItem = {};

                        if (customerId) {

                            wishListItem = {
                                ProductName: cartItem.ProductName,
                                ProductNumber: cartItem.ProductNumber,
                                CustomerId: customerId
                            };

                            Customers.addWishListItem(customerId, wishListItem)
                                .then(function (response) {
                                    Common.showMessageNew('success', 'None', '603', { replace: '%product%', value: cartItem.ProductName }); //"Thank you!  %product% has been added to favorites!",
                                    $log.log('Product added to wishlist.');
                                });
                        } else {
                            Common.showMessage('danger', '601'); // must be logged in to save favorites

                        }

                    } catch (e) {
                        Common.showMessage('danger'); //will display generic error message... something went wrong. 
                    }
                },

                showEmailCart = function () {
                    //$scope.$emit('showSendToFriendModal', $scope.currentProduct);
                    var modalInstance = $uibModal.open({
                        templateUrl: 'EmailCartModalContent',
                        controller: 'EmailCartModalCtrl',
                        resolve: {
                            //currentProduct: function () {
                            //    return $scope.currentProduct;
                            //}
                        }
                    });

                    modalInstance.result.then(
                        function (data) {
                            ShoppingCarts.emailCart($scope.cartInfo.cart.CartId, data)
                                .then(function (response) {
                                    Common.showMessage('success', 'Your cart has been shared successfully.');
                                    $log.log('Cart Emailed.');
                                    //var product = $scope.currentProduct;
                                    //Common.showMessageNew('share', 'SendToFriend', '604', null, {
                                    //    product: {
                                    //        name: product.Name,
                                    //        productSlug: product.ProductSlug,
                                    //        productNumber: product.ProductNumber,
                                    //        image: getProductMainImageUrl(product),
                                    //        qty: product.Qty,
                                    //        price: product.Price,
                                    //        url: ProductUrlService.getUrl(product.ProductSlug)
                                    //    },
                                    //    friend: {
                                    //        name: data.SendTo,
                                    //        email: data.SendToEmail
                                    //    },
                                    //    customer: {
                                    //        name: data.SharedBy,
                                    //        email: data.SharedByEmail
                                    //    }
                                    //});


                                });

                        });

                },

                removeCartItem = function ($event, itemIndex) {

                    if ($event) {
                        $event.preventDefault();
                    }


                    //build in additional information for the image paths
                    var data = $scope.cartInfo.cart.CartItems[itemIndex];
                    data.Url = ProductUrlService.getUrl(data.ProductSlug);
                    data.Image.Url = ProductUrlService.getImageUrl(data.Image.FileName, data.Image.Extension, 'tt');

                    CartService.removeCartItem(data);
                },

                clearCart = function () {
                    $log.log('Clearing the Cart');

                    CartService.clearCart();
                },


                applyPromoCode = function () {

                    var code = $scope.promoCodeToApply;

                    if (code && code !== '') {
                        $log.log('Applying Promo Code to Cart' + code);

                        data = {};
                        data.Code = code;
                        CartService.applyPromoCode(data).then(getCart);

                        $scope.promoCodeVisible = false;
                        $scope.promoCodeToApply = "";
                    }

                },

                addItemToCart = function (product) {
                    CartService.addCartItem({
                        Name: product.Name,
                        ProductSlug: product.ProductSlug,
                        ProductNumber: product.ProductNumber,
                        Image: Config.ProductImageBaseURL + 'MIC/MIC120558-tt.jpg',
                        Qty: product.desiredQty || 1,
                        Price: product.Price,
                        Url: ProductUrlService.getUrl(product.ProductSlug)
                    });
                    $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();

                },

                removePromoCode = function ($event, promoCodeIndex) {

                    if ($event) {
                        $event.preventDefault();
                    }

                    $log.log('Removing Promo Code:' + $scope.cartInfo.cart.PromoCodes[promoCodeIndex].Code);

                    CartService.removePromoCode($scope.cartInfo.cart.PromoCodes[promoCodeIndex])
                        .then(getCart);

                    $scope.promoCodeVisible = false;
                    $scope.promoCodeToApply = "";
                },

                getDiscountedItemPrice = function (price, discountAmount, baseCurrency, currencyExchangeRates) {

                    var locale = $scope.locale,
                        cPrice = Number(locale.exchangeRate(price, baseCurrency, currencyExchangeRates)),
                        cDiscountAmount = Number(locale.exchangeRate(discountAmount, baseCurrency, currencyExchangeRates));

                    return locale.formatCurrency(cPrice - cDiscountAmount, baseCurrency, currencyExchangeRates);
                },

                //Bread crumbs now done via URL
                //resetBreadCrumbs = function () {

                //    Common.clearCurrentCatalogName();
                //    Common.resetHistoryCounter();
                //},

                getRenderPDF = function (guid) {
                    ChiliService.getRenderPDF(guid);
                },


                getRelatedProducts = function () {
                    var self = this,
                        cart = $scope.cartInfo


                    if (!cart)
                        cart = CartService.getCart();

                    if (cart.cart && cart.cart.CartId) {

                        ShoppingCarts.getRelatedProducts($scope.cartInfo.cart.CartId)
                            .then(function (response) {
                                $scope.relatedProducts = response.data;
                            });

                    };


                },

                getCart = function () {
                    CartService.getCart()
                        .then(function (response) {
                            $scope.cartInfo = response;
                            $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();
                            getRelatedProducts();
                        });
                };

            getCart();

            //Bread crumbs now done via URL
            //$scope.resetBreadCrumbs = resetBreadCrumbs;
            $scope.quantityOptions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
            $scope.updateCartItemQty = updateCartItemQty;
            $scope.removeCartItem = removeCartItem;
            $scope.saveForLater = saveForLater;
            $scope.clearCart = clearCart;
            $scope.promoCodeVisible = promoCodeVisible;
            $scope.discountAmount = CartService.discountAmount();
            $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();
            $scope.saveForLaterVisible = !$scope.user.IsAnonymous;
            $scope.showEmailCart = showEmailCart;
            $scope.getRenderPDF = getRenderPDF;
            $rootScope.$on("onHelpMessageChange", function () {
                $scope.freeShippingHelpMessage = CartService.freeShippingHelpMessage();
            });

            $scope.promoCodeToApply = promoCodeToApply;
            $scope.applyPromoCode = applyPromoCode;
            $scope.removePromoCode = removePromoCode;
            $scope.cartItems = CartService.numberOfItems();
            $scope.cartVisible = ($scope.cartItems > 0);
            $scope.getDiscountedItemPrice = getDiscountedItemPrice;
            $scope.addItemToCart = addItemToCart;
            $scope.changeCartItemQty = changeCartItemQty;
            $scope.editPersonalizedInfo = editPersonalizedInfo;
            $scope.updatePersonalizedInfo = updatePersonalizedInfo;

            $scope.$watch(function () { return CartService.numberOfItems(); }
                , function (numberOfItems) {
                    numberOfItems = numberOfItems || 0; //In case we don't have it
                    $scope.cartItems = numberOfItems;
                    $scope.cartVisible = (numberOfItems > 0);
                }, true);

            $scope.$watch(function () { return CartService.discountAmount(); }
                , function (discountAmount) {
                    discountAmount = discountAmount || 0; //In case we don't have it
                    $scope.discountAmount = discountAmount;
                    $scope.promoCodesAppliedVisible = (discountAmount > 0);
                }, true);

        }])

    .directive('compileTemplate', function ($compile, $parse) {
        return {
            link: function (scope, element, attr) {
                var parsed = $parse(attr.ngBindHtml);
                function getStringValue() {
                    return (parsed(scope) || '').toString();
                }
            }
        }
    });
;angular
    .module('ecs.ctrl.ssoRegister', [])
    .controller('ssoRegisterCtrl', [
        '$scope',
        '$location',
        'AddressService',
        'Constants',
        'Common',
        'Objects',
        'Customers',
        'Employees',
        'StorePasses',
        '$log',
        '$window',
        '$cookieStore',

        function ($scope, $location, AddressService, Constants, Common, Objects, Customers, Employees, StorePasses, $log, $window, $cookieStore) {


            /*
            This method just populates dummy data into the $scope.

            */
            var getCustomer = function () {

                var customer = {
                    FullName: '',
                    firstName: null,
                    lastName: null,
                    Email: '',
                    EmailConfirm: '',
                    Phone: '',
                    Extension: '',
                    Fax: '',
                    VerifiedStoreCode: true,
                    BillingAddress: {
                        Name: '',
                        AddressType: '',
                        CompanyName: '',
                        Phone: '',
                        Extension: '',
                        Email: '',
                        EmailConfirm: '',
                        Address1: '',
                        Address2: '',
                        City: '',
                        State: '',
                        PostalCode: '',
                        Country: 'US',
                        TaxJurisdictionCode: ''
                    },
                    PasswordReminder: '',
                    NotificationSettings: {
                        //NewsletterEmails: false,
                        MarketingEmails: true
                    },

                    CustomerCredentials: {
                        UserName: '',
                        Password: '',
                        PasswordVerify: '',
                        IdentityProviderName: '',
                        IdentityProviderToken: ''
                    },

                    enableEmail: true


                }

                if (!$scope.user.IsAnonymous) {
                    if ($scope.user.Name) {
                        customer.FullName = $scope.user.Name;
                        $scope.fullNameDisabled = true;
                    }

                    if ($scope.user.FirstName) {
                        customer.firstName = $scope.user.FirstName;
                    }
                    if ($scope.user.LastName) {
                        customer.lastName = $scope.user.LastName;
                        $scope.fullNameDisabled = true;
                    }

                    customer.enableEmail = true;
                    if ($scope.user.Email) {
                        customer.enableEmail = false;
                        customer.Email = $scope.user.Email;
                        customer.EmailConfirm = $scope.user.Email;
                        customer.BillingAddress.Email = $scope.user.Email;
                        customer.BillingAddress.EmailConfirm = $scope.user.Email;
                    }

                    if ($scope.user.EmployeeId || $scope.user.IdPId) {
                        customer.CustomerCredentials.UserName = $scope.user.IdPId;
                        if (!customer.CustomerCredentials.UserName)
                            customer.CustomerCredentials.UserName = $scope.user.EmployeeId;
                    }
                    else {
                        //We didn't get username in the claims, so let's show it and try to default it to the email
                        customer.showUserName = true;
                        if ($scope.user.Email)
                            customer.CustomerCredentials.UserName = $scope.user.Email;
                    }

                    if ($scope.user.IdP) {
                        customer.CustomerCredentials.IdentityProviderName = $scope.user.IdP;
                        customer.CustomerCredentials.IdentityProviderToken = $scope.user.IdPId;
                    }

                }

                return customer;
            },

           setDefaults = function () {
               $scope.addressType = 'BillingAddress';

               var customer = getCustomer();
               $scope.customer = customer;

               $scope.linkedAccountCredentitals = {};
               $scope.linkedAccountCredentitals.IdentityProviderName = customer.CustomerCredentials.IdentityProviderName;
               $scope.linkedAccountCredentitals.IdentityProviderToken = customer.CustomerCredentials.IdentityProviderToken;


               AddressService.getCountries($scope,'Billing');
               AddressService.getStateOrRegions($scope, customer[$scope.addressType].Country);


           },

            onCountryChanged = function () {
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);

            },

            getNotificationSettings = function () {

                $scope.customer.NotificationSettings = $scope.customer.NotificationSettings || {};

                var notifications = [],
                        newsletterEmails = { Type: 'Newsletters', Enabled: $scope.customer.NotificationSettings.NewsletterEmails },
                        marketingEmails = { Type: 'Emails', Enabled: $scope.customer.NotificationSettings.MarketingEmails };

                if (newsletterEmails) {
                    notifications.push(newsletterEmails);
                }

                if (marketingEmails) {
                    notifications.push(marketingEmails);
                }

                return notifications;

            },

            submitForm = function (form, returnUrl) {

                $scope.submitted = true;
                $scope.returnUrl = returnUrl;

                if ($scope.customer.firstName !== null && $scope.customer.lastName !== null) {
                    if (!AddressService.testNameValidity(form, $scope.customer)) {
                        Common.showMessage('danger', '678');
                        return;
                    }
                    $scope.customer.FullName = $scope.customer.firstName + ' ' + $scope.customer.lastName;
                }

                if (!$scope.customer.DataConsent) {
                    Common.showMessage('error', 'You must accept the Data Subject Consent policy before continuing.');
                    return;
                }

                $scope.customer[$scope.addressType].Name = $scope.customer.FullName;

                $scope.customer.CompanyName = $scope.customer[$scope.addressType].CompanyName;
                $scope.customer.Phone = $scope.customer[$scope.addressType].Phone;
                $scope.customer.Extension = $scope.customer[$scope.addressType].Extension;
                $scope.customer.Email = $scope.customer[$scope.addressType].Email;
                $scope.customer.EmailConfirm = $scope.customer[$scope.addressType].EmailConfirm;
                //$scope.customer.DataConsent = $scope.customer[$scope.addressType].DataConsent;

                //Generate random password
                $scope.customer.CustomerCredentials.Password = Math.random().toString(36).slice(-16);
                $scope.customer.PasswordReminder = 'SSO';

                //Get any roles from the user to provide to the API
                if (!!$scope.user.Roles && $scope.user.Roles.length > 0)
                    $scope.customer.Roles = $scope.user.Roles;

                if (form.$valid) {
                    $scope.$scrollTop();
                    $scope.customer.NotificationSettings = getNotificationSettings();

                    //Make sure the state is not set if the country doesn't have states
                    if ($scope.states.length === 0) {
                        $scope.customer[$scope.addressType].State = "";
                    }

                    Common.showLoader('106');

                    Customers.createCustomer($scope.customer)
                      .then(function (response) {
                          $log.log('Customer created!');

                          $scope.customer = response.data;
                          $scope.isRedirectToLogin = true;
                          loginSSOCustomer(returnUrl, response.data);
                      });


                } else {
                    Common.showMessage('danger', '615');
                }
            },

            linkExistingAccount = function (form, returnUrl) {

                $scope.submitted = true;
                $scope.returnUrl = returnUrl;

                
                if (form.$valid) {
                    $scope.$scrollTop();
                    
                    Common.showLoader('128');

                    $scope.linkAttempts++;
                    Customers.linkSSO($scope.linkedAccountCredentitals)
                      .then(function (response) {
                          $log.log('Customer created!');

                          $scope.customer = response.data;
                          $scope.isRedirectToLogin = true;
                          loginSSOCustomer(returnUrl, response.data);
                      });


                } else {
                    Common.showMessage('danger', '615');
                }
            }

            showLinkAccount = function () {
                $scope.submitted = false;
                $scope.toggleSSOMigrationInstructions = true;
            },

            showRegistration = function () {
                $scope.submitted = false;
                $scope.toggleSSOMigrationInstructions = true;
                $scope.isSSOMigration = false;
            }

            cancelRegistration = function (returnUrl, customer) {

                var redirectPathBuilder = [App.Configuration.RootPath, "Home/CancelNewSSO"];
                $window.location.href = redirectPathBuilder.join('');

            },

            loginSSOCustomer = function (returnUrl, customer) {

                //create a cookie to indicate we've registered this user
                //$cookieStore.put("regssocid", customer.CustomerId);
                //Cookies we're working because AngularJS cookie defaults the path of the cookie to the current path.
                //It was preventing the .NET MVC code from loading up the cookie. Instead pass this to a specific MVC controller and
                //we'll set it there
                var redirectPathBuilder = [App.Configuration.RootPath, 'Home/SigninNewSSO?cid=', customer.CustomerId];
                $window.location.href = redirectPathBuilder.join('');

            },


            updateTaxJurisdictions = function (reset, form) {

                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            };


            setDefaults();

            $scope.activeForm = 'ssoRegForm';

            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.isRedirectToLogin = false;
            $scope.isSSOMigration = true; //default to true, we'll only use this if store is setup for SSO Migration
            $scope.toggleSSOMigrationInstructions = false;
            $scope.linkAttempts = 0;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;
            $scope.submitForm = submitForm;
            $scope.linkExistingAccount = linkExistingAccount;
            $scope.preventDefault = Common.preventDefault;
            $scope.cancelRegistration = cancelRegistration;
            $scope.showLinkAccount = showLinkAccount;
            $scope.showRegistration = showRegistration;
            $scope.testNameValidity = AddressService.testNameValidity;
            $scope.showMarketingEmails = $scope.store.Functionality.MarketingEmails;
            $scope.showNewsletterEmails = $scope.store.Functionality.NewsletterEmails;

        }]);



/*


Create a new MVC View for the Register New User page.
 
User should enter:
 
Contact Info (Name, Email, Phone, Fax)
Billing Address (Addr1, Addr2, City, Country, State, Postal Code, County/Jurisdiction)
UserLogin Info (username, password 2x, password reminder, notification prefs)
 
Use the same UI from the Checkout - Register page
 
Logic.
 
- done - Country should default to US and the US states are loaded by default. 
- done - If Store is not US only, then the Country can be a drop down and the States are refreshed when the country is selected
- done - By default the County/Jurisdiction dropdown is not visible. After the user enters both the City and PostalCode and country is US, get the TaxJurisdictions for the City and Postal Code via the API. If more than 1 jurisdiction is returned, show the County/Jurisdiction drop down

- not done - do not implement (per andy) - After the username is entered, should validate the username is available for the store code - do not implement. (per andy)

- done - Password must be entered twice and match.
- Show Notification Preferences for MarketingEmail and NewsletterEmails if enabled for store. If yes, these preferences should default to checked/true.
 
- Create a new Customer with the information provided via the API.
- If Customer is successfully created, login the new customer via Identity Server



*/;
angular
    .module('ecs.ctrl.storeLocation', [])
    .controller('storeLocationCtrl', [
        '$scope',
        '$window',
        'Customers',
        function ($scope, $window, Customers) {
            
            var getLocations = function () {
                Customers.getLocations($scope.user.CustomerId)
                .then(function (response) {

                    $scope.storeLocations = response.data;
                });

            };

            getLocations();

            
        }]);
;angular
    .module('ecs.ctrl.sendToFriendCtrl', [])
    .controller('SendToFriendModalCtrl', [
                '$scope',
                'Products',
                'Common',
                '$log',
                'currentProduct',
            function ($scope, Products, Common, $log, currentProduct) {

                var sendToFriend = function (form, scope) {
                    scope.sendToFriendSubmitted = true;
                    if (form.$valid) {

                            scope.sendToFriendError = false;
                            data = {};
                            data.ProductSlug = scope.currentProduct.ProductSlug;
                            data.ShareType = 'Email';
                            data.SharedBy = $scope.user.Name;
                            data.SharedByEmail = $scope.user.Email;
                            data.SendTo = scope.sendToFriendToName;
                            data.SendToEmail = scope.sendToFriendToEmail;
                            data.Message = scope.sendToFriendComments;
                            data.CustomerId = $scope.user.CustomerId;
                            data.CopySharer = scope.CopySharer;

                            $scope.$close(data);

                        }
                        else {
                            scope.sendToFriendError = true;
                        }
                    },

                    sendToFriendDefaultComment = function () {
                        //TO DO: determine project multilingual support and modify this to return message in correct language code
                        try {
                            return "Hey, thought you'd like to check out this product, " + $scope.currentProduct.Name + ".";
                        }
                        catch (err) {
                            //prevent any problems with the current product from interfering with the feature
                            return "Hey, thought you'd like to check out this product.";
                        }
                    },

                    resetSendToFriend = function (scope) {
                        scope.sendToFriendToEmail = "";
                        scope.sendToFriendToName = "";
                        scope.sendToFriendComments = sendToFriendDefaultComment();
                        scope.shareForm.$setPristine();
                        scope.shareForm.$dirty = false;
                        scope.sendToFriendSubmitted = false;
                        scope.sendToFriendError = false;
                    },

                    cancel = function (form) {
                        $scope.$dismiss();
                    },

                    initForm = function () {
                        Common.focusElement('#SendToName');
                    },

                    self = this;

                    $scope.currentProduct = currentProduct;
                    $scope.resetSendToFriend = resetSendToFriend;
                    $scope.sendToFriend = sendToFriend;
                    $scope.cancel = cancel;

                    $scope.sendToFriendVisible = false;
                    $scope.sendToFriendError = false;
                    $scope.sendToFriendSubmitted = false;
                    $scope.sendToFriendToName = "";
                    $scope.sendToFriendToEmail = "";
                    $scope.sendToFriendComments = sendToFriendDefaultComment();

                    initForm();
               

                /*
                remove_showSendToFriendListener = $rootScope.$on('showSendToFriendModal', function (event, currentProduct) {
                    showModal(currentProduct);
                });

                */
            }]);;angular
    .module('ecs.ctrl.emailCartCtrl', [])
    .controller('EmailCartModalCtrl', [
                '$scope',
                'Common',
                '$log',
            function ($scope, Common, $log) {

                var emailCart = function (form, scope) {
                    scope.emailCartSubmitted = true;
                    if (form.$valid) {

                            scope.emailCartError = false;
                            data = {};
                            data.Message = scope.emailCartComments;
                            data.SendTo = scope.emailCartToName;
                            data.SendToEmail = scope.emailCartToEmail;
                            data.SharedBy = $scope.user.Name;
                            data.SharedByEmail = $scope.user.Email;
                            data.CustomerId = $scope.user.CustomerId;


                            $scope.$close(data);

                        }
                        else {
                        scope.emailCartError = true;
                        }
                    },

                    emailCartDefaultComment = function () {
                        return "Hey, check out my cart";
                    },

                    resetEmailCart = function (scope) {
                        scope.emailCartToEmail = "";
                        scope.emailCartToName = "";
                        scope.emailCartComments = emailCartDefaultComment();
                        scope.shareForm.$setPristine();
                        scope.shareForm.$dirty = false;
                        scope.emailCartSubmitted = false;
                        scope.emailCartError = false;
                    },

                    cancel = function (form) {
                        $scope.$dismiss();
                    },

                    initForm = function () {
                        Common.focusElement('#SendToName');
                    },

                    self = this;

                    $scope.resetEmailCart = resetEmailCart;
                    $scope.emailCart = emailCart;
                    $scope.cancel = cancel;

                    $scope.emailCartVisible = false;
                    $scope.emailCartError = false;
                    $scope.emailCartSubmitted = false;
                    $scope.emailCartToName = "";
                    $scope.emailCartToEmail = "";
                    $scope.emailCartComments = emailCartDefaultComment();

                    initForm();
               

                /*
                remove_showSendToFriendListener = $rootScope.$on('showSendToFriendModal', function (event, currentProduct) {
                    showModal(currentProduct);
                });

                */
            }]);;angular
    .module('ecs.ctrl.product.search', [])
    .controller('productSearchCtrl', [
        '$scope',
        'Common',
        '$location',
        '$rootScope',
        'EcsResource',
        'CartService',
        'Products',
        '$timeout',
        '$log',
        '$window',
        function ($scope, Common, $location, $rootScope, EcsResource, CartService, Products, $timeout, $log, $window) {

            var getSearchProducts = function () {
                return ECSStores.ProductSearch.SearchResult;
            },

                init = function () {

                    clearInterval(scrollListenerInterval);

                    var searchResults = getSearchProducts();

                    $timeout(function () {
                        $rootScope.$broadcast('loader_hide');
                    }, 1000)

                    $scope.isPriceSearch = ECSStores.ProductSearch.IsPriceSearch;
                    $scope.catalog = ECSStores.ProductSearch.Catalog;
                    $scope.priceFilter = ECSStores.ProductSearch.PriceFilter;
                    $scope.searchTerm = ECSStores.ProductSearch.SearchTerm;
                    if ($scope.isPriceSearch) //Price search doesn't search by search term
                        $scope.searchTerm = '';

                    if (searchResults.ShouldRedirect) {
                        //If we got here something is not right, just show no search results
                        $scope.searchProducts = searchResults.Products;
                        $scope.noResults = true;
                        $scope.showButton = false;
                    }
                    else {
                        $scope.facets = searchResults.Facets;
                        facetsObj = Common.updateFacetsObj($scope);

                        $scope.searchProducts = searchResults.Products;
                        $scope.noResults = true;
                        $scope.showButton = false;

                        if (searchResults) {

                            var products = searchResults.Products;
                            //If we have any results, don't show the message
                            if (products.length !== 0) {
                                $scope.noResults = false;
                            }
                            //If we have 25, show the "More" button
                            if (products.length === ECSStores.ProductSearch.RecordsToReturn) {
                                var product = products[products.length - 1];

                                $timeout(function () {
                                    setScrollListener(product.ProductNumber);
                                }, 500);

                                //$scope.showButton = true;
                            }
                        }
                    }
                },

                sortItems = function ($event, order) {
                    getItems($event, order, true);
                },

                getItems = function ($event, order, sort, append) {
                    clearInterval(scrollListenerInterval);

                    if ($event) {
                        $event.preventDefault();
                    }

                    var searchProducts = $scope.searchProducts,
                        skip = skip || 0,
                        top = sort ? searchProducts.length : ($scope.isPriceSearch ? 1000 : 25);

                    //If we're appending the results (i.e. get next 25, then skip all the products we've retrieved.
                    if (append) {
                        skip = searchProducts.length;
                    }

                    //JC - The scrollToTop was resetting the page after loading more records upon scroll down
                    //$scope.$scrollTop($('#sidebar').offset().top);
                    $rootScope.$broadcast('loader_show', '103');

                    Products.searchProducts({
                        'skip': skip,
                        'top': top,
                        'pricelevel': '01',
                        'orderBy': order || $scope.sortOrder,
                        'q': 'keyword=' + $scope.searchTerm + Common.getFacets($scope)

                    }).then(function (response) {

                        $scope.searchProducts = append ? searchProducts.concat(response.data.Products) : response.data.Products;
                        $scope.facets = response.data.Facets;
                        $scope.sortOrder = order || $scope.sortOrder;

                        if (response.data.Products.length < 25 || $scope.isPriceSearch) {
                            //$scope.showButton = false;
                        }
                        else {
                            var products = $scope.searchProducts;

                            $timeout(function () {
                                setScrollListener(products[products.length - 1].ProductNumber);
                            }, 500);

                            //$scope.showButton = true;
                        }
                    })
                },
                showProductGalleryInfo = function(event, product) {
                    $scope.productGalleryInfo.position = {
                            top: event.clientY + 'px',
                            left: event.clientX + 'px'
                        };

                    $scope.productGalleryInfo.product = product;
                    $scope.productGalleryInfo.showPopover = showStockOnGalleryView == 'True';

                },

                /*
    
                Method setScrollListener
                
                @param id is the ProductNumber property of the last product in the list. 
                
                ProductSearch.html has a repeater that assigns the ProductNumber as the id attribute for each
                product in the list.  In the method below the ProductNumber of the last item in the current 
                list of products is passed in and jquery is used to fetch the DOM elemenet with that id. 
                An interval is then set up to check every 250ms to see if the user has scrolled to the top 
                value of this element, plus a buffer.  Once its within the buffer area the call to getNext is 
                made and the interval is cancelled.
    
                */
                scrollListenerInterval,
                setScrollListener = function (id) {
                    var target = $('#' + id),
                        buffer = 750; //num of pixels above the element with this id to trigger getNext()

                    if (target && target.length > 0) {
                        scrollListenerInterval = setInterval(function () {

                            var isHasProductSearch = window.location.hash.toLowerCase().indexOf("product-search");
                            if (isHasProductSearch == -1)
                                clearInterval(scrollListenerInterval);
                            else {
                                if (target.offset().top !== 0 && $(window).scrollTop() + buffer >= target.offset().top) {
                                    getItems(null, null, false, true); //Load more...
                                }
                            }
                        }, 1000);
                    }
                },

                getSortLabel = function () {

                    var sortLabels = {
                        'NEWEST': 'Newest',
                        'PRICELOW-HI': 'Lowest Price',
                        'PRICEHI-LOW': 'Highest Price',
                        'NAMEA-Z': 'Alphabetical', 
                        'RELEVANCE': 'Relevance'
                    }

                    return sortLabels[$scope.sortOrder] || 'Sort Chosen';
                },

                lookForFacets = function () {
                    $timeout(function () {
                        if ($(".facets .facet-title").filter(':visible').length !== 0)
                            $scope.noFacetsVisible = false;
                        else
                            $scope.noFacetsVisible = $(".facet-value").filter(':visible').length === 0;
                    }, 100);
                },

                refineSearch = function (scope, facetToRemove, value) {
                    Common.refineSearch($scope, facetToRemove, value);
                };

            $scope.$on('onRepeatLast', lookForFacets);

            $scope.showButton = true;
            $scope.noResults = false;
            $scope.sortItems = sortItems;
            $scope.getItems = getItems;
            $scope.sortOrder = 'RELEVANCE';

            $scope.refineSearch = refineSearch;
            $scope.activeFacets = [];
            $scope.facetHidden = {};
            $scope.toggleFacet = Common.toggleFacet;
            $scope.changeFocus = Common.changeFocus;

            $scope.getSortLabel = getSortLabel;
            $scope.showProductGalleryInfo = showProductGalleryInfo;
            $scope.productGalleryInfo = {
                templateUrl: 'ProductGalleryModalContent.html',
                position: { top: 0, left: 0 },
                product: null,
                showPopover: false
            };

            init();

        }])
    .controller('ProductGalleryInfoCtrl', [
        '$scope',
        '$log',
        '$sce',
        'Products',
        function ($scope, $log, $sce, Products) {

            //$scope.multipleBudgetCodes = false;
            //var firstBudgetCode = (balances.length > 0) ? balances[0].BudgetCode : '';
            //for (i = 0; i < balances.length; i++) {
            //    balances[i].descriptionHTML = $sce.trustAsHtml(balances[i].BudgetDescription);
            //    if (firstBudgetCode !== balances[i].BudgetCode)
            //        $scope.multipleBudgetCodes = true;
            //}
            const availability = {
                AVAILABLE: "Available",
                UNAVAILABLE: "Unavailable",
                ONORDER: "On Order",
                DISCONTINUED: "Discontinued",
                PREORDER: "Pre-Order",
            }
            var childOptionSort = [];
            //var imageZoomOptions = {};

            childOptionSort['color'] = function (arr) {
                return arr.sort(function (a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };
            childOptionSort['media'] = function (arr) {
                return arr.sort(function (a, b) {
                    if ((a.Name || a.Value) < (b.Name || b.Value)) return -1;
                    if ((a.Name || a.Value) > (b.Name || b.Value)) return 1;
                    return 0;
                })
            };

            $scope.childProducts = [];



            loadProduct = function () {
                fetchProduct($scope.productGalleryInfo.product.ProductSlug);

                //var currentProduct = getCurrentProduct();

                ////check to see if we have current product data, and if that product data
                ////is still valid. Anything over 20 seconds old is cached on the page.
                //if (currentProduct) {
                //    $log.log('Product loaded from page cache');

                //    setUpProductData(currentProduct);
                //} else {
                //    $log.log('Product fetch from API');

                //    fetchProduct(getProductSlug());
                //}
            };

            fetchProduct = function (productSlug) {

                Products.getProduct({ ':sku': productSlug })
                    .then(function (response) {
                        setUpProductData(response.data);
                    });
            };

            getPointsConfig = function () {
                return ECSStores.PointsConfig || {};
            };

            setUpProductData = function (product) {
                var pointsConfig = getPointsConfig();
                $scope.availability = availability;
                $scope.isPointsValueNull = pointsConfig != null && pointsConfig.PointsValue && product.PointsValue == null;
                var qtyAvailable = product.QtyAvailable,
                    //Show the Notify Me option if there is no quantity, the item is not discontinued, and it is a product that can't be backordered
                    showNotify = Number(qtyAvailable) <= 0 && !product.Discontinued && !product.AllowBackOrder && !product.IsPreOrder,

                    //Show Add to Cart if Allow Back Order is true or if the qty available is > 0
                    showAddToCart = (product.AllowBackOrder || Number(qtyAvailable) > 0 || product.IsPreOrder),

                    //Set the avail flag. 1 = Unavailable, 2 = On Order, 3 = Discontinued
                    availFlag = $scope.isPointsValueNull ? availability.DISCONTINUED : Number(qtyAvailable) <= 0 ? (!product.Discontinued ? (showNotify ? availability.UNAVAILABLE : availability.ONORDER) : availability.DISCONTINUED) : availability.AVAILABLE,

                    hasImages = product.Images.length > 0,
                    hasOptions = product.ChildProductOptions && product.ChildProductOptions.length > 0,
                    //relatedProducts = getRelatedProducts(),
                    showMinQntyLmt = (product.MinimumQuantityLimit != undefined);

                if (product.IsPreOrder)
                    availFlag = availability.PREORDER;

                //if (relatedProducts) {
                //    setUpRelatedProductData(relatedProducts);
                //} else {
                //    loadRelatedProducts(product);
                //};

                var isApparel = false;
                if (hasOptions) {
                    angular.forEach(product.ChildProductOptions, function (productOption, i) {
                        //check if we have a sort for this type of data...
                        var sortFunc = childOptionSort[productOption.Option.toLowerCase()];
                        if (sortFunc !== undefined) {
                            productOption.Values = sortFunc(productOption.Values);
                        }
                        //check if this is the current product we are viewing.
                        angular.forEach(productOption.Values, function (option, i) {
                            if (option.IsThisProduct) {
                                productOption.selectedOption = option.ProductSlug;
                                option.selectedIndex = i;
                            }

                            if (option.Option.toLowerCase() === 'media') {
                                $scope.isMedia = true;
                            } else {
                                $scope.isMedia = false;
                            }

                            if (option.Option.toLowerCase() === 'size') {
                                isApparel = true;
                            }

                        });
                        if (!productOption.selectedOption) {
                            productOption.selectedOption = productOption.Values[i].ProductSlug
                        }
                    });
                }


                $scope.currentProduct = product;
                $scope.currentProduct.availFlag = availFlag;
                switch (availFlag) {
                    case availability.UNAVAILABLE, availability.DISCONTINUED:
                        $scope.currentProduct.availability = 'Unavailable';
                        break;
                    case availability.ONORDER:
                        $scope.currentProduct.availability = 'On Order';
                        break;
                    case availability.PREORDER:
                        $scope.currentProduct.availability = 'Pre-Order';
                        break;
                    default:
                        $scope.currentProduct.availability = (product.ShowAvailableQty) ? qtyAvailable : (Number(qtyAvailable) <= 10) ? 'Only ' + qtyAvailable + ' left in stock' : 'In stock';
                }
                $scope.currentProduct.showNotify = showNotify;
                $scope.currentProduct.showAddToCart = availFlag !== availability.DISCONTINUED && showAddToCart;
                $scope.currentProduct.hasImages = hasImages;
                $scope.currentProduct.desiredQty = 1; //Math.min(product.QtyAvailable, 1);
                $scope.currentProduct.showMinQntyLmt = showMinQntyLmt;
                $scope.currentProduct.minQntyLmt = showMinQntyLmt ? product.MinimumQuantityLimit.PurchaseLimit : 1;
                $scope.currentProduct.isTemplate = showMinQntyLmt ? product.MinimumQuantityLimit.IsTemplate : false;
                $scope.currentProduct.displaySKU = product.PurchaseProductNumber !== null ? product.PurchaseProductNumber : product.ProductNumber;

                if (!!product.TemplateProductNumber)
                    $scope.currentProduct.displaySKU = product.TemplateProductNumber;

                var productTextArray = $scope.currentProduct.Text;
                for (var i = 0, len = productTextArray.length; i < len; i += 1) {
                    productTextArray[i].htmlText = $sce.trustAsHtml(productTextArray[i].Text);
                }

                //$scope.currentProduct.personalizationLites = product.PersonalizationLites;
                //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo(product);
                //$scope.currentProduct.personalizationLiteInfoInstructions = [];
                //angular.forEach(product.personalizationLites, function (litesInfo) {
                //    litesInfo.CharacterLimit = litesInfo.CharacterLimit <= 0 ? "" : litesInfo.CharacterLimit;
                //    litesInfo.isFieldTypeDropdown = litesInfo.FieldType == 'Dropdown';
                //    litesInfo.isFieldTypeValidatedText = litesInfo.FieldType == 'Text with validation';
                //});

                //$scope.currentProduct.isPersonalized = false;
                //$scope.currentProduct.PersonalizedInfo = null;
                //angular.forEach(product.Attributes, function (attribute, i) {

                //    if (attribute.Type && attribute.Type.toLowerCase() === 'productpersonlization') {
                //        $scope.currentProduct.isPersonalized = true;
                //        $scope.currentProduct.PersonalizedInfo = {};
                //        $scope.currentProduct.personalizationConfig = JSON.parse(attribute.Value);
                //    }

                //});

                //$scope.newProductSlug = {};

                //setUpImages();
                checkForShowAllOptions();
            };

            checkForShowAllOptions = function () {
                var showAllProductOptions = ECSStores.ShowAllProductOptions,
                    optionsArray = $scope.currentProduct.ChildProductOptions;

                if (showAllProductOptions) {

                    if (optionsArray) {

                        for (var i = 0, len = optionsArray.length; i < len; i += 1) {
                            if (optionsArray[i].CanShowAvailability) {
                                showChildProductTable(undefined, i);
                            }
                        }
                    } else {
                        showAllProductOptions = false;
                        showLoadingChildProducts(false);
                    }
                    $scope.showAllProductOptions = showAllProductOptions;
                }
            };

            showChildProductTable = function ($event, index) {
                if ($event) {
                    $event.preventDefault();
                }


                //If we've already loaded them, just show it
                if ($scope.childProducts && $scope.childProducts.length > 0) {

                    $scope.childProductTableVisible = !$scope.isPointsValueNull;
                    //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                    //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                    showLoadingChildProducts(false);
                } else {
                    //Load the Child Options
                    showLoadingChildProducts(true);

                    //In case there is already values in Personalization Lite, reset it after shifting from simple to multiple order
                    //$scope.currentProduct.personalizationLiteInfo = getDefaultPersonalizationLiteInfo($scope.currentProduct);
                    var optionToShow = $scope.currentProduct.ChildProductOptions[index];
                    Products.getChildProducts(optionToShow.ParentProductSlug)
                        .then(function (response) {
                            if (response.data.length > 0) {
                                //check if we have a sort for this type of data...
                                var sortFunc = childOptionSort[optionToShow.Option.toLowerCase()];
                                if (sortFunc === undefined) {
                                    $scope.childProducts = response.data;
                                } else {
                                    $scope.childProducts = sortFunc(response.data);
                                }

                                $scope.childProductOptionShown = optionToShow.Option;
                                $scope.childProductTableVisible = !$scope.isPointsValueNull;
                            }
                            else {
                                $scope.childProductTableVisible = false;
                                Common.showMessage('danger', '606', { replace: '%product%', value: optionToShow.Option });
                            }

                            showLoadingChildProducts(false);
                        },
                        function () {
                            showLoadingChildProducts(false);
                        });
                };
            }

            showLoadingChildProducts = function (bool) {
                $scope.loadingChildProducts = bool;
            }

            $scope.getPriceToUse = function (useSellDisplayPrice, product) {
                if ((useSellDisplayPrice === "True") && product.DisplayPrice) {
                    return product.DisplayPrice;
                } else if (product.IsTieredPrice) {
                    var toReturn;
                    var tierToUse = product.PriceTiers[0];
                    product.PriceTiers.forEach(function (tier) {
                        if ($scope.totalDesiredQty >= tier.MinOrderQuantity && $scope.totalDesiredQty <= tier.MaxOrderQuantity) {
                            tierToUse = tier
                        }
                        else if ($scope.totalDesiredQty >= tier.MinOrderQuantity && tier.MaxOrderQuantity == 0 && $scope.totalDesiredQty != 0) {
                            tierToUse = tier
                        }
                    });
                    toReturn = tierToUse.Price;
                    return toReturn
                } else {
                    return product.Price;
                }
            }
            //getProductAvailability = function () {

            //    Products.getProductAvailability(product.ProductSlug)
            //        .then(function (response) {
            //            if (response.data.length > 0) {
            //                $scope.childProducts = response.data;
            //            }
            //            else {
            //                $scope.showAttributeTable = false;
            //            }
            //        });
            //};


            //getProductAvailability();

            showLoadingChildProducts(true);
            loadProduct();

        }]).directive('aDisabled', function () {
            return {
                compile: function (tElement, tAttrs, transclude) {
                    //Disable ngClick
                    tAttrs["ngClick"] = "!(" + tAttrs["aDisabled"] + ") && (" + tAttrs["ngClick"] + ")";

                    //Toggle "disabled" to class when aDisabled becomes true
                    return function (scope, iElement, iAttrs) {
                        scope.$watch(iAttrs["aDisabled"], function (newValue) {
                            if (newValue !== undefined) {
                                iElement.toggleClass("disabled", newValue);
                            }
                        });

                        //Disable href on click
                        iElement.on("click", function (e) {
                            if (scope.$eval(iAttrs["aDisabled"])) {
                                e.preventDefault();
                            }
                        });
                    };
                }
            };
        });;angular
    .module('ecs.ctrl.microsoftLanding', [])
    .controller('microsoftLandingCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        '$log',
        '$window',
        '$rootScope',
        function ($scope, $location, EcsResource, $log, $window, $rootScope) {
           
            var submitForm = function (form, idProvider) {

                $scope.submitted = true;
                if (form.$valid) {
                    if (/@microsoft.com\s*$/i.test($scope.userEmailAddress)) {
                        redirectToSSO(idProvider);
                    }
                    else {
                        $scope.userSelectionVisible = true;
                        $scope.userEmailVisible = false;
                    }

                }
            },

            redirectToSSO = function (idProvider) {
                var redirectPathBuilder = ['/Microsoft/Home/Logon/?storeCode=MIC&idProvider=', idProvider, '&remember=true'];
                $window.location.href = redirectPathBuilder.join("");

            }

            start = function () {
                $('#login-main-bg').removeClass('hidden');
            };

            $scope.submitForm = submitForm;
            $scope.submitted = false;
            $scope.userSelectionVisible = false;
            $scope.userEmailVisible = true;
            $scope.userEmailAddress = ""

            start();
        }]);;angular
    .module('ecs.ctrl.msLinkedIn', [])
    .controller('msLinkedInCtrl', [
        '$cookies',
        '$timeout',
        'Employees',
        'Common',
        '$scope',
        function ($cookies, $timeout, Employees, Common, $scope) {

            $scope.linkedInUrl = ' ';


            getEmployeeDetails = function () {
                var curUser = $scope.user;

                if (curUser.IsEmployee && curUser.EmployeeId) {
                    Employees.getEmployee(curUser.EmployeeId)
                       .then(function (response) {
                           $scope.linkedInUrl = response.data.OrganizationInfo.BusinessReasonCode;
                       });
                }
                else {
                    $scope.linkedInUrl = ' ';
                }

            };

            getEmployeeDetails();






        }]);;
angular
    .module('ecs.ctrl.header', [])
    .controller('headerCtrl', [
        '$rootScope',
        '$log',
        '$scope',
        '$window',
        '$location',
        '$anchorScroll',
        '$uibModal',
        'Common',
        'CartService',
        'BudgetsService',
        'Customers',
        'CheckoutService',
        '$cookies',
        '$timeout',
        function ($rootScope, $log, $scope, $window, $location, $anchorScroll, $uibModal, Common, CartService, BudgetsService, Customers, CheckoutService, $cookies, $timeout) {

            var mobileLinks = undefined,

                toggleMobileMenu = function () {
                    $scope.showMobileMenu = !$scope.showMobileMenu;

                    var $menu = $('#main-menu');
                    var $mainMenuState = $('#main-menu-state');
                    if ($menu.length > 0) {
                        //New Smart menus
                        if ($scope.showMobileMenu) {
                            $mainMenuState[0].checked = true;
                        } else {
                            $mainMenuState[0].checked = false;
                        }
                    }
                    else {
                        //Old Accordian Menu
                        if (!mobileLinks) {
                            mobilelinks = $('#mobile-nav a').not('.accordion-toggle');
                            mobilelinks.click(toggleMobileMenu);
                        }
                    }

                };

            $scope.$window = $window;
            $scope.signInVisible = $scope.user.IsAnonymous;
            $scope.signOutVisible = !$scope.signInVisible;
            $scope.cartVisible = true; //For now, this is always true
            CartService.loadCart();
            $scope.cartItems = CartService.numberOfItems();
            $scope.checkOutVisible = ($scope.cartItems > 0); //Show the Checkout if we have any cart items
            $scope.searchTerm = '';
            $scope.eligibleEPP = false;
            $scope.showBalances = false;
            $scope.showMulipleBudgetsLink = false;
            $scope.realTimeBalances = false;
            $scope.showCookieWarningMessage = false;
            $scope.showAlertMessage = false;
            $scope.showGDPRWarningMessage = false;

            $scope.$on('$locationChangeStart', function () {
                if ($scope.showMobileMenu) {
                    toggleMobileMenu();
                }
            });

            $scope.$watch(function () { return CartService.numberOfItems(); }
                , function (numberOfItems) {
                    numberOfItems = numberOfItems || 0; //In case we don't have it
                    $scope.cartItems = numberOfItems;
                    $scope.checkOutVisible = (numberOfItems > 0);

                }, true);


            $scope.goToHome = function () {
                $location.path('/');
            };

            $scope.quickSearch = function ($event) {

                if ($event) {
                    $event.preventDefault();
                }
                var str = new String($scope.searchTerm),
                    qsSplit = $location.path().split('/'),
                    lastchar = str.slice(-1);
                while (lastchar === ".") {
                    str = str.slice(0, -1);
                    lastchar = str.slice(-1);
                }
                $scope.searchTerm = str;
                str = str.trim();
                if (str !== '') {
                    if (qsSplit[qsSplit.length - 1].toString() !== str) {
                        $rootScope.$broadcast('loader_show', '102');
                    }

                    var d = new Date().getTime();
                    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                        var r = (d + Math.random() * 16) % 16 | 0;
                        d = Math.floor(d / 16);
                        return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                    });


                    $scope.$scrollTop();
                    var redirectPathBuilder = ['product-search/', uuid, '/', str];
                    $location.path(redirectPathBuilder.join(''));

                    //Bread crumbs now done via URL
                    //Common.setCurrentCatalogName('Search');
                    //Common.resetHistoryCounter(); //each search requires a reset of this counter in order to return to individual searches
                    $scope.searchTerm = '';
                }
            };

            $scope.markCookieWarningMessageAsViewed = function () {
                var expDate = new Date();
                expDate.setDate(expDate.getDate() + 30);
                $cookies.put('Hvcwm', new Date(), {
                    expires: expDate
                });

                showPrivacyMessage(false);
            };

            $scope.markAlertMessageAsViewed = function () {
                let expDate = new Date();
                expDate.setDate(expDate.getDate() + 1);
                $cookies.put('Awm', new Date(), {
                    expires: expDate
                });

                showAlertMessage(false);
            };

            $scope.scrollToMainContent = function () {
                $anchorScroll('mainContent');
                $('#mainContent a[data-accessibility-id="skip-to-main-accessibility"]').attr('tabIndex', 0).focus();
            };

            var classes = ['no-class', 'fa-chevron-down', 'menu', 'menu-container'],

                classNotInList = function (classList) {

                    for (var found = false, i = 0, len = classes.length; i < len; i += 1) {

                        if (classList.contains(classes[i])) {
                            found = true;
                            break;
                        }
                    }

                    return found;

                },

                closeMenuWhenClickingElsewhere = function (event, callbackOnClose) {

                    var clickedElement = event.target;
                    if (!clickedElement) return;

                    var elementClasses = clickedElement.classList,
                        clickedOnMenu = classNotInList(elementClasses) || (clickedElement.parentElement !== null && clickedElement.parentElement.classList.contains('menu-category'));

                    if (!clickedOnMenu) {
                        callbackOnClose();
                        return;
                    }

                },

                updateAfterOrder = function () {
                    getEmployeeBalance(true);
                    //This will reset the shopping cart after the order has been placed
                    CartService.loadEmptyCart();
                    if (Common.getCartInitialized()) {
                        CheckoutService.clearCheckoutCart();
                        Common.clearCartInitialized();
                        Common.clearStoredShippingData();
                    }
                },

                showPrivacyMessage = function (bool) {
                    $scope.showCookieWarningMessage = bool;
                },

                showAlertMessage = function (bool) {
                    $scope.showAlertMessage = bool;
                },

                updateUserName = function () {
                    if (!$scope.user.IsAnonymous && $scope.user.CustomerId) {
                        Customers.getCustomer($scope.user.CustomerId)
                            .then(function (response) {
                                $scope.userName = response.data.FullName
                                if (!response.data.DataConsent) {
                                    showPrivacyMessage(true);
                                    $scope.showGDPRWarningMessage = true;
                                }
                            });
                    }
                },

                refreshCart = function () {
                    CartService.loadCart(true);
                    if (Common.getCartInitialized())
                        CheckoutService.clearCheckoutCart();
                },

                start = function () {
                    getEmployeeBalance(false);
                    $('#main-header').removeClass('hidden');

                    if (!$cookies.get('Hvcwm')) {
                        $timeout(function () {
                            showPrivacyMessage(true);
                        }, 2000);
                    }

                    if (!$cookies.get('Awm')) {
                        $timeout(function () {
                            showAlertMessage(true);
                        }, 2000);
                    }

                },

                showAllBalances = function () {
                    var self = this,
                        modalInstance = $uibModal.open({
                            templateUrl: 'purchaseBalanceModalContent', //This content can be found in Shared/_BalanceInfo.cshtml, and each store has their own custom partial view content
                            controller: 'PurchaseBalanceModalCtrl',
                            size: 'lg',
                            resolve: {
                                balances: function () {
                                    return $scope.balances;
                                },
                                locale: function () {
                                    return $scope.locale;
                                }
                            }
                        });

                    modalInstance.result.then(function () {

                        $log.log('Dismissing modal');
                    }, function () {
                        //when cancelled do nothing
                    });
                },

                showBalanceInfo = function (balance) {
                    var self = this,
                        modalInstance = $uibModal.open({
                            templateUrl: 'purchaseBalanceModalContent', //This content can be found in Shared/_BalanceInfo.cshtml, and each store has their own custom partial view content
                            controller: 'PurchaseBalanceModalCtrl',
                            size: 'lg',
                            resolve: {
                                balances: function () {
                                    var balances = [];
                                    balances.push(balance)
                                    return balances;
                                },
                                locale: function () {
                                    return $scope.locale;
                                }
                            }
                        });

                    modalInstance.result.then(function () {

                        $log.log('Dismissing modal');
                    }, function () {
                        //when cancelled do nothing
                    });
                },

                parseEmployeeBalances = function (balances) {
                    $scope.balances = balances;

                    if (balances == undefined || balances == null || balances.length === 0) {
                        $scope.eligibleEPP = false;
                        $scope.showBalances = false;
                        $scope.realTimeBalances = false;
                        $scope.showMulipleBudgetsLink = false;
                    }
                    else {
                        $scope.eligibleEPP = true;
                        $scope.showMulipleBudgetsLink = balances.length > 2;

                        var firstBudgetCode = balances[0].BudgetCode;
                        for (i = 0; i < balances.length; i++) {
                            if (balances[i].BalanceType === 'EPP' && balances[i].OriginalBalance <= 0)
                                $scope.eligibleEPP = false;

                            if (balances[i].OriginalBalance > 0 || balances[i].ShowWhenZero)
                                $scope.showBalances = true;

                            if (balances[i].CalculateRealtime)
                                $scope.realTimeBalances = true;

                            if (firstBudgetCode !== balances[i].BudgetCode)
                                $scope.showMulipleBudgetsLink = true;
                        }
                    }

                },

                getEmployeeBalance = function (isRefresh) {
                    if (BudgetsService.budgetsEnabled)
                        BudgetsService.getBudgets(isRefresh)
                            .then(function (response) {
                                parseEmployeeBalances(response);
                            });
                };

            $scope.showBalanceInfo = showBalanceInfo;
            $scope.showAllBalances = showAllBalances;

            $scope.$on('onRefreshCart', refreshCart);
            $scope.$on('onOrderCreate', updateAfterOrder);
            $scope.$on('onUserNameChanged', updateUserName);
            $scope.$on('onOrderItemCancel', function () {
                getEmployeeBalance(true);
            });

            //Original code reloaded the cart anytime "Checkout" was in the path
            //This handled the onCartChange event which is broadcast anytime an items
            //it added, removed, or broadcasted. Reduces (hopefully) the number times we need to do this

            //TODO: Determine if this is the best location for this. This controller get's loaded
            //in multiple places so it is still firing multiple times when an order changes
            $rootScope.$on("onCartChange", function () {

                if ($scope.realTimeBalances)
                    getEmployeeBalance(true)

                if (Common.getCartInitialized()) {
                    Common.clearStoredShippingData();
                    CheckoutService.clearCheckoutCart();
                }
            });

            $rootScope.$on("onCartChangeCheckout", function () {

                if ($scope.realTimeBalances)
                    getEmployeeBalance(true)
            });

            $rootScope.$on("onMyAccountInfoChanged", function () {

                if (Common.getCartInitialized()) {
                    Common.clearStoredShippingData();
                    CheckoutService.clearCheckoutCart();
                }
            });
            $scope.showMobileMenu = false;
            $scope.showMobileSearch = false;

            $scope.toggleMobileSearch = function () {
                $scope.showMobileSearch = !$scope.showMobileSearch;
            };

            $scope.toggleMobileMenu = toggleMobileMenu;

            $scope.largeMenuVisible = false;
            $scope.menuLinkVisible = false;

            $scope.megaMenuVisible = false;


            $scope.toggleMenu = function ($event) {

                $scope.menuLinkVisible = !$scope.menuLinkVisible;

                if ($event) {
                    $event.preventDefault();
                }

                if ($scope.menuLinkVisible) {
                    $scope.$window.onclick = function (event) {
                        closeMenuWhenClickingElsewhere(event, $scope.toggleMenu);
                    };
                }
                else {
                    $scope.$window.onclick = null;
                    if (!$event)
                        $scope.$apply();
                }
            };

            // open
            // close
            // toggle
            // is open
            $scope.megaMenuIsOpen = function () {
                return $('#megamenu').is(':visible');
            };


            // open
            $scope.megaMenuOpen = function (id, $event) {
                //$().addClass('active');
                $(id).show();
            };

            // toggle
            $scope.megaMenuToggle = function (id, $event) {
                var isid = $(id).is(':visible'); //is currently visible
                $('.menu-panel').hide();
                $('.primary-nav-tabs a').removeClass('active');

                if (!isid) {
                    $(id).show();
                    $($event.currentTarget).addClass('active');
                }

                $scope.$window.onclick = function (event) {
                    closeMenuWhenClickingElsewhere(event, $scope.megaMenuClose);
                };

                closeMenuWhenClickingElsewhere($event, $scope.megaMenuClose);
            };
            //close
            $scope.megaMenuClose = function ($event) {
                $('.menu-panel').hide();
                $('.primary-nav-tabs a').removeClass('active');
            };


            $scope.toggleLargeMenu = function (id, $event) {

                var categoriesLength = categories.length,
                    menuVisible = $scope.largeMenuVisible;

                if ($event) {
                    $event.stopPropagation();
                }

                if (id !== undefined && !menuVisible) {

                    if (id < categoriesLength) {

                        $scope.category = categories[id].menu;
                        $scope.largeMenuVisible = true;

                        $scope.$window.onclick = function (event) {
                            closeMenuWhenClickingElsewhere(event, $scope.toggleLargeMenu);
                        };

                    } else {

                        //console.log("Invalid menu Id");

                    }

                } else if (!id) {

                    //hide the menu
                    $scope.largeMenuVisible = false;
                    $scope.$window.onclick = null;
                    $scope.$apply();

                } else {
                    // fetch the menu of id...


                }
            };

            updateUserName();
            //setSignInReturnUrl();
            $scope.solo = true;

            start();
        }]);
;
angular
    .module('ecs.ctrl.main', [])
    .controller('mainCtrl', [
        '$scope',
        '$rootScope',
        '$timeout',
        'AppTimeout',
        '$window',
        '$http',
        '$location',
        '$route',
        'Common',
        'Messaging',
        '$log',
        '$filter',
        'EcsLocale',
        'ProductUrlService',
        'Config',
        function ($scope, $rootScope, $timeout, AppTimeout, $window, $http, $location, $route, Common, Messaging, $log, $filter, EcsLocale, ProductUrlService, Config) {

            var messaging = new Messaging($scope),

                appTimeout = new AppTimeout($scope, $rootScope),

                setSignInReturnUrl = function () {

                    $scope.$signInReturnUrl = Common.getReturnUrl();
                },

                unbindRouteChangeListener,

                setUrl = function (path) {
                    var unBindMe = function ($event) {
                        unbindRouteChangeListener();
                        $scope.$scrollTop();
                    };

                    if (path) {
                        unbindRouteChangeListener = $scope.$on('$routeChangeSuccess', unBindMe);
                        $location.path(path);
                    }

                },

                /*
                setUrl = function (link) {
                    if (link) {
                        $location.url(link);
                        $scope.$scrollTop();
                    }
                },
                */

                checkForLoginPage = function () {

                    var isLoginPage = $('#login-main-bg').length > 0;

                    if (!isLoginPage) {
                        $scope.bodyLayout = 'persistent-scrollbar';
                    }
                },

                checkForSignedIn = function (pollRate) {
                    if ($scope.user && $scope.user.CustomerId !== null) {
                        appTimeout.startApplicationTimeoutSystem(pollRate, true);

                    }


                };

            checkForLoginPage();

            if (($scope.store.StoreCode && $scope.store) && $scope.store.StoreCode === "NIS") {
                checkForSignedIn(5); //timer poll rate for NIS 5 = 5 minutes after every page load, reoccuring.
            }


            $scope.$on('addAlert', function (event, alert) {
                $rootScope.$broadcast("loader_hide");
                messaging.addAlert(alert);
            });

            $scope.$on('scrollTop', function () {
                $scope.$scrollTop();
            });

            $scope.$on('goHome', function () {
                $scope.$goHome();
            });

            $scope.$on('onSessionTimeOut', function () {
                $scope.$goSessionTimeOut();
            });

            $scope.$on('waiting_on', function () {
                $scope.$waiting = true;
            });

            $scope.$on('waiting_off', function () {
                $scope.$waiting = false;
            });


            $scope.$goHome = function () {
                $scope.$scrollTop();
                $location.path('/');
            };

            $scope.$goPunchout = function () {
                $scope.$scrollTop();
                var redirectPathBuilder = [App.Configuration.RootPath, "Punchout/"];
                $window.location.href = redirectPathBuilder.join('');
            };

            $scope.$goPunchoutCampaign = function (campaignId) {
                $scope.$scrollTop();
                var redirectPathBuilder = [App.Configuration.RootPath, "Punchout/Campaign/", campaignId];
                $window.location.href = redirectPathBuilder.join('');
            };

            $scope.$goCheckout = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }

                var d = new Date().getTime();
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    var r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                });

                //var checkoutPath = 'checkout/register/';
                var checkoutPath = $location.path("cart");

                if ($scope.user.CustomerId) {
                    checkoutPath = 'checkout/shipping/';

                    $location.path(checkoutPath + uuid);

                    //Check if store requires we capture payment method first
                    if ($scope.store.Functionality.COCapturePaymentMethodFirst && !!$scope.store.PaymentMethods && $scope.store.PaymentMethods.length > 1)
                        checkoutPath = 'checkout/payment/';

                    $location.path(checkoutPath + uuid);
                }
                else {
                    checkoutPath = '/checkout/landing';
                    $location.path(checkoutPath);
                }

                //TODO: in the future, let's put code in here to check the state of the checkout cart to see what step to take them too

                $scope.$scrollTop();
                //$location.path(checkoutPath + uuid);
            };

            $scope.$gcCheckout = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }

                var d = new Date().getTime();
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    var r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                });

                var checkoutPath = 'checkout/register/';
                if ($scope.user.CustomerId)
                    checkoutPath = 'gccheckout/recipients/';

                $scope.$scrollTop();
                $location.path(checkoutPath + uuid);
            };

            $scope.$goCart = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }

                $scope.$scrollTop();
                $location.path("cart");
            };

            $scope.$goProductSearch = function ($event, text) {
                if ($event) {
                    $event.preventDefault();
                }

                var d = new Date().getTime();
                var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                    var r = (d + Math.random() * 16) % 16 | 0;
                    d = Math.floor(d / 16);
                    return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                });

                var searchPath = 'product-search/';

                $scope.$scrollTop();
                var redirectPathBuilder = ['product-search/', uuid, '/', text];
                $location.path(redirectPathBuilder.join(''));
            };

            $scope.$goSessionTimeOut = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }


                $scope.$scrollTop();
                var redirectPathBuilder = [App.Configuration.RootPath, "Home/Logoff/?timeout=true"];
                $window.location.href = redirectPathBuilder.join('');
            };

            $scope.$goLogOff = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }

                var redirectPathBuilder = [App.Configuration.RootPath, "Home/Logoff/"];
                $window.location.href = redirectPathBuilder.join('');
            };

            $scope.$back = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }

                $window.history.go(Common.getHistoryCounter());
            };


            $scope.$acceptTerms = function ($event, termsToAccept) {
                if ($event) {
                    $event.preventDefault();
                }

                var endpointURL = App.Configuration.RootPath + 'User/CatalogTermsAccept',
                    model = { TermsToAccept: termsToAccept, IsAccepted: true };

                request = $http({
                    method: "post",
                    url: endpointURL,
                    data: JSON.stringify(model)
                });

                request.success(function (response) {
                    $window.location.reload();
                });

                request.error(function (response) {
                    Common.showMessage('danger', '600');
                });

            };

            $scope.$scrollTop = function (value) {

                $window.scrollTo(0, value || 0);

            };

            $scope.$on("$locationChangeStart", function (event, next, current) {
                Common.incrementHistoryCounter(next, current);
                $timeout(function () {
                    messaging.resetMessages();
                    setSignInReturnUrl();

                }, 500);
                //Moved to within timeout
                //resetMessages();
                //setSignInReturnUrl();
            });



            $scope.showTaxLine = function (baseCurrency, exchangeCurrency) {
                baseCurrency = baseCurrency || {};
                hasExchangeCurrency = exchangeCurrency && exchangeCurrency.length > 0;

                var showTaxLine = !baseCurrency.BundleTaxes && (!hasExchangeCurrency || !exchangeCurrency[0].BundleTaxes);

                return showTaxLine;
            };

            $scope.convertToJsonDateString = function (date) {
                if (date) {
                    var _date;

                    if (typeof date === "string") {
                        _date = new Date(date);
                    } else if (typeof date === "object") {
                        _date = date;
                    } else {
                        return null;
                    }

                    var timeStamp = _date.getTime(),
                        jsonDate = "\/Date(%timestamp%)\/";

                    return jsonDate.replace('%timestamp%', timeStamp);

                } else {

                    return null;
                }
            };

            messaging.resetMessages(); //initialize messages
            setSignInReturnUrl();

            $scope.$waiting = false;
            $scope.setUrl = setUrl;
            $scope.addAlert = messaging.addAlert;
            $scope.closeAlert = messaging.closeAlert;
            $scope.closeError = messaging.closeError;
            $scope.closeMessage = messaging.closeMessage;
            $scope.hideEmailConfirm = true;
            $scope.locale = EcsLocale;
            $scope.user = $rootScope.user;
            $scope.$appConfig = Config;
            $scope.$toggleHelp = Common.toggleHelp;
            $scope.blurb = Common.getBlurb;
        }])
    .controller('TimerWarningModalCtrl', [
        '$scope',
        '$uibModal',
        '$log',
        function ($scope, $uibModal, $log) {


            var showModal = function () {

                var modalInstance = $uibModal.open({
                    templateUrl: 'timeoutWarningContent',
                    scope: $scope
                }),

                    self = this;

                modalInstance.result
                    .then(function () {
                        // close modal - ok button action
                        //remove_showTimeoutWarningModal();
                        $scope.$emit('cancelApplicationTimeout');
                    }, function () {
                        // cancel button action - none 
                        $scope.$emit('cancelApplicationTimeout');
                    });
            },

                remove_showTimeoutWarningModal,

                setListener = function () {
                    if (!remove_showTimeoutWarningModal) {
                        remove_showTimeoutWarningModal = $scope.$on('showTimeoutWarningModal', function (event) {
                            showModal();
                        });
                    }
                };

            setListener();

        }])
    .controller('ValidationErrorsModalCtrl', [
        '$scope',
        '$uibModal',
        '$log',
        'Constants',
        'errorArray',
        function ($scope, $uibModal, $log, Constants, errorArray) {

            $scope.errorArray = errorArray;
            $scope.getMessage = function (code) {
                var altMsg = 'We are sorry but this item is unavailable.',
                    msg = Constants.ERROR_MESSAGES["en-US"][code] || altMsg;

                return msg;
            };



        }])
    .controller('PurchaseBalanceModalCtrl', [
        '$scope',
        '$uibModal',
        '$log',
        '$sce',
        'balances',
        'locale',
        function ($scope, $uibModal, $log, $sce, balances, locale) {

            $scope.multipleBudgetCodes = false;
            var firstBudgetCode = (balances.length > 0) ? balances[0].BudgetCode : '';
            for (i = 0; i < balances.length; i++) {
                balances[i].descriptionHTML = $sce.trustAsHtml(balances[i].BudgetDescription);
                if (firstBudgetCode !== balances[i].BudgetCode)
                    $scope.multipleBudgetCodes = true;
            }

            $scope.balances = balances;
            $scope.locale = locale;
        }]);;angular
    .module('ecs.ctrl.doorbusters', [])
    .controller('doorbustersCtrl', [
        '$cookies',
        '$timeout',
        'Customers',
        'Common',
        '$scope',
        function ($cookies, $timeout, Customers, Common, $scope) {

            var view = this,

            init = function () {

                view.setPreferences = setPreferences;
                
                if (!checkForCookie()) {

                    loadCustomer();

                }
                
            },

            customer = {},

            loadCustomer = function () {
                Customers.getCustomer($scope.user.CustomerId)
                    .then(function (response) {
                        angular.extend(customer, response.data);

                        $timeout(function () {
                            showMessage(true);
                        }, 1000);
                    });
            },

            getEmailIndex = function (notificationSettings) {

                var index = -1;

                for (var i = 0, len = notificationSettings.length; i < len; i += 1) {
                    if (notificationSettings[i].Type === 'Emails') {
                        index = i;
                    }
                }

                return index;

            },

            setNotificationSetting = function () {

                var settings = customer.NotificationSettings = customer.NotificationSettings || [],
                    hasSettings = settings.length > 0,
                    emailSettingIndex = hasSettings ? getEmailIndex(settings) : -1;

                if (hasSettings && emailSettingIndex > -1) {
                    settings[emailSettingIndex].Enabled = true;
                    
                } else {
                    settings.push({ Type: 'Emails', Enabled: true });
                }
                
                Customers.updateCustomer(customer.CustomerId, customer);

            },

            checkForCookie = function () {

                return !!$cookies.get('doorbusters2015');

            },

            showMessage = function (bool) {

                view.showDoorbustersMessage = bool;
            },

            setPreferences = function (bool) {

                if (bool) {
                    setNotificationSetting();
                }

                $cookies.put('doorbusters2015', new Date(), {
                    expires: new Date("12/31/2030")
                });

                showMessage(false);

            };

            init();
        }]);;angular
    .module('ecs.ctrl.cookieMessage', [])
    .controller('cookieMessageCtrl', [
        '$cookies',
        '$scope',
        '$timeout',
        function ($cookies, $scope, $timeout) {

            var

            init = function () {

                $scope.markCookieWarningMessageAsViewed = markCookieWarningMessageAsViewed;
                
                if (!checkForCookie()) {
                    $timeout(function () {
                        showMessage(true);
                    }, 2000);
                }
                
                
            },

            checkForCookie = function () {

                return !!$cookies.get('Hvcwm');

            },

            showMessage = function (bool) {

                $scope.showCookieWarningMessage = bool;
            },

            markCookieWarningMessageAsViewed = function () {

                var expDate = new Date();
                expDate.setDate(expDate.getDate() + 30);

                $cookies.put('Hvcwm', new Date(), {
                    expires: expDate
                });

                showMessage(false);
            };

            init();
        }]);;angular
    .module('ecs.ctrl.scrolltotop', [])
    .controller('scrollToTopCtrl', [
        '$scope',
        '$timeout',
        '$window',
        '$location',
        function ($scope, $timeout, $window, $location) {
            $scope.$scrollTop();
        }]);;angular
    .module('ecs.ctrl.contact-us', [])
    .controller('contactUsCtrl', [
        '$scope',
        '$http',
        '$window',
        '$timeout',
        'Common',
        function ($scope, $http, $window, $timeout, Common) {
            var waitingForRefocus = false;

            var self = this,
                submit = function (form) {
                    $scope.submitted = true;
                    if (form.$valid) {                        
                        $scope.submitted = false;
                        postData(this.data);
                    } else {                        
                        waitingForRefocus = true;

                        Common.showMessage('danger', '615', {}, () => {
                            if (waitingForRefocus) {
                                waitingForRefocus = false;
                                angular.element('form .ng-invalid').first().focus();
                            }
                        });
                        
                        setTimeout(function () {
                            var msgBtn = angular.element('.update-panel button').first()[0];
                            msgBtn.focus();
                            msgBtn.addEventListener('click', function msgbtnOnClick() {
                                msgBtn.removeEventListener('click', msgbtnOnClick);
                                if (waitingForRefocus) {
                                    waitingForRefocus = false;
                                    angular.element('form .ng-invalid').first().focus();
                                }
                            });
                        }, 1);
                    }
                },

                postData = function (data) {

                    var anonymous = !$scope.user.CustomerId,
                        contactUsApi = App.Configuration.RootPath + 'User/ContactUsRequest',
                        captchaResponse = anonymous ? ('?grca=' + grecaptcha.getResponse(window.ECSStoresGreCaptchaID)) : null,
                        contactUsApiPath = !captchaResponse ? contactUsApi : contactUsApi + captchaResponse,
                        request;

                    if (data) {
                        request = $http({
                            method: "post",
                            url: contactUsApiPath,
                            data: JSON.stringify(data)
                        });

                        request.success(function (response) {
                            var status = 'success',
                                errorMessageNum = '624';
                            if (response && !response.SendSuccesful) {
                                if (response.FailedDueToCaptcha) {
                                    errorMessageNum = '622';
                                    status = 'failedDueToCaptcha';                                    
                                    angular.element('#gcaptcha')[0].focus();
                                }
                                Common.showMessage('danger', errorMessageNum);

                            } 

                            self.submission = status;
                            
                        });

                        request.error(function (response) {

                            var reason = "Form submit failed.";
                            self.submission = 'failed';

                            Common.showMessage('danger', '624');
                        });
                    }
                    
                    
                },

                initialize = function () {
                    var user = $scope.user;

                    if (user && user.Name && user.Name !== '') {
                        self.data.Name = user.Name;
                        self.disableNameField = true;
                    }

                    if (user && user.Email && user.Email !== '') {
                        self.data.Email = user.Email;
                    }
                };


            this.submittedSuccessfully = false;
            this.submit = submit;
            this.data = {};
            this.emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
            
            initialize();

        }]);
        

;angular
    .module('ecs.ctrl.dataConsentRequest', [])
    .controller('dataConsentRequestCtrl', [
        '$scope',
        '$http',
        '$window',
        '$timeout',
        'Common',
        'Customers',
        function ($scope, $http, $window, $timeout, Common, Customers) {

            var self = this,
                updateConsent = function () {
                    if ($scope.requestData.dataConsent) {

                        var dataConsentPref = {};
                        dataConsentPref.Enabled = true;
                        dataConsentPref.Type = 'Data Consent';
                        Customers.updateNotificationPreferences($scope.userProfile.CustomerId, dataConsentPref)
                         .then(function (response) {
                             $scope.userProfile.updatedDataConsent = true; //This just shows a update message
                         });
                    }
                    else
                        Common.showMessage('danger', '635');
                    
                },

                submit = function () {
                    if ($scope.requestData.RequestType === 'Data Consent Access Request') {

                        if ($scope.requestData.DataSubjectConfirmation && $scope.requestData.Details && $scope.requestData.Details !== '')
                            postData($scope.requestData);
                        else
                            Common.showMessage('danger', '633');
                    }
                    else {
                        if ($scope.requestData.WithdrawalConfirmation || $scope.requestData.DeletionConfirmation || $scope.requestData.DataCopyConfirmation)
                            postData($scope.requestData);
                        else
                            Common.showMessage('danger', '634');
                    }
                },

                postData = function (data) {

                    var dataConsentAPI = App.Configuration.RootPath + 'User/DataConsentRequest',
                        profile = $scope.userProfile,
                        request;

                    data.CustomerId = profile.CustomerId;
                    data.Name = profile.FullName;
                    data.Address1 = profile.BillingAddress.Address1;
                    data.Address2 = profile.BillingAddress.Address2;
                    data.City = profile.BillingAddress.City;
                    data.State = profile.BillingAddress.State;
                    data.PostalCode = profile.BillingAddress.PostalCode;
                    data.Country = profile.BillingAddress.Country;
                    data.Email = profile.Email;
                    data.Phone = profile.Phone;

                    if (data) {
                        request = $http({
                            method: "post",
                            url: dataConsentAPI,
                            data: JSON.stringify(data)
                        });

                        request.success(function (response) {
                            var status = 'success',
                                errorMessageNum = '624';
                            if (response && !response.SendSuccess) {
                                
                                Common.showMessage('danger', errorMessageNum);

                            } 

                            $scope.submittedSuccessfully = true;
                            
                        });

                        request.error(function (response) {
                            $scope.submittedSuccessfully = false;
                            Common.showMessage('danger', '624');
                        });
                    }
                    
                    
                },

                getProfile = function () {


                    var user = $scope.user;

                    if (user && user.CustomerId && user.CustomerId !== '') {
                        Customers.getCustomer(user.CustomerId)
                            .then(function (response) {
                                $scope.userProfile = response.data;
                                if (!!$scope.userProfile.DataConsentDate)
                                    $scope.userProfile.DataConsentDate = Common.convertJsonDateString($scope.userProfile.DataConsentDate);
                            });
                    } else { //not authorized
                        Common.goHome();
                    }
                };


            $scope.submittedSuccessfully = false;
            $scope.submit = submit;
            $scope.updateConsent = updateConsent;
            $scope.requestData = {};
            $scope.requestData.RequestType = 'Data Consent Access Request';
            $scope.requestData.todaysDate = new Date();
            $scope.requestData.dataConsent = false;
            $scope.userProfile = null;

            getProfile();

        }]);
        

;angular
    .module('ecs.ctrl.refreshheader', [])
    .controller('refreshHeaderCtrl', [
        '$rootScope',
        '$scope',
        function ($rootScope, $scope) {
            $scope.$scrollTop();
            $rootScope.$broadcast('onSessionTimeOut');
        }]);;angular
    .module('ecs.ctrl.creditCardTokenizer', [])
    .controller('creditCardTokenizerCtrl', [
        '$scope',
        '$http',
        '$sce',
        'Objects',
        function ($scope, $http, $sce, Objects) {
            Objects.getCreditCardTokenizeIFrameURL().then((resp) => {
                //console.log(resp);
                $scope.tokenizeIFrameURL = $sce.trustAsResourceUrl(resp.data);
            });
        }]);;
angular
    .module('ecs.ctrl.cmsCarouselCtrl', [])
    .controller('cmsCarouselCtrl', [
        '$scope',
        '$window',
        '$log',
        function ($scope, $window, $log) {

            var init = function (data) {

                var slides = data.Images;

                $scope.slides = slides;
                $scope.currentSlide = slides[0]; //emulating the internal design for currentSlide
                $scope.carouselInterval = 5000;

                // May return `undefined` if no slide is active 
                // (e.g. when the carousel hasn't initialised)
                var getActiveSlide = function () {
                    return slides.filter(function (s) {
                        return s.active;
                    })[0];
                },

                //check for a transition and set to the current slide if changed/updated
                checkForTransition = function () {
                    var activeSlide = getActiveSlide();

                    if ($scope.currentSlide !== activeSlide) {
                        $scope.currentSlide = activeSlide;
                        $scope.$apply();
                    }
                };

                //design a simple check to make sure we have the most accurate information
                //on the current slide. note: ui bootstrap does not expose an event for slide transitions
                setInterval(function () {
                    checkForTransition();
                }, 1000);

                $scope.useCarousel = true;



            };

            $scope.init = init;
            

        }]);;
angular
    .module('ecs.ctrl.cmsImageCtrl', [])
    .controller('cmsImageCtrl', [
        '$scope',
        function ($scope) {
            var init = function (data) {
                $scope.data = data;
            };

            $scope.init = init;
            
        }]);;
angular
    .module('ecs.ctrl.cmsGrid3WidelCtrl', [])
    .controller('cmsGrid3WidelCtrl', [
        '$scope',
        '$sanitize',
        '$window',
        '$log',
        function ($scope, $sanitize, $window, $log) {

            var init = function (data) {

                var imageArr = data.Images,
                    rowsArr = [];

                while (imageArr.length > 0) {
                    var row = { images: [] }
                    for (var j = 0; j < 3; j += 1) {
                        if (imageArr.length > 0) {
                            var imgObj = imageArr.shift();
                            if (imgObj.Title) {
                                imgObj.Title = $sanitize(imgObj.Title)
                            }
                            if (imgObj.AltText) {
                                imgObj.AltText = $sanitize(imgObj.AltText)
                            }
                            row.images.push(imgObj);
                        }
                    }
                    rowsArr.push(row);
                }


                $scope.rowsArr = rowsArr;
                $scope.useGrid = true;



            };

            $scope.init = init;


        }])
        .filter('escapeHTML', function () {

            return function (text) {
                if (text) {
                    return text.
                        replace(/&/g, '&amp;').
                        replace(/</g, '&lt;').
                        replace(/>/g, '&gt;').
                        replace(/'/g, '&#39;').
                        replace(/"/g, '&quot;');
                }
                return '';
            }
        });;angular
    .module('ecs.directives.loader', [])
    .directive("loader", ['$rootScope', '$timeout', 'Common', function ($rootScope, $timeout, Common) {
 
        return function ($scope, element, attrs) {
            $scope.$on("loader_show", function (event, message_id, keepOpen) {
                if (element.css('display') === 'none') {
                    element.find('.message').text(Common.getMessage(message_id));
                    if (keepOpen) {
                        element.addClass('manual-close');
                    }
                    return element.show();
                } else {
                    return null;
                }
            });
            return $scope.$on("loader_hide", function (event, forceClose) {
                if (!element.hasClass('manual-close') || forceClose) {
                    $timeout(function () {
                        element.removeClass('manual-close');
                        return element.hide();
                    }, 100);
                    
                }
                
               
            });
        };
    }]);;angular
    .module('ecs.directives.accessibleForm', [])
    .directive('accessibleForm', function () {
    return {
        retrict: 'E',
        link: function (scope, elem) {

            // set up event handler on the form element
            elem.on('submit', function () {

                // find the first invalid element
                var firstInvalid = angular.element(
                    elem[0].querySelector('.ng-invalid'))[0];

                // if we find one, set focus
                if (firstInvalid) {
                    firstInvalid.focus();
                }
            });
        }
    };
});;angular
    .module('ecs.directives.numbersOnly', [])
    .directive('numbersOnly', function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, modelCtrl) {
            modelCtrl.$parsers.push(function (inputValue) {
                // this next if is necessary for when using ng-required on your input. 
                // In such cases, when a letter is typed first, this parser will be called
                // again, and the 2nd time, the value will be undefined
                if (inputValue == undefined) return ''
                var transformedInput = (inputValue).toString().replace(/[^0-9]/g, '');
                if (transformedInput != inputValue.toString()) {
                    modelCtrl.$setViewValue(Number(transformedInput));
                    modelCtrl.$render();
                }

                return transformedInput;
            });
        }
    };
});;angular
    .module('ecs.directives.noSpecialChar', [])
    .directive('noSpecialChar', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                modelCtrl.$parsers.push(function (inputValue) {
                    // this next if is necessary for when using ng-required on your input. 
                    // In such cases, when a letter is typed first, this parser will be called
                    // again, and the 2nd time, the value will be undefined
                    if (inputValue == undefined) return ''
                    var transformedInput = inputValue.replace(/[^0-9a-zA-Z .]/g, '');
                    if (transformedInput != inputValue) {
                        modelCtrl.$setViewValue(transformedInput);
                        modelCtrl.$render();
                    }

                    return transformedInput;
                });
            }
        };
    });;angular
    .module('ecs.directives.codiceFicale', [])
    .directive('codiceFiscale', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                var validateInput = function (cf) {
                    if (cf == '') {
                        return '';
                    }

                    cf = cf.toUpperCase();

                    if (cf.length != 16) {
                        return false;
                    }

                    return cf;
                },

                validaCodiceFiscale = function (cf) {
                    var validChrs, i, s, set1, set2, setpari, setdisp;

                    if (!cf) return false;

                    validChrs = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
                    for (i = 0; i < 16; i++) {
                        if (validChrs.indexOf(cf.charAt(i)) == -1)
                            return false;
                    }
                    set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                    set2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ";
                    setpari = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                    setdisp = "BAKPLCQDREVOSFTGUHMINJWZYX";
                    s = 0;
                    for (i = 1; i <= 13; i += 2) {
                        s += setpari.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
                    }

                    for (i = 0; i <= 14; i += 2) {
                        s += setdisp.indexOf(set2.charAt(set1.indexOf(cf.charAt(i))));
                    }

                    if (s % 26 != cf.charCodeAt(15) - 'A'.charCodeAt(0)) {
                        return false;
                    }
                        
                    return true;
                };

                modelCtrl.$parsers.unshift(validateInput);
                modelCtrl.$validators.validaCodiceFiscale = validaCodiceFiscale;
            }
        };
    });
;angular
    .module('ecs.directives.limitedSpecialChar', [])
    .directive('limitedSpecialChar', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {

                var validateInput = function (inputValue) {
                    // this next if is necessary for when using ng-required on your input. 
                    // In such cases, when a letter is typed first, this parser will be called
                    // again, and the 2nd time, the value will be undefined

                    var regex = new RegExp(attrs.limitedSpecialChar, 'g');

                    if (inputValue == undefined) return ''
                    var transformedInput = inputValue.replace(regex, '');
                    if (transformedInput != inputValue) {
                        modelCtrl.$setViewValue(transformedInput);
                        modelCtrl.$render();
                    }

                    return transformedInput;
                };

                modelCtrl.$parsers.unshift(validateInput);
            }
        };
    });;angular
    .module('ecs.directives.numbersHypen', [])
    .directive('numbersHypen', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                modelCtrl.$parsers.push(function (inputValue) {
                    // this next if is necessary for when using ng-required on your input. 
                    // In such cases, when a letter is typed first, this parser will be called
                    // again, and the 2nd time, the value will be undefined
                    if (inputValue == undefined) return ''
                    var transformedInput = inputValue.replace(/[^-0-9 ]/g, '');
                    if (transformedInput != inputValue) {
                        modelCtrl.$setViewValue(transformedInput);
                        modelCtrl.$render();
                    }

                    return transformedInput;
                });
            }
        };
    });;angular
.module('ecs.directives.affix', [])
    .directive('affix', ['$window', function ($window) {
        return {
            $scope: true,
            link: function ($scope, $element, $attrs) {
                var relativeTo = // overide or use default: body (html for IE) element
                    !!$attrs.relativeTo ? angular.element(window.document.getElementById($attrs.relativeTo)) :
                        !$scope.$root.isIE ? // specify your own isIE check will default to body element
                            angular.element(window.document.getElementsByTagName('body')) :
                            angular.element(window.document.getElementsByTagName('html')), // required by IE
                    win = !!$attrs.relativeTo ? relativeTo : angular.element($window),
                    // if a relativeTo other than the default is set we will 
                    // offset the affixed position by it's offset
                    relativeToOffset = null,
                    fixedAt = null;

                // boolean
                $scope.affixed = false;
                $scope.offset = 0;

                // Obviously, whenever a scroll occurs, we need to check and possibly 
                // adjust the position of the affixed $element.
                win.bind('scroll', checkPosition);

                // on resize recalculate fixedAt position 
                win.bind('resize', function () {
                    $scope.$apply(function () {
                        $scope.affixed = false;
                    });
                    relativeToOffset = null;
                    fixedAt = null;
                    checkPosition();
                });

                // calculate if we need to affix element
                function checkPosition() {

                    relativeToOffset = relativeToOffset || win[0].offsetTop;
                    fixedAt = fixedAt || $element[0].offsetTop - relativeToOffset;

                    $scope.$apply(function () {
                        $scope.offset = { top: relativeToOffset + 'px' };
                        $scope.affixed = fixedAt <= relativeTo[0].scrollTop;
                    });
                }
            }
        };
    }]);;angular
    .module('ecs.directives.emailSpecialCharOnly', [])
    .directive('emailSpecialCharOnly', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                modelCtrl.$parsers.push(function (inputValue) {
                    // this next if is necessary for when using ng-required on your input. 
                    // In such cases, when a letter is typed first, this parser will be called
                    // again, and the 2nd time, the value will be undefined
                    if (inputValue == undefined) return ''
                    var transformedInput = inputValue.replace(/[^0-9a-zA-Z @._-]/g, '');
                    if (transformedInput != inputValue) {
                        modelCtrl.$setViewValue(transformedInput);
                        modelCtrl.$render();
                    }

                    return transformedInput;
                });
            }
        };
    });;angular
.module('ecs.directives.localeDateFormatter', [])
.directive('localeDateFormatter', ['EcsLocale', function (EcsLocale) {
    var checkValue = function (val) {
        var value = String(val).toLowerCase(),
            valid = true;
        if (value === '' || value.indexOf('invalid') !== -1 || value.indexOf('nan') !== -1) {
            valid = false;
        }

        return valid;
    };

    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attr, ngModel) {

            ngModel.$parsers.push(function (str) {
                var converted = EcsLocale.convertDate(str),
                    value = 'Invalid Date';

                if (checkValue(converted)) {
                    value = converted;
                }

                return value; 
            });

            ngModel.$formatters.push(EcsLocale.convertDate);

            element.bind('blur', function () {

                var converted = EcsLocale.convertDate(ngModel.$modelValue),
                    value = 'Invalid Date';

                if (checkValue(converted)) {
                    value = converted;
                }
                element.val(value);
            });
            
            element.bind('focus', function () {
                if (!checkValue(ngModel.$modelValue)) {
                    element.val('');
                }
                
            });
            
        }
    };
}]);angular
    .module('ecs.directives.datesOnly', [])
    .directive('datesOnly', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                modelCtrl.$parsers.push(function (inputValue) {
                    // this next if is necessary for when using ng-required on your input. 
                    // In such cases, when a letter is typed first, this parser will be called
                    // again, and the 2nd time, the value will be undefined
                    if (inputValue == undefined) return ''
                    var transformedInput = inputValue.replace(/[^0-9/]/g, '');
                    if (transformedInput != inputValue) {
                        modelCtrl.$setViewValue(transformedInput);
                        modelCtrl.$render();
                    }

                    return transformedInput;
                });
            }
        };
    });;angular
    .module('ecs.directives.futureDate', [])
    .directive('futureDate', function () {
        return {
            require: 'ngModel',
            link: function (scope, element, attrs, modelCtrl) {
                var isFutureDate = function (inputValue) {
                    if (inputValue == undefined) return ''
                    var dateMin = new Date(scope.minimumDate);
                    //var today = new Date();
                    var inputDate = new Date(inputValue);
                    var isValid = inputDate.setHours(0, 0, 0, 0) >= dateMin.setHours(0, 0, 0, 0); //today.setHours(0, 0, 0, 0);
                    modelCtrl.$setValidity('futureDate', isValid);

                    return inputValue;
                };

                modelCtrl.$parsers.unshift(isFutureDate);
                modelCtrl.$formatters.push(isFutureDate);

                attrs.$observe('futureDate', function () {
                    isFutureDate(modelCtrl.$viewValue);
                });
            }
        };
    });;angular
    .module('ecs.directives.fallbackSrc', [])
    .directive('fallbackSrc', function () {
    var fallbackSrc = {
        link: function postLink(scope, iElement, iAttrs) {
            iElement.bind('error', function () {
                angular.element(this).attr("src", iAttrs.fallbackSrc);
            });
        }
    }
    return fallbackSrc;
});;angular.module('ecs.directives.contenteditable', ['ngSanitize']).
directive('contenteditable', ['$sce', function ($sce) {
    return {
        restrict: 'A', // only activate on element attribute
        require: '?ngModel', // get a hold of NgModelController
        link: function (scope, element, attrs, ngModel) {
            if (!ngModel) return; // do nothing if no ng-model

            // Specify how UI should be updated
            ngModel.$render = function () {
                element.html($sce.getTrustedHtml(ngModel.$viewValue || ''));
            };

            // Listen for change events to enable binding
            element.on('blur keyup change', function () {
                scope.$evalAsync(read);
            });


            // Write data to the model
            function read() {
                var html = element.html();
                // When we clear the content editable the browser leaves a <br> behind
                // If strip-br attribute is provided then we strip this out
                if (attrs.stripBr && html == '<br>') {
                    html = '';
                }
                ngModel.$setViewValue(html);
            }
        }
    };
}]);;angular

    .module('ecs.ctrl.select-pack', [])
    .controller('selectPackCtrl', [
        '$scope',
        '$routeParams',
        '$location',
        'EcsResource',
        'CartService',
        'ProductUrlService',
        'Customers',
        'Common',
        'Rewards',
        '$log',
        function ($scope, $routeParams, $location, EcsResource, CartService, ProductUrlService, Customers, Common, Rewards, $log) {

            var selectPackCtrl = this,

                currentReward = null,

                trophyPack = null,
                swagPack = null,

                availableProducts = {},

                getReward = function () {
                    Rewards.getReward(selectPackCtrl.rewardId)
                        .then(function (reward) {
                            if (reward.data.Status != 1) {
                                Common.goHome();
                                return;
                            }
                            var currentReward = reward.data,
                                trophyPack = null,
                                swagPack = null;

                            for (var i = 0; i < currentReward.Packs.length; i++) {
                                if (currentReward.Packs[i].Type === 1) {
                                    trophyPack = currentReward.Packs[i];
                                }
                                else {
                                    swagPack = currentReward.Packs[i];
                                }

                            };

                            setImageUrls(trophyPack);
                            setImageUrls(swagPack);

                            selectPackCtrl.currentReward = currentReward;
                            selectPackCtrl.trophyPack = trophyPack;
                            selectPackCtrl.swagPack = swagPack;

                            setPageReady();


                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/awards/error/');
                            } else {
                                var errCode = reason.data ? reason.data.errorCode : undefined;
                                var messageInData = reason.data ? reason.data.message : undefined;
                                var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                                Common.showMessage('danger', message, { errorCode: errCode });
                            }
                        });
                },

                setImageUrls = function (pack) {
                    var urls = {};

                    if (pack) {
                        urls.lg = getMainImageUrl(pack, 'l');
                        urls.md = getMainImageUrl(pack);
                        urls.sm = getMainImageUrl(pack, 'tt');

                        pack.imageUrls = urls;
                    }

                    return;
                    
                },

                setPageReady = function () {
                    selectPackCtrl.pageReady = true;
                },

                getMainImageUrl = function (pack, size) {
                    var imageUrl,
                        product = getProduct(pack);

                    if (product) {
                        imageUrl = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                    } else {
                        imageUrl = ProductUrlService.getNoImageUrl(size);
                    }

                    return imageUrl;
                },

                linkToReview = function (rewardId, pack) {
                    linkTo('/awards/review-order/' + rewardId + '/' + pack.RewardPackId + '/' + '[' + getProduct(pack).RewardProductId + ']');
                },
                linkToSelectGroup = function (rewardId, pack) {
                    linkTo('/awards/select-group/' + rewardId + '/' + pack.RewardPackId);
                },
                linkToSelectAward = function (rewardId, pack) {
                    linkTo('/awards/select-award/' + rewardId + '/' + pack.RewardPackId);
                },
                redeemAsOptOut = function (rewardId) {

                    Common.showLoader('110');

                    var rewardRedemptionDTO = {
                        'RewardId': rewardId,
                        'Type': 5, //OptOut
                        'RedeemedAs': 'OPTOUT',
                        'RedeemedProducts': [{
                            RedeemedAs: 'OPTOUT'
                        }]
                    };

                    Rewards.redeemRewards(rewardId, rewardRedemptionDTO)
                    .then(function (response) {
                        $log.log(response);
                        selectPackCtrl.optoutcomplete = true;
                    },
                    function (message) {
                        Common.showMessage('error', 'Error redeeming the reward.');
                        $log.log('Error redeeming product', message);
                    });
                },


                linkTo = function (path) {
                    Common.linkTo(path);
                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },

                showMyOptions = function () {

                    selectPackCtrl.landing = false;

                },

                // Phase 1, packs only have 1 group with 1 product
                getProduct = function (pack) {
                    if (pack && !!pack.Groups && !!pack.Groups[0] && !!pack.Groups[0].Products && !!pack.Groups[0].Products[0])
                        return pack.Groups[0].Products[0];
                    return null;
                };

            selectPackCtrl.currentReward = currentReward;
            selectPackCtrl.trophyPack = trophyPack;
            selectPackCtrl.swagPack = swagPack;

            selectPackCtrl.redeemAsOptOut = redeemAsOptOut;
            selectPackCtrl.linkTo = linkTo;
            selectPackCtrl.linkToReview = linkToReview;
            selectPackCtrl.linkToSelectGroup = linkToSelectGroup;
            selectPackCtrl.linkToSelectAward = linkToSelectAward;
            selectPackCtrl.convertDate = convertDate;
            selectPackCtrl.getProduct = getProduct;
            selectPackCtrl.showMyOptions = showMyOptions;
            selectPackCtrl.landing = true;
            selectPackCtrl.optoutcomplete = false;
            selectPackCtrl.rewardId = $routeParams.id;

            $scope.changeFocus = Common.changeFocus;

            getReward();

        }]);;'use strict';

angular
    .module('ecs.ctrl.review-catalog-order', [])
    .controller('reviewCatalogOrderCtrl', [
        '$scope',
        '$rootScope',
        '$routeParams',
        'RewardService',
        'ProductUIService',
        '$window',
        function ($scope, $rootScope, $routeParams, RewardService, ProductUIService, $window) {
            var

                redirectBackToSelect = function () {
                    $scope.rewardService.linkTo('/awards/select-catalog-award/' + $scope.rewardId);
                    $window.sessionStorage.clear();
                },

                showAddressForm = function () {
                    $scope.rewardService.showAddressForm(false);
                };

            $scope.productUI = ProductUIService;
            $scope.rewardService = RewardService;
            $scope.rewardId = $routeParams.id;
            $scope.productId = $routeParams.productId;
            $scope.redirectBackToSelect = redirectBackToSelect;
            $scope.showAddressForm = showAddressForm;
            $scope.rewardService.setScope($scope);
            $scope.rewardService.setStoreCode($rootScope.store.StoreCode);
            $scope.rewardService.getReward($scope.rewardId);
            $scope.rewardService.getProducts($scope.productId);

        }]);
;'use strict';

/* 
    1. Code to display existing shipping address with 
    selection option will be moved to a directive.
*/

angular
    .module('ecs.ctrl.review-order', [])
    .controller('reviewOrderCtrl', [
        '$scope',
        '$rootScope',
        '$location',
        '$routeParams',
        'EcsResource',
        'Products',
        'Common',
        'Rewards',
        'ProductUrlService',
        '$log',
        '$uibModal',
        '$sce',
        'Campaign',
        'RewardService',
        'ProductUIService',
        '$window',
        function ($scope, $rootScope, $location, $routeParams, EcsResource, Products, Common, Rewards, ProductUrlService, $log, $uibModal, $sce, Campaign, RewardService, ProductUIService, $window) {
            var currentUser = ECSStores.CurrentUser,
                redeemed = false,

                // PHX-61
                // TODO: We need to merge this logic to reward service 
                updateRemainingRedemptions = (product) => {
                    if (!product.Quantity) product.Quantity = 1;
                    const remainingQty = $scope.reward.NumberOfRemainingProductsToRedeem;
                    const totalQty = $scope.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                    if (totalQty <= remainingQty) {
                        RewardService.remainingRedemptions = remainingQty - totalQty;
                    } else {
                        const excessQty = totalQty - remainingQty;
                        product.Quantity = product.Quantity - excessQty;
                        RewardService.remainingRedemptions = 0;
                        Common.showMessage('danger', 'The quantity you entered exceeded your total remaining redemptions, the quantity was set to your total remaining redemptions');
                    }
                    $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(RewardService.remainingRedemptions));
                    $window.sessionStorage.setItem("products", JSON.stringify($scope.products));
                },

                // PHX-61
                // TODO: We need to merge this logic to reward service 
                removeSelectedProduct = (product) => {
                    const idx = $scope.products.indexOf(product);
                    $scope.products.splice(idx, 1);
                    const remainingQty = $scope.reward.NumberOfRemainingProductsToRedeem;
                    const totalQty = $scope.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                    RewardService.remainingRedemptions = remainingQty - totalQty;
                    $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(RewardService.remainingRedemptions));
                    $window.sessionStorage.setItem("products", JSON.stringify($scope.products));

                    if ($scope.products.length == 0) {
                        $window.sessionStorage.clear();
                        $scope.redirectToSelectAward();
                    }
                },


                getPack = function (packId, reward) {
                    var pack = null;

                    if (!reward || !reward.Packs)
                        return pack;

                    $.each(reward.Packs, function (index) {
                        if (this.RewardPackId == $scope.packId) {
                            pack = this;
                        }
                    });

                    if (pack == null) {
                        $location.path('/awards/error/');
                    }

                    return pack;
                },

                getProduct = function (productId, pack) {
                    var product = null;

                    if (!pack || !pack.Groups)
                        return product;

                    $.each(pack.Groups, function (index) {
                        if (!!this.Products) {
                            $.each(this.Products, function (index) {
                                var p = this;
                                if (p.RewardProductId == productId) {
                                    product = p;
                                }
                            });
                        }
                    });

                    if (product == null) {
                        $location.path('/awards/error/');
                    }

                    return product;
                },

                //required for displaying shipping address in 2 columns
                //can be moved to a different service when tested
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },



                loadChildProducts = function (product) {
                    if (!product || !product.IsConfigurable) {
                        product.selectedConfiguration = null;
                        product.childProducts = null;
                        return;
                    }

                    product.selectedConfiguration = null;
                    product.childProducts = null;

                    //haven't fully tested this yet with Multi Gifts
                    Products.getBackendChildProducts(product.ProductNumber).then(
                        function (response) {
                            product.childProducts = response.data;
                        },
                        function (message) {
                            $log.log('Error getting child products', message);
                        });
                },

                getNoImageurl = function (size) {
                    return ProductUrlService.getNoImageurl(size);
                },

                getProductImage = function (product, size) {
                    if (!product)
                        return getNoImageurl(size);

                    return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                },

                getProductImages = function (product) {
                    product.Image.urls = {};

                    product.Image.urls.lg = getProductImage(product, 'l');
                    product.Image.urls.md = getProductImage(product, '');
                    product.Image.urls.sm = getProductImage(product, 't');
                    product.Image.urls.xs = getProductImage(product, 'tt');
                },

                loadSelectedProductByIds = function (productIds, pack) {
                    var productArray = [];

                    if (!Array.isArray(productIds)) {
                        productArray.push(productIds)
                    } else {
                        productArray = productIds;
                    }

                    $.each(productArray, function (index) {
                        var product = getProduct(this, pack);
                        getProductImages(product);
                        $scope.products.push(product);
                        loadChildProducts(product);
                    });
                },

                loadSelectedProducts = function (selectedProducts) {
                    if (!selectedProducts) {
                        //to handle when page is hard reload/refresh
                        RewardService.products = JSON.parse($window.sessionStorage.getItem("products"));
                        selectedProducts = RewardService.products;
                        RewardService.remainingRedemptions = JSON.parse($window.sessionStorage.getItem("remainingRedemptions"));
                    }
                    $scope.products = selectedProducts;
                    angular.forEach($scope.products, function (p) {
                        loadChildProducts(p);
                    });
                },

                getReward = function (rewardid) {

                    Rewards.getReward(rewardid).
                        then(function (reward) {

                            if (reward.data.Status != 1) {
                                Common.goHome();
                                return;
                            }

                            $scope.reward = reward.data;
                            $scope.shipToAddress = $scope.reward.DefaultShippingAddress;
                            $scope.pack = getPack($scope.packId, $scope.reward);
                            if (!!$scope.productId) {
                                loadSelectedProductByIds($scope.productId, $scope.pack);
                            } else {
                                loadSelectedProducts(RewardService.selectedProducts);
                            }
                            $scope.reward.awardConfigJSON = JSON.parse(reward.data.AwardConfigJSON);
                            $scope.reward.termsConfigObj = JSON.parse(reward.data.TermsJson);
                            if (!!$scope.reward.termsConfigObj) {
                                $scope.reward.termsConfigObj.Message = $sce.trustAsHtml($scope.reward.termsConfigObj.Message);
                            }

                            $scope.reward.PersonalizedName = $scope.reward.RecipientName;
                            $scope.paymentRequired = $scope.reward.PaymentRequired;

                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/awards/error/');
                            } else {
                                var errCode = reason.data ? reason.data.errorCode : undefined;
                                var messageInData = reason.data ? reason.data.message : undefined
                                var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                                Common.showMessage('danger', message, { errorCode: errCode });
                            }
                        });
                },

                getNoImageurl = function (size) {
                    return ProductUrlService.getNoImageurl(size);
                },

                //====End Private functions



                toggleEdit = function () {
                    $scope.editName = !$scope.editName;
                },


                cancelNameEdit = function () {
                    $scope.reward.PersonalizedName = $scope.savedRecipientName;
                    $scope.toggleEdit();
                },

                prepareForNameEdit = function () {
                    $scope.savedRecipientName = $scope.reward.PersonalizedName;
                    $scope.toggleEdit();
                },

                canRedeem = function () {
                    var isReadyToRedeem = false;

                    if ($scope.products != null && $scope.products.length == 1) {
                        var product = $scope.products[0];
                        isReadyToRedeem = !!product &&
                            (!product.IsConfigurable || !!product.selectedConfiguration);
                    }
                    else {
                        if (!!$scope.products) {
                            isReadyToRedeem = true;
                            $.each($scope.products, function (index) {
                                var product = this;
                                if (!!product.childProducts && !product.selectedConfiguration) {
                                    isReadyToRedeem = false;
                                }
                            });
                        }

                        isReadyToRedeem = isReadyToRedeem;
                    }

                    return isReadyToRedeem;
                },

                redirectTo = function () {
                    $scope.linkTo('/awards/select-pack/' + $scope.rewardId);
                },

                redirectToSelectAward = function () {
                    $scope.linkTo('/select-award/' + $routeParams.id + '/' + $routeParams.packId);
                },

                redeemReward = function () {
                    if (!$scope.rewardService.shippingChecks()) {
                        return;
                    }
                    Common.showLoader('119');

                    var selectedProduct = [];

                    $.each($scope.products, function (index) {
                        var product = {};
                        product.ProductNumber = this.IsConfigurable ? (!!this.selectedConfiguration.PurchaseProductNumber ? this.selectedConfiguration.PurchaseProductNumber : this.selectedConfiguration.ProductNumber) : this.ProductNumber;
                        product.ProductName = this.Name;
                        product.Quantity = this.Quantity ? this.Quantity : 1;
                        product.RedeemedAs = this.Name;

                        if (this.IsConfigurable) {
                            product.RedeemedAs = product.RedeemedAs + ' with Option ' + this.selectedConfiguration.OptionType + ':' + this.selectedConfiguration.Name
                        }

                        selectedProduct.push(product);
                    });

                    var rewardRedemptionDTO = {
                        'RewardId': $scope.reward.RewardId,
                        'Type': 1, //Redeem Pack
                        'RedeemedAs': $scope.pack.Name,
                        'PersonalizedName': $scope.reward.PersonalizedName,
                        'ShippingAddress': $scope.shipToAddress, //Don't need to provide the shipping address anymore in the redemption. Is already been set in the DB
                        'RedeemedPack': {
                            'RewardPackId': $scope.packId,
                            'RedeemedProducts': selectedProduct
                        },
                        'IsExpired': false,
                        'IncludesBase': Boolean($scope.reward.needsBase)
                    };

                    if ($scope.reward.TermsRequired && $scope.reward.termsConfigObj.RequireSignature)
                        rewardRedemptionDTO.TermsSignature = $scope.reward.termsAgreement;

                    if ($scope.shipToAddress.Country !== 'US') {
                        rewardRedemptionDTO.ContactPhone = $scope.reward.ContactPhone;
                        rewardRedemptionDTO.ContactPhoneExtension = $scope.reward.ContactPhoneExtension;
                    }


                    $scope.redeeming = true;

                    Rewards.redeemRewards($scope.reward.RewardId, rewardRedemptionDTO, '100')
                        .then(function (response) {
                            $log.log(response);
                            $scope.reward.OrderNumber = !!response.data.RedeemedPack.RedeemedProducts && response.data.RedeemedPack.RedeemedProducts.length > 0 ? response.data.RedeemedPack.RedeemedProducts[0].OrderNumber : null;
                            redeemed = true;
                            $scope.redeeming = false;
                            $scope.$scrollTop(0);
                        },
                            function (message) {
                                $scope.redeeming = false;
                                Common.showMessage('error', 'Error redeeming the reward.');
                                $log.log('Error redeeming product', message);
                            });
                },

                isRedeemed = function () {
                    // There is no OrderNumber created for trophies yet, so we need to also track via
                    // the redeemed variable.
                    return !!$scope.reward && (!!$scope.reward.OrderNumber || $scope.reward.Status != 1 || redeemed);
                },

                isTrophy = function () {
                    return !!$scope.pack && !$scope.pack.GenerateSAPOrder;
                },

                getNote = function (pack, paymentRequired) {
                    var paymentRequiredMsg = 'A request for final processing information has been sent to your nominating supervisor. Once this information is received, your order will ship within 2-3 weeks.',
                        isTrophyMsg = 'Please allow 8 - 10 weeks for delivery',
                        notTrophyMsg = 'Merchandise orders generally ship next business day',
                        note = notTrophyMsg;

                    if (paymentRequired) {
                        note = paymentRequiredMsg;
                    } else if (!!pack && !pack.GenerateSAPOrder) {
                        note = isTrophyMsg;
                    }

                    return note;
                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },



                swapProductImage = function (product) {
                    if (!!product.selectedConfiguration) {
                        product.Image.urls.lg = getProductImage(product.selectedConfiguration, 'l');
                        product.Image.urls.md = getProductImage(product.selectedConfiguration, '');
                        product.Image.urls.sm = getProductImage(product.selectedConfiguration, 't');
                        product.Image.urls.xs = getProductImage(product.selectedConfiguration, 'tt');
                    }
                },

                rewardProductDiscontinuedFilter = function (child) {

                    if (child.IsDiscontinued && child.QtyAvailable <= 0) {
                        return false;
                    } else {
                        return true;
                    }

                },

                showAddressForm = function () {

                    var reward = $scope.reward,
                        modalInstance = $uibModal.open({
                            templateUrl: 'AddEditRewardShippingAddress.html',
                            controller: 'rewardShippingAddressCtrl as ctrl', //different controller
                            size: 'lg',
                            resolve: {
                                campaign: function () {
                                    return Campaign;
                                },
                                storeCode: function () {
                                    return $rootScope.store.StoreCode;
                                },
                                reward: function () {
                                    return {
                                        OverrideAddress: reward.OverrideAddress,
                                        EmailReplyToAddress: reward.EmailReplyToAddress,
                                        Name: reward.Name,
                                        ShipToAddress: $scope.shipToAddress,
                                        CustomerId: reward.CustomerId,
                                        RewardId: reward.RewardId
                                    };

                                },
                                scope: function () {
                                    return $scope;
                                }
                            }

                        }).result.then(function (shipToAddress) {
                            Common.showMessage('success', 'Address has been updated.');
                            $scope.shipToAddress = shipToAddress;
                        });
                };

            $scope.removeSelectedProduct = removeSelectedProduct;
            $scope.updateRemainingRedemptions = updateRemainingRedemptions;


            $scope.productUI = ProductUIService;
            $scope.rewardService = RewardService;
            $scope.reward = null;
            $scope.editName = false;

            $scope.products = [];

            $scope.rewardId = $routeParams.id;
            $scope.packId = $routeParams.packId;
            $scope.productId = !!$routeParams.productId ? JSON.parse($routeParams.productId) : null;

            $scope.pack = {};

            $scope.redeeming = false;


            $scope.linkTo = function (path) {
                return Common.linkTo(path);
            };

            $scope.swapProductImage = swapProductImage;
            $scope.convertDate = convertDate;
            $scope.isTrophy = isTrophy;
            $scope.getNote = getNote;
            $scope.redeemed = isRedeemed;
            $scope.redeemReward = redeemReward;
            $scope.redirectTo = redirectTo;
            $scope.redirectToSelectAward = redirectToSelectAward;
            $scope.canRedeem = canRedeem;

            $scope.showAddressForm = showAddressForm;


            $scope.toggleEdit = toggleEdit;
            $scope.cancelNameEdit = cancelNameEdit;
            $scope.prepareForNameEdit = prepareForNameEdit;

            $scope.productUI = ProductUIService;
            $scope.rewardProductDiscontinuedFilter = rewardProductDiscontinuedFilter;

            getReward($scope.rewardId);
            $scope.rewardService.getReward($scope.rewardId);
        }])

    .controller('rewardShippingAddressCtrl', [
        'Rewards',
        'Common',
        'Stores',
        'Objects',
        '$uibModalInstance',
        '$scope',
        'campaign',
        'storeCode',
        'reward',
        'scope',
        function (Rewards, Common, Stores, Objects, $uibModalInstance, $scope, campaign, storeCode, reward, scope) {

            var ctrl = this,

                init = function () {

                    //Do we actually have an address (just look at Address 1 to determine that)
                    if (!!reward.ShipToAddress && !!reward.ShipToAddress.Address1)
                        newAddress = angular.copy(reward.ShipToAddress);

                    exposeSelf();

                },


                newAddress = {
                    Name: '',
                    FirstName: '',
                    LastName: '',
                    Address1: '',
                    Address2: '',
                    City: '',
                    State: '',
                    PostalCode: '',
                    County: '',
                    CompanyName: '',
                    Country: 'US',
                    Email: '',
                    PhoneNumber: '',
                    PhoneExtension: ''
                },

                apiStoreCode = storeCode,


                exposeSelf = function () {

                    ctrl.newAddress = newAddress;

                    ctrl.reward = reward || {};

                    ctrl.saveAndUseAddress = saveAndUseAddress;

                    ctrl.cancelChanges = closeModal;
                    ctrl.countries = [];
                    ctrl.countriesLoading = true;
                    Objects.getCountries({ type: 'Shipping' })
                        .then(function (response) {
                            ctrl.countriesLoading = false;
                            ctrl.countries = !!$scope.store.StoreCode && Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                        });

                    ctrl.states = [];
                    ctrl.originalCountry = ctrl.newAddress.Country;
                    Objects.getStateOrRegions({ country: ctrl.originalCountry })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    ctrl.onCountryChanged = onCountryChanged;
                    ctrl.selectOffice = selectOffice;


                    ctrl.close = closeModal;
                    ctrl.scope = scope;
                    ctrl.updateInProgress = false; //I'm doing this because $waiting isn't the best solution for this form.

                    //AR - Leaving in case we ever need to support the address lookup again.
                    ctrl.offices = [];
                    ctrl.officesLoading = false;
                    ctrl.officesPageNum = 1;
                    ctrl.officesTotalNum = 0;
                    ctrl.officesItemsPerPage = 6;
                },

                hideForm = function () {
                    closeModal();
                    ctrl.newAddress = newAddress;
                },

                onCountryChanged = function () {

                    //AR - 78050: All user to enter any address, not just US. I will leave this original code here in case this is something we need to add back in.
                    ctrl.newAddress.State = '';
                    Objects.getStateOrRegions({ country: ctrl.newAddress.Country })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    //AR - Leaving code that toggles between Address Entery form and Address Lookup. In case we ever need to support this again.
                    //if (ctrl.newAddress.Country != 'US') {
                    //    ctrl.officesLoading = true;
                    //    ctrl.officesPageNum = 1;
                    //    ctrl.officesTotalNum = 0;
                    //    Stores.searchAddresses(apiStoreCode, 'Office', "Country=" + ctrl.newAddress.Country)
                    //    .then(function (response) {
                    //        ctrl.officesLoading = false;
                    //        ctrl.officesTotalNum = response.data.length;
                    //        ctrl.offices = segmentize(response.data, ctrl.officesItemsPerPage);
                    //    });
                    //}
                    //else {
                    //    if (ctrl.originalCountry !== 'US')
                    //    {
                    //        //If the original address that we loaded was not US, then clear out the address fields
                    //        ctrl.newAddress = {
                    //            Address1: '',
                    //            Address2: '',
                    //            City: '',
                    //            State: '',
                    //            PostalCode: '',
                    //            County: '',
                    //            CompanyName: '',
                    //            Country: 'US',
                    //            Email: '',
                    //            PhoneNumber: '',
                    //            PhoneExtension: ''
                    //        }

                    //    }
                    //}

                },

                //AR - Leaving in case we ever need to support the address lookup again.
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },


                closeModal = function () {
                    $uibModalInstance.dismiss('cancel');
                },

                //AR - Leaving in case we ever need to support the address lookup again.
                selectOffice = function (selectedAddress) {

                    ctrl.updateInProgress = true;
                    var model = angular.copy(selectedAddress);
                    //Specify that it is a shipping address and use the existing ShipToName put the Name of the office as the CompanyName of the shipping address
                    model.AddressType = 'Shipping';
                    model.CompanyName = model.Name;
                    model.Name = reward.ShipToAddress.Name;
                    updateRewardAddress(reward, model);

                },

                saveAndUseAddress = function (form, newAddress) {

                    ctrl.updateInProgress = true;
                    campaign.getTaxJurisdiction(newAddress, form)
                        .then(function () {
                            if (form.$valid) {

                                var model = {
                                    'AddressType': 'Shipping',
                                    'Name': newAddress.FirstName + ' ' + newAddress.LastName, //newAddress.Name,
                                    'FirstName': newAddress.FirstName,
                                    'LastName': newAddress.LastName,
                                    'Address1': newAddress.Address1,
                                    'Address2': newAddress.Address2,
                                    'Country': newAddress.Country,
                                    'City': newAddress.City,
                                    'State': newAddress.State,
                                    'PostalCode': newAddress.PostalCode,
                                    'Email': newAddress.Email,
                                    'Phone': newAddress.Phone
                                };

                                updateRewardAddress(reward, model);

                            } else {
                                Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                                ctrl.updateInProgress = false;
                                //Common.hideLoader();
                            }
                        }, function () {
                            Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                            ctrl.updateInProgress = false;
                            //Common.hideLoader();
                        });

                },


                updateRewardAddress = function (reward, address) {
                    Rewards.updateRewardShippingAddress(reward.RewardId, address)
                        .then(function (response) {
                            $uibModalInstance.close(address);
                        },
                            function (message) {
                                ctrl.updateInProgress = false;
                                Common.showMessage('error', 'Error saving address.');
                            });

                };




            init();



        }])

    .controller('showRewardProductAdditionalInfoCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'product',
        function ($scope, Common, $uibModalInstance, product) {

            var removeRecipient = function (recipient) {
                Campaign.removeRecipient(recipient);
                $uibModalInstance.close();
            };

            $scope.product = product;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);


;angular
	.module('ecs.ctrl.select-award', [])
	.controller('selectAwardCtrl', [
		'$scope',
		'$location',
		'$routeParams',
		'EcsResource',
		'Products',
		'Common',
		'Customers',
        'Rewards',
        'RewardService',
		'ProductUrlService',
        '$log',
        '$window',
        function ($scope, $location, $routeParams, EcsResource, Products, Common, Customers, Rewards, RewardService, ProductUrlService, $log, $window) {
		   

		    var trophyPack = null,

		    rewardProductId = null,

		    getPack = function (packs) {

		        var pack = null;

		        $.each(packs, function (index) {
		            if (this.RewardPackId == $scope.packId) {
		                pack = this;
		            }
		        });

		        if (pack == null) {
		            $location.path('/awards/error/');
		        }

		        for (var i = 0; i < packs.length; i++) {
		            if (!trophyPack && packs[i].Type === 1) {
		                trophyPack = packs[i];
		                $scope.trophyPackId = trophyPack.RewardPackId;
		            }
		            if (!!trophyPack)
		                break;
		        };

		        // Trophy packs only have 1 group and 1 product - for now.
		        if (!!trophyPack && !!trophyPack.Groups && !!trophyPack.Groups[0] && !!trophyPack.Groups[0].Products && !!trophyPack.Groups[0].Products[0])
		            rewardProductId = trophyPack.Groups[0].Products[0].RewardProductId;

		        $scope.rewardProductId = rewardProductId;

		        return pack;
		    },



		   

		    getNoImageurl = function (size) {
		        return ProductUrlService.getNoImageurl(size);
		    },

		    getProductImage = function (product, size) {
		        if (!product)
		            return getNoImageurl(size);

		        return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
		    },

            getProductImages = function (product) {
                product.Image.urls = {};

                product.Image.urls.lg = getProductImage(product, 'l');
                product.Image.urls.md = getProductImage(product, '');
                product.Image.urls.sm = getProductImage(product, 't');
                product.Image.urls.xs = getProductImage(product, 'tt');
            },

            getProducts = function (reward) {
                var products = null;

                var pack = getPack(reward.Packs);

                // Phase 1, packs on ly have 1 group
                if (!!pack.Groups[0]) {
                    products = pack.Groups[0].Products;
                }

                if (!!products) {
                    for (var i = 0; i < products.length; i++) {
                        getProductImages(products[i]);
                    }
                }

                return products;
            },



		    convertDate = function (date) {
		        return Common.convertJsonDateString(date);
		    },



                customRewardsRedirectToOrderReview = function (rewardId, packId, productId) {

		        Common.linkTo("/awards/review-order/" + rewardId + "/" + packId + "/" + JSON.stringify(productId));
                },

                redirectToOrderReview = function (rewardId, packId, remainingRedemptions) {
                    RewardService.setSelectedProducts(remainingRedemptions, $scope.selectedProducts);
                    Common.linkTo("/awards/review-order/" + rewardId + "/" + packId);
                },

             showProductDetails = function (products, selectedIndex) {
                 if (products[selectedIndex].showDetails) {
                     products[selectedIndex].showDetails = false;
                 } else {
                     for (var i = 0, len = products.length; i < len; i += 1) {
                         products[i].showDetails = false;
                     }
                     products[selectedIndex].showDetails = true;
                 }

                },

                addToSelectedProduct = function (product) {
                    var remainingRedemptions = $scope.remainingRedemptions - product.Quantity;
                    if (remainingRedemptions >= 0) {
                        product = Object.assign({}, product, { Quantity: product.Quantity });
                        $scope.remainingRedemptions = remainingRedemptions;
                        // check if product is already added
                        var pid = $scope.selectedProducts.find((p) => p.RewardProductId === product.RewardProductId);
                        if (pid && !pid.IsConfigurable) { //IsConfigurable is used for getting childProducts
                            $scope.selectedProducts = $scope.selectedProducts.map(p => {
                                if (p.RewardProductId === product.RewardProductId) {
                                    return { ...p, Quantity: p.Quantity + product.Quantity }
                                } else {
                                    return { ...p }
                                }
                            });
                        } else {
                            $scope.selectedProducts = [...$scope.selectedProducts, product];
                        }

                        RewardService.addToSelectedProduct($scope.selectedProducts);
                        Common.showMessage('success', `You have successfully added ${product.Name}. If you wish to check all of the added Products, proceed to the Checkout page.`);
                    } else {
                        Common.showMessage('error', 'Unable to redeem. The Quantity should not be greater than the Total Redemptions Remaining.');
                    }
                },

            getReward = function () {
                Rewards.getReward($scope.rewardId)
				    .then(function (reward) {
				        if (reward.data.Status != 1) {
				            Common.goHome();
				            return;
				        }

                        $scope.reward = reward.data;
                        var remainingRedemptions = $scope.reward.TotalUnitsRedeemable;
                        if (reward.data.RedeemedProducts && reward.data.RedeemedProducts.length > 0) {
                            angular.forEach(reward.data.RedeemedProducts, function (rp) {
                                remainingRedemptions -= rp.Quantity;
                            });
                        }
                        $scope.remainingRedemptions = remainingRedemptions;
                        $scope.products = getProducts($scope.reward);

                        $window.sessionStorage.clear(); //if the user clicks the back button, remove any stored selected products in session storage
				    }, function (reason) {
				        if (reason.status == '400' || reason.status == '401') {
				            $location.path('/awards/error/');
				        } else {
				            var errCode = reason.data ? reason.data.errorCode : undefined;
				            var messageInData = reason.data ? reason.data.message : undefined;
				            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
				            Common.showMessage('danger', message, { errorCode: errCode });
				        }
				    });
            };

		    $scope.linkTo = function (path) {
		        return Common.linkTo(path);
		    };

		    
		    $scope.reward = null;
            $scope.products = [];
            $scope.selectedProducts = [];

		    $scope.rewardId = $routeParams.id;
		    $scope.packId = $routeParams.packId;
		    $scope.rewardProductId = rewardProductId;
		    $scope.convertDate = convertDate;
		    $scope.showProductDetails = showProductDetails;
            $scope.redirectToOrderReview = redirectToOrderReview;
            $scope.customRewardsRedirectToOrderReview = customRewardsRedirectToOrderReview;
            $scope.addToSelectedProduct = addToSelectedProduct;
			$scope.changeFocus = Common.changeFocus;

		    

            getReward();
		}]);;angular
	.module('ecs.ctrl.select-catalog-award', [])
	.controller('selectCatalogAwardCtrl', [
		'$scope',
		'$location',
		'$routeParams',
		'EcsResource',
		'Products',
		'Common',
		'Catalogs',
        'Rewards',
        'RewardService',
		'ProductUrlService',
		'$log',
        '$uibModal',
        '$sce', 
        '$window',
        function ($scope, $location, $routeParams, EcsResource, Products, Common, Catalogs, Rewards, RewardService, ProductUrlService, $log, $uibModal, $sce, $window) {
		   

            var selectedCatalog = [],

                getPack = function (packs) {

                    var pack = null;

                    //Catalog rewards have 1 pack, with the catalogs defined as groups under the pack
                    if (packs.length > 1) {
                        $location.path('/awards/error/');
                    }

                    return packs[0];
                },

                getProductImage = function (product, size) {
                    if (!product)
                        return ProductUrlService.getNoImageurl(size);

                    return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                },

                getProductImages = function (product) {
                    product.Image.urls = {};

                    product.Image.urls.lg = getProductImage(product, 'l');
                    product.Image.urls.md = getProductImage(product, '');
                },


                getCatalogs = function (reward) {
                    var catalogs = [];

                    var pack = getPack(reward.Packs);

                    if (!!pack) {
                        for (var i = 0; i < pack.Groups.length; i++) {
                            var catalogValues = pack.Groups[i].Name.split('|');
                            var catalog = {};
                            catalog.name = catalogValues[0];
                            catalog.slug = catalogValues[1];
                            catalog.displayOrder = pack.Groups[i].DisplayOrder;
                            catalogs.push(catalog);
                        }
                    }

                    return catalogs;
                },

                getProducts = function () {
                    var products = null;

                    var catalogSlug = $scope.selectedCatalog.slug;

                    var params = {
                        ':catalogId': $scope.selectedCatalog.slug,
                        'order': 'NEWEST'
                    };
                    Common.showLoader('121');
                    Catalogs.getCatalogProducts(params)
                        .then(function (response) {
                            $scope.products = response.data.Products;
                            for (var i = 0; i < $scope.products.length; i++) {
                                getProductImages($scope.products[i]);
                            }
                        });

                },



                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },

                customRewardsRedirectToOrderReview = function (rewardId, productSlug) {
                    Common.linkTo("/awards/review-catalog-order/" + rewardId + "/" + productSlug);
                },

                redirectToOrderReview = function (rewardId, remainingRedemptions) {
                    RewardService.setSelectedProducts(remainingRedemptions, $scope.selectedProducts);
                    Common.linkTo("/awards/review-catalog-order/" + rewardId);
                },

                showProductDetails = function (product, selectedIndex) {
                    Common.showLoader('137');

                    Products.getProduct({ ':sku': product.ProductSlug }).then((res) => {
                        Common.hideLoader();

                        var p = res.data;
                        var modalInstance = $uibModal.open({
                            templateUrl: 'RewardCatalogProductDetails.html',
                            controller: 'showRewardCatalogProductDetailsCtrl',
                            size: 'lg',
                            resolve: {
                                product: function () {
                                    return p;
                                }
                            }
                        });

                        //If confirmed, delete the recipient and refresh the list
                        modalInstance.result.then(function (chooseProduct) {
                            if (chooseProduct)
                                $scope.customRewardsRedirectToOrderReview($scope.rewardId, product.ProductSlug);
                        });
                    });
                },

                addToSelectedProduct = function (product) {
                    var remainingRedemptions = $scope.remainingRedemptions - product.Quantity;
                    if (remainingRedemptions >= 0) {
                        product = Object.assign({}, product, { Quantity: product.Quantity });
                        $scope.remainingRedemptions = remainingRedemptions;
                        $scope.selectedProducts = [...$scope.selectedProducts, product];
                        RewardService.addToSelectedProduct($scope.selectedProducts);
                        Common.showMessage('success', `You have successfully added ${product.Name}. If you wish to check all of the added Products, proceed to the Checkout page.`);
                    } else {
                        Common.showMessage('error', 'Unable to redeem. The Quantity should not be greater than the Total Redemptions Remaining.');
                    }
                },

            getReward = function () {
                Rewards.getReward($scope.rewardId)
				    .then(function (reward) {
				        if (reward.data.Status != 1) {
				            Common.goHome();
				            return;
				        }

                        $scope.reward = reward.data;
				        $scope.rewardCatalogs = getCatalogs($scope.reward);
				        $scope.selectedCatalog = $scope.rewardCatalogs[0];
                        $scope.showCatalogSel = ($scope.rewardCatalogs.length > 1);
                        var remainingRedemptions = $scope.reward.TotalUnitsRedeemable;
                        if (reward.data.RedeemedProducts && reward.data.RedeemedProducts.length > 0) {
                            angular.forEach(reward.data.RedeemedProducts, function (rp) {
                                remainingRedemptions -= rp.Quantity;
                            });
                        }
                        $scope.remainingRedemptions = remainingRedemptions;
                        //Get the products in the catalog
                        getProducts();

                        $window.sessionStorage.clear(); //if the user clicks the back button, remove any stored selected products in session storage
				    }, function (reason) {
				        if (reason.status == '400' || reason.status == '401') {
				            $location.path('/awards/error/');
				        } else {
				            var errCode = reason.data ? reason.data.errorCode : undefined;
				            var messageInData = reason.data ? reason.data.message : undefined;
				            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
				            Common.showMessage('danger', message, { errorCode: errCode });
				        }
				    });
            };



		    $scope.linkTo = function (path) {
		        return Common.linkTo(path);
		    };

		    
		    $scope.reward = null;
		    $scope.products = [];
            $scope.rewardCatalogs = [];
            $scope.selectedProducts = [];

		    $scope.rewardId = $routeParams.id;
		    $scope.selectedCatalog = selectedCatalog;
		    $scope.getProducts = getProducts;
		    $scope.convertDate = convertDate;
		    $scope.showProductDetails = showProductDetails;
            $scope.redirectToOrderReview = redirectToOrderReview;
            $scope.customRewardsRedirectToOrderReview = customRewardsRedirectToOrderReview;
            $scope.addToSelectedProduct = addToSelectedProduct;
            $scope.changeFocus = Common.changeFocus;
		    

            getReward();
		}])

        .controller('showRewardCatalogProductDetailsCtrl', [
            '$scope',
            '$uibModalInstance',
            '$sce',
            'Common',
            'ProductUrlService',
            'product',
            'RewardService',
            function ($scope, $uibModalInstance, $sce, Common, ProductUrlService, product, RewardService) {
                $scope.product = product || {};
                $scope.product.DescriptionHTML = $sce.trustAsHtml(product.Description);

                $scope.close = function (chooseProduct) {
                    $uibModalInstance.close(chooseProduct);
                };

                (function initialiseZoomOptions() {
                    RewardService.renderZoomableMultiImage($scope.product);
                })();
            }]);
;angular
	.module('ecs.ctrl.select-charity', [])
	.controller('selectCharityCtrl', [
		'$scope',
		'$location',
		'$routeParams',
		'EcsResource',
		'Products',
		'Common',
		'Customers',
		'Rewards',
		'ProductUrlService',
		'$log',
		function ($scope, $location, $routeParams, EcsResource, Products, Common, Customers, Rewards, ProductUrlService, $log) {
		   

		    var ctrl = this,

		    rewardProductId = null,

		    getNoImageurl = function (size) {
		        return ProductUrlService.getNoImageurl(size);
		    },

		    getProductImage = function (product, size) {
		        if (!product)
		            return getNoImageurl(size);

		        return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
		    },

            getProductImages = function (product) {
                product.Image.urls = {};

                product.Image.urls.lg = getProductImage(product, 'l');
                product.Image.urls.md = getProductImage(product, '');
                product.Image.urls.sm = getProductImage(product, 't');
                product.Image.urls.xs = getProductImage(product, 'tt');
            },


		    convertDate = function (date) {
		        return Common.convertJsonDateString(date);
		    },


            showCharityDetails = function (products, selectedIndex) {
                if (products[selectedIndex].showDetails) {
                    products[selectedIndex].showDetails = false;
                } else {
                    for (var i = 0, len = products.length; i < len; i += 1) {
                        products[i].showDetails = false;
                    }
                    products[selectedIndex].showDetails = true;
                }

            },

            
            redeemReward = function (selectedCharity) {

                Common.showLoader('119');

                var rewardId = ctrl.reward.RewardId,
                    rewardRedemptionDTO = {
                        'RewardId': rewardId,
                        'Type': 3,
                        'RedeemedAs': "Donation to " + selectedCharity,
                        'IsExpired': false
                    };

                Rewards.redeemRewards(rewardId, rewardRedemptionDTO, '100')
                    .then(function (response) {
                        ctrl.reward.OrderNumber = response.data.OrderNumber;
                        ctrl.redeemed = true;
                        ctrl.redeeming = false;
                        $scope.$scrollTop(0);
                        
                    },
                    function (message) {
                        $scope.redeeming = false;
                        Common.showMessage('error', 'Error redeeming the reward.');
                        $log.log('Error redeeming product', message);
                    });
            },

            getReward = function () {
                Rewards.getReward(ctrl.rewardId)
				    .then(function (reward) {
				        if (reward.data.Status != 1) {
				            Common.goHome();
				            return;
				        }

				        ctrl.reward = reward.data;

				    }, function (reason) {
				        if (reason.status == '400' || reason.status == '401') {
				            $location.path('/awards/error/');
				        } else {
				            var errCode = reason.data ? reason.data.errorCode : undefined;
				            var messageInData = reason.data ? reason.data.message : undefined;
				            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
				            Common.showMessage('danger', message, { errorCode: errCode });
				        }
				    });
            };

		    ctrl.linkTo = function (path) {
		        return Common.linkTo(path);
		    };


		    ctrl.reward = null;
		    ctrl.selectedCharity = null;
		    ctrl.rewardId = $routeParams.id;
		    ctrl.convertDate = convertDate;
		    //ctrl.showCharityDetails = showCharityDetails;
			ctrl.redeemReward = redeemReward;
			$scope.changeFocus = Common.changeFocus;



		    getReward();
		}]);;angular
	.module('ecs.ctrl.select-points', [])
	.controller('selectPointsCtrl', [
		'$scope',
		'$location',
		'$routeParams',
		'EcsResource',
		'Products',
		'Common',
		'Customers',
		'Rewards',
		'ProductUrlService',
		'$log',
		function ($scope, $location, $routeParams, EcsResource, Products, Common, Customers, Rewards, ProductUrlService, $log) {
		   

		    var ctrl = this,

		    rewardProductId = null,

		    getNoImageurl = function (size) {
		        return ProductUrlService.getNoImageurl(size);
		    },

		    getProductImage = function (product, size) {
		        if (!product)
		            return getNoImageurl(size);

		        return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
		    },

            getProductImages = function (product) {
                product.Image.urls = {};

                product.Image.urls.lg = getProductImage(product, 'l');
                product.Image.urls.md = getProductImage(product, '');
                product.Image.urls.sm = getProductImage(product, 't');
                product.Image.urls.xs = getProductImage(product, 'tt');
            },


		    convertDate = function (date) {
		        return Common.convertJsonDateString(date);
		    },



             showDetails = function (products, selectedIndex) {
                 if (products[selectedIndex].showDetails) {
                     products[selectedIndex].showDetails = false;
                 } else {
                     for (var i = 0, len = products.length; i < len; i += 1) {
                         products[i].showDetails = false;
                     }
                     products[selectedIndex].showDetails = true;
                 }

             },

             redeemReward = function (selectedMethod) {

                 Common.showLoader('119');

                 var rewardId = ctrl.reward.RewardId,
                     rewardRedemptionDTO = {
                         'RewardId': rewardId,
                         'Type': 0,
                         'RedeemedAs': "Points",
                         'IsExpired': false
                     };

                 Rewards.redeemRewards(rewardId, rewardRedemptionDTO, '100')
                     .then(function (response) {
                         ctrl.reward.OrderNumber = response.data.OrderNumber;
                         ctrl.redeemed = true;
                         ctrl.redeeming = false;
                         $scope.$scrollTop(0);
                     },
                     function (message) {
                         $scope.redeeming = false;
                         Common.showMessage('error', 'Error redeeming the reward.');
                         $log.log('Error redeeming product', message);
                     });
             },

            getReward = function () {
                Rewards.getReward(ctrl.rewardId)
				    .then(function (reward) {
				        if (reward.data.Status != 1) {
				            Common.goHome();
				            return;
				        }

				        ctrl.reward = reward.data;

				    }, function (reason) {
				        if (reason.status == '400' || reason.status == '401') {
				            $location.path('/awards/error/');
				        } else {
				            var errCode = reason.data ? reason.data.errorCode : undefined;
				            var messageInData = reason.data ? reason.data.message : undefined;
				            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
				            Common.showMessage('danger', message, { errorCode: errCode });
				        }
				    });
            };

		    ctrl.linkTo = function (path) {
		        return Common.linkTo(path);
		    };

		    
		    ctrl.reward = null;
		    ctrl.redeemed = false;
		    ctrl.rewardId = $routeParams.id;
		    ctrl.redeemReward = redeemReward;
		    ctrl.convertDate = convertDate;
		    ctrl.selectedRedemptionMethod = "Visa Gift Card";

			$scope.changeFocus = Common.changeFocus;

            getReward();
		}]);;angular
.module('ecs.ctrl.select-group', [])
.controller('selectGroupCtrl', [
    '$scope',
    '$location',
    '$routeParams',
    'EcsResource',
    'Products',
    'Common',
    'Customers',
    'Rewards',
    'ProductUrlService',
    function ($scope, $location, $routeParams, EcsResource, Products, Common, Custommers, Rewards, ProductUrlService) {
       

        var rewardId = $routeParams.id,
            packId   = $routeParams.packId,

            getPack = function (packId, reward) {
                var pack = null;

                if (!reward || !reward.Packs)
                    return pack;

                $.each(reward.Packs, function (index) {
                    if (this.RewardPackId == packId) {
                        pack = setDefaultGroupProduct(this);
                    }
                });

                if (pack == null) {
                    $location.path('/awards/error/');
                }

                return pack;
            },

            getTrophyPack = function (reward) {
                if (reward == null) {
                    $location.path('/awards/error/');
                }

                var trophyPack = null;

                for (var i = 0; i < reward.Packs.length; i++) {
                    if (!trophyPack && !reward.Packs[i].GenerateSAPOrder) {
                        trophyPack = reward.Packs[i];
                        $scope.trophyPackId = trophyPack.RewardPackId;
                    }
                    if (!!trophyPack)
                        break;
                };

                // Trophy packs only have 1 group and 1 product - for now.
                if (!!trophyPack && !!trophyPack.Groups && !!trophyPack.Groups[0] && !!trophyPack.Groups[0].Products && !!trophyPack.Groups[0].Products[0])
                    $scope.trophyProductId = trophyPack.Groups[0].Products[0].RewardProductId;

                return;
            },

            //If a group contains only one product, the auto selecte it.
            setDefaultGroupProduct = function (pack) {
                $.each(pack.Groups, function (index) {
                    if (this.Products.length == 1) {
                        this.SelectedProduct = this.Products[0];
                    }
                    else {
                        this.SelectedProduct = null;
                    }
                });

                return pack;
            },

            getNoImageurl = function (size) {
                return ProductUrlService.getNoImageurl(size);
            },

            getProductImage = function (product, size) {
                if (!product)
                    return getNoImageurl(size);

                return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
            },

            getProductImages = function (product) {
                product.Image.urls = {};

                product.Image.urls.lg = getProductImage(product, 'l');
                product.Image.urls.md = getProductImage(product, '');
                product.Image.urls.sm = getProductImage(product, 't');
                product.Image.urls.xs = getProductImage(product, 'tt');
            },

            setProductImages = function (pack) {
                if (!!pack) {
                    $.each(pack.Groups, function (index) {
                        if (!!pack.Groups) {
                            $.each(this.Products, function (index) {
                                this.Image.urls = {};

                                this.Image.urls.lg = getProductImage(this, 'l');
                                this.Image.urls.md = getProductImage(this, '');
                                this.Image.urls.sm = getProductImage(this, 't');
                                this.Image.urls.xs = getProductImage(this, 'tt');
                            });
                        }
                    });
                }
            },



            getReward = function (rewardid) {

                Rewards.getReward(rewardid).
                    then(function (reward) {
                        if (reward.data.Status != 1) {
                            Common.goHome();
                            return;
                        }

                        $scope.reward = reward.data;
                        $scope.pack = getPack(packId, $scope.reward);
                        setProductImages($scope.pack);
                        getTrophyPack($scope.reward);
                        //$scope.reward.PersonalizedName = $scope.reward.RecipientName;
                        //getChildProducts();
                    }, function (reason) {
                        if (reason.status == '400' || reason.status == '401') {
                            $location.path('/awards/error/');
                        } else {
                            var errCode = reason.data ? reason.data.errorCode : undefined;
                            var messageInData = reason.data ? reason.data.message : undefined
                            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                            Common.showMessage('danger', message, { errorCode: errCode });
                        }
                    });
            },

            showProductDetails = function (products, selectedIndex) {
                if (products[selectedIndex].showDetails) {
                    products[selectedIndex].showDetails = false;
                } else {
                    for (var i = 0, len = products.length; i < len; i += 1) {
                        products[i].showDetails = false;
                    }
                    products[selectedIndex].showDetails = true;
                }

            },


            showProducts = function (group) {
                $scope.isShowingProduct = true;
                $scope.selectedGroup = group;
                $scope.products = angular.extend([], group.Products);
            },

            addToSelectedProducts = function (product) {
                $.each($scope.reward.Packs, function (index) {
                    var pack = this;
                    if (pack.RewardPackId == packId) {
                        $.each(pack.Groups, function (index) {
                            var group = this;
                            if (group.RewardPackGroupId == $scope.selectedGroup.RewardPackGroupId) {
                                group.SelectedProduct = product;
                            }
                        });
                    }
                });
                $scope.selectedProducts.push(product);

                $scope.isShowingProduct = false;
            },

            checkProductSelection = function () {
                var selectedProducts = 0;

                if (!$scope.pack)
                    return false;

                $.each($scope.pack.Groups, function (index) {
                    if (this.SelectedProduct != null) {
                        selectedProducts++;
                    }
                });

                if (selectedProducts != $scope.pack.Groups.length) {
                    return false;
                }
                else {
                    return true;
                }
            },

        

            rediretToOrderReview = function () {
                var ids = [];

                if (!!$scope.pack) {
                    $.each($scope.pack.Groups, function (index) {
                        if (!!this.SelectedProduct) {
                            ids.push(this.SelectedProduct.RewardProductId);
                        }
                    });
                }

                $scope.linkTo('/awards/review-order/' + rewardId + '/' + packId + '/' + JSON.stringify(ids));
            };
        
        $scope.rediretToOrderReview = rediretToOrderReview;
        $scope.isAllProductSelected = checkProductSelection;

        $scope.showProductDetails = showProductDetails;
        $scope.showProducts = showProducts;
        $scope.addToSelectedProducts = addToSelectedProducts;
        $scope.reward = null;
        $scope.products = [];
        $scope.pack = null;
        $scope.selectedProducts = [];
        $scope.selectedGroup = {};
        $scope.isShowingProduct = false;


        $scope.rewardId = rewardId;
        $scope.trophyPackId = null;
        $scope.trophyProductId = null;

        $scope.linkTo = function (path) {
            return Common.linkTo(path);
        };


        getReward(rewardId);

 }]);;angular
    .module('ecs.ctrl.createReward', [])
    .controller('createRewardCtrl', [
        'EcsResource',
        'Stores',
        '$scope',
        'Campaign',
        'Common',
        'Rewards',
        'EcsLocale',
        '$log',
        '$window',
        '$timeout',
        '$uibModal',
        '$rootScope',
        'FileUploader',
        function (EcsResource, Stores, $scope, Campaign, Common, Rewards, EcsLocale, $log, $window, $timeout, $uibModal, $rootScope, FileUploader) {

            var self = this,

                init = function () {

                    getAddresseNames();
                    addEventListeners();
                    exposeSelf();
                    showControlSet(['nominateEmployee']);
                    getAvailableRewards();
                    var today = new Date();
                    var priorDate = new Date().setDate(today.getDate());
                    $scope.eventDateOptions = {
                        minDate: priorDate, // set this to whatever date you want to set
                    }


                    $scope.datePicker = {};
                    $scope.datePicker.opened = false;
                    $scope.ExpirationDate = today;
                    $scope.Today = new Date();
                },

                defaultControlState = {
                    'nominateEmployee': { visible: false },
                    'selectRewardCampaign': { visible: false },
                    'selectSupervisor': { visible: false },
                    'selectGenerateGiftCodes': { visible: false },
                    'addressBlock': { visible: false },
                    'supervisorForm': { visible: false },
                    'recipientTable': { visible: false },
                    'recipientForm': { visible: false },
                    'confirmation': { visible: false },
                    'uploadTable': { visible: false },
                    'giftCodeConfirmation': { visible: false },
                },

                controlState,

                showControlSet = function (arr) {
                    var controlState = angular.copy(defaultControlState);

                    for (var i = 0, len = arr.length; i < len; i += 1) {
                        controlState[arr[i]].visible = true;
                    }

                    self.controlState = controlState;
                },

                addEventListeners = function () {
                    $scope.$on('hideSupervisorEdit', function () {
                        var controls = ['selectSupervisor'];
                        if (self.supervisor) {
                            controls = ['addressBlock', 'recipientTable'];
                        }
                        showControlSet(controls);
                    });
                    $scope.$on('addressUpdated', function () {
                        self.supervisor = Campaign.getSupervisor();
                    });
                },

                updateRecipients = function () {
                    self.recipients = Campaign.getAllRecipients();
                },

                exposeSelf = function () {
                    self.next = next;

                    self.supervisorSelected = supervisorSelected;
                    self.showRecipientForm = showRecipientForm;
                    self.showRecipientAssets = showRecipientAssets;

                    self.recipients = Campaign.getAllRecipients();
                    self.editRecipient = editRecipient;
                    self.removeRecipient = showRemoveRecipientModal;
                    self.createCampaign = createCampaign;
                    self.hasRecipient = hasRecipient;

                    self.createGiftCodes = createGiftCodes;
                    //self.downloadGiftCodes = downloadGiftCodes;

                    self.cancelCampaign = resetEverything;
                    self.createAnotherReward = resetEverything;

                    self.domainEmails = ['@corp-imaging.com', '@ecompanystore.com'];


                    self.confirmationVisible = false;
                    self.addSupervisorFormVisible = true;
                    self.showSupervisorStep = false;
                    self.showRecipientStep = false;
                    self.senderName = "Name, Title";

                    self.showControlSet = showControlSet;
                    self.controlState = controlState;

                    self.updateSupervisor = updateSupervisor;

                    self.start = start;
                    self.startEmailWorkflow = startEmailWorkflow;
                    self.startGCWorkflow = startGCWorkflow;


                },

                start = function () {
                    self.campaignTemplate = self.selectedReward;
                    self.campaignTemplate.EmailFromAddressDomain = self.domainEmails[0];
                    self.campaignTemplate.EmailFromAddressName = 'customercare';
                    showControlSet(['selectRewardCampaign'])
                    $scope.ExpirationDate = new Date();
                    $scope.ExpirationDate.setDate($scope.ExpirationDate.getDate() + self.campaignTemplate.DaysToRedeem);
                    self.campaignTemplate.NamingConvention =
                        self.campaignTemplate.NamingConvention ||
                        App.Session.RewardCampaignNamingConvention;
                    self.ExpirationDate = $scope.ExpirationDate;
                    self.campaignTemplate.TotalUnitsRedeemable = 1; //set initial value to 1
                },

                startEmailWorkflow = function () {
                    showControlSet(['selectSupervisor']);
                    self.campaignTemplate.ExpirationDate = $scope.ExpirationDate;
                    if (self.campaignTemplate.BillToCustomerId == null) {
                        showControlSet(['selectSupervisor']);
                    }
                    else {
                        showControlSet(['recipientTable']);
                    }
                },

                startGCWorkflow = function () {
                    showControlSet(['selectGenerateGiftCodes']);
                },

                showRemoveRecipientModal = function (recipient) {

                    var modalInstance = $uibModal.open({
                        templateUrl: 'RemoveRecipient.html',
                        controller: 'removeRecipientCtrl as ctrl',
                        resolve: {
                            recipient: function () {
                                return recipient
                            }

                        }

                    });
                },

                removeRecipient = function (id) {

                    Campaign.removeRecipient(id);

                },


                resetEverything = function () {
                    $rootScope.$broadcast('resetCreateCampaignForm');

                    showControlSet(['nominateEmployee']);

                    clearRecipients();
                    clearSupervisor();

                    getAddresseNames();

                    self.campaignTemplate = {};
                    self.selectedReward = null;
                    $timeout(function () {
                        $window.scrollTo(0, 0);
                    }, 100);

                    getAvailableRewards();
                },

                clearRecipients = function () {
                    Campaign.resetCampaign();
                    updateRecipients();
                },

                clearSupervisor = function () {
                    self.supervisor = undefined;
                    self.supervisor_temp = undefined;
                },

                editRecipient = function (recipient) {
                    showRecipientForm(true, recipient.id);

                },

                createCampaign = function (form) {
                    if (form.$valid) {
                        self.campaignTemplate.ClonedFromId = self.campaignTemplate.CampaignId;
                        self.campaignTemplate.CreatedBy = $scope.user.Name;

                        self.campaignTemplate.IsTemplate = false;
                        self.campaignTemplate.Status = 4;
                        self.campaignTemplate.LaunchDate = Common.convertToJsonDateString(new Date());
                        var today = new Date();
                        var diffTime = Math.abs(self.campaignTemplate.ExpirationDate - today);
                        self.campaignTemplate.DaysToRedeem = Math.round(diffTime / (1000 * 3600 * 24));
                        self.campaignTemplate.ExpirationDate = Common.convertToJsonDateString(self.campaignTemplate.ExpirationDate);
                        self.campaignTemplate.EmailFromAddress = `${self.campaignTemplate.EmailFromAddressName}${self.campaignTemplate.EmailFromAddressDomain}`;
                        self.campaignTemplate.EmailFromName = self.campaignTemplate.EmailFromAddress;
                        self.campaignTemplate.EmailReplyToAddress = self.campaignTemplate.EmailFromAddress;

                        Common.showLoader('112');
                        Campaign.createCampaign(self.campaignTemplate)
                            .then(function (response) {
                                showConfirmation(true);
                                console.log('create campaign success');
                            }, function (response) {
                                console.log('create campaign error');
                            });

                    } else {
                        //show error
                    }

                },

                createGiftCodes = function (form) {
                    form.$valid = self.ExpirationDate >= new Date();
                    if (form.$valid) {
                        self.campaignTemplate.ClonedFromId = self.campaignTemplate.CampaignId;
                        self.campaignTemplate.CreatedBy = $scope.user.Name;
                        self.campaignTemplate.IsTemplate = false;
                        self.campaignTemplate.Status = 4;
                        self.campaignTemplate.LaunchDate = Common.convertToJsonDateString(new Date());
                        var today = new Date();
                        var diffTime = Math.abs($scope.ExpirationDate - today);
                        self.campaignTemplate.DaysToRedeem = Math.round(diffTime / (1000 * 3600 * 24));

                        //Common.showLoader('112');
                        self.generateRewardCode = {
                            CampaignId: self.campaignTemplate.CampaignId,
                            ExpirationDate: Common.convertToJsonDateString(self.ExpirationDate),
                            CodeCount: self.campaignTemplate.NumberOfGiftCodes,
                            TotalUnitsRedeemable: self.campaignTemplate.TotalUnitsRedeemable
                        }
                        Rewards.createGiftCodes(self.generateRewardCode)
                            .then(function (response) {
                                showGiftCodeConfirmation(true);
                                angular.forEach(response.data, function (data) {
                                    data.ExpirationDate = new Date(Common.convertJsonDateString(data.ExpirationDate));
                                    if (data.ExpirationDate < today) {
                                        data.StatusId = 3; // not really used
                                    }
                                });
                                self.rewardGiftCodes = response.data;
                                console.log('create gift codes success');
                            }, function (response) {
                                console.log('create gift codes error');
                            });
                        //showGiftCodeConfirmation(true);
                    } else {
                        //show error
                        Common.showMessage('danger', 'Redeemed By Date must be date today or date in the future.');
                    }

                },

                //downloadGiftCodes = function () {
                //    alert("Coming soon!");
                //},

                updateSupervisor = function () {
                    showControlSet(['supervisorForm']);
                },


                getAddresseNames = function () {
                    Stores.getAddressNames()
                        .then(function (response) {

                            setTypeAheadArray(response.data);
                        });
                },


                getAvailableRewards = function () {
                    var query = 'isTemplate=true';
                    Campaign.searchCampaigns(0, 1000, query)
                        .then(function (response) {
                            setAvailableRewardsArray(response.data);
                        });
                },

                setAvailableRewardsArray = function (data) {

                    self.availableRewards = data;

                    if (self.availableRewards.length > 0)
                        self.selectedReward = self.availableRewards[0];

                },

                /*
                    Visiblity of sections
                */


                showAddSupervisorForm = function (bool) {

                    self.addSupervisorFormVisible = bool || false;


                },

                showRecipientForm = function (bool, recipientId) {

                    if (bool) {
                        var modalInstance = $uibModal.open({
                            templateUrl: 'AddRecipient.html',
                            controller: 'recipientCtrl as rec',
                            resolve: {
                                recipientId: function () {
                                    return recipientId
                                }

                            }

                        });
                    }
                },

                hasRecipient = function () {
                    return Campaign.hasRecipient();
                },

                showRecipientAssets = function () {
                    var visible = false;

                    if (!self.confirmationVisible && supervisorSelected()) {
                        visible = true;
                    }

                    return visible;
                },

                showConfirmation = function (bool) {

                    showControlSet(['confirmation']);

                },

                showGiftCodeConfirmation = function (bool) {

                    showControlSet(['giftCodeConfirmation']);

                },

                supervisorSelected = function () {

                    return !!(self.supervisor && self.supervisor.AddressId);
                },


                next = function (supervisor) {

                    if (supervisor && supervisor.AddressId) {

                        Campaign.loadSupervisor(supervisor)
                            .then(function (supervisor) {
                                self.supervisor = supervisor;
                                showControlSet(['addressBlock', 'recipientTable']);
                            });

                    } else {
                        showControlSet(['supervisorForm']);
                        self.supervisor_temp = undefined;
                    }

                },

                setTypeAheadArray = function (data) {

                    self.addressNames = data;

                };

            $scope.openDatePicker = function ($event) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.datePicker.opened = true;
            };

            $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/ParseRecipientSpreadSheet", autoUpload: true }),
                $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
                    console.log(status);
                };


            $scope.uploader.onCompleteItem = function (item, response, status, headers) {
                if (response.Error) {
                    $scope.uploadError = true;
                    $scope.uploadErrorList = response.ErrorMessages;
                } else {
                    $scope.uploadError = false;
                    for (var i = 0; i < response.Recipients.length; i++) {
                        var recipient = new Object();
                        recipient.FirstName = response.Recipients[i].FirstName;
                        recipient.LastName = response.Recipients[i].LastName;
                        recipient.Email = response.Recipients[i].EmailAddress;
                        if (recipient.FirstName != "" && recipient.LastName != "" && recipient.Email != "") {
                            Campaign.saveRecipient(recipient, self.campaignTemplate.BillToCustomerId == null);
                        }
                    }

                    updateRecipients();
                    $scope.guestEntryMode = 'none';
                    self.controlState['uploadTable'].visible = false;
                }
                $scope.$apply();
            };

            init();
            $scope.changeFocus = Common.changeFocus;

        }])

    .controller('removeRecipientCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'recipient',
        'Campaign',
        function ($scope, Common, $uibModalInstance, recipient, Campaign) {

            var removeRecipient = function (recipient) {
                Campaign.removeRecipient(recipient);
                $uibModalInstance.close();
            };

            $scope.removeRecipient = removeRecipient;
            $scope.recipient = recipient;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);

;angular
    .module('ecs.ctrl.recipient', [])
    .controller('recipientCtrl', [
        'Stores',
        'Campaign',
        '$uibModalInstance',
        '$scope',
        'recipientId',
        function (Stores, Campaign, $uibModalInstance, $scope, recipientId) {

            var recipient = this,

                init = function () {

                    exposeSelf();
                    isEdit();

                },

                isEdit = function () {
                    if (recipientId) {
                        editRecipient(recipientId);
                    }
                },

                defaultRecipient = {
                    Email: '',
                    FirstName: '',
                    LastName: '',
                },

                
                exposeSelf = function () {
                    
                    recipient.saveRecipient = saveRecipient;
                    
                    recipient.getRecipient = Campaign.getRecipient;

                    recipient.recipient = angular.copy(defaultRecipient);
                    recipient.cancelChanges = closeModal;

                    recipient.close = closeModal;
                },

                hideForm = function () {
                    
                    closeModal();
                    recipient.recipient = angular.copy(defaultRecipient);
                },

                saveRecipient = function (form) {

                    if (form.$valid) {
                        Campaign.saveRecipient(recipient.recipient);
                        form.$submitted = false;
                        hideForm();
                    }
                    
                },

                editRecipient = function (id) {
                    recipient.recipient = angular.copy(Campaign.getRecipient(id));
                },

                getTaxJurisdiction = function (recipient, form) {
                    Campaign.getTaxJurisdiction(recipient, form);
                },
                
                    
                closeModal = function () {
                    $uibModalInstance.dismiss('cancel');
                };


            

            init();

           

        }]);
        

;angular
    .module('ecs.ctrl.supervisor', [])
    .controller('supervisorCtrl', [
        'Stores',
        'Campaign',
        'Customers',
        '$scope',
        '$window',
        '$timeout',
        'Common',
        function (Stores, Campaign, Customers, $scope, $window, $timeout, Common) {

            var ctrl = this,

                init = function () {

                    addEventListeners();
                    exposeSelf();
                    populateStates();
                    populateForm();
                },

                defaultForm = {
                    BillingAddress: {
                        Address1: '',
                        Address2: '',
                        AddressType: 'Billing',
                        City: '',
                        CompanyName: '',
                        Country: '',
                        County: '',
                        Email: '',
                        Extension: '',
                        Name: '',
                        PartnerNumber: '',
                        Phone: '',
                        PostalCode: '',
                        State: '',
                        TaxJurisdictionCode: '',
                        Country: 'US'
                    },

                    shippingSameAsBilling: { value: false, initialValue: false, changed: false },
                    previousShippingAddresses: [],

                    ShippingAddress: {
                        Address1: '',
                        Address2: '',
                        AddressType: 'Shipping',
                        City: '',
                        CompanyName: '',
                        Country: '',
                        County: '',
                        Email: '',
                        Extension: '',
                        Name: '',
                        PartnerNumber: '',
                        Phone: '',
                        PostalCode: '',
                        State: '',
                        TaxJurisdictionCode: '',
                        Country: 'US'
                    }
                    
                    

                },

                 addEventListeners = function () {

                     $scope.$on('resetCreateCampaignForm', function () {
                         ctrl.showSupervisorForm = true;
                         ctrl.showShippingAddressForm = false;
                         ctrl.supervisor = angular.copy(defaultForm);

                     });
                 },

                exposeSelf = function () {
                    ctrl.updateBillingAddress = updateBillingAddress;
                    ctrl.updateShippingAddress = updateShippingAddress;
                    ctrl.cancelChanges = cancelChanges
                    ctrl.toggleShippingSameAsBilling = toggleShippingSameAsBilling;
                    ctrl.showSupervisorForm = true;
                    ctrl.showShippingAddressForm = false;
                },

                populateForm = function () {
                    ctrl.supervisor = angular.copy(Campaign.getSupervisor(defaultForm));
                },

                populateStates = function () {
                    Campaign.setStateCallBack(this, setStates);
                    ctrl.states = Campaign.getStates();
                },

                setStates = function () {
                    ctrl.states = Campaign.getStates();
                },

                toggleShippingSameAsBilling = function (shippingSameAsBilling) {
                    var supervisor = ctrl.supervisor,
                        billing = supervisor.BillingAddress;

                    if (shippingSameAsBilling.value) {
                        if (supervisor.ShippingAddress) {
                            supervisor.previousShippingAddresses = supervisor.previousShippingAddresses || [];
                            supervisor.previousShippingAddresses.push(angular.copy(supervisor.ShippingAddress));
                        }
                        supervisor.ShippingAddress = defaultForm.ShippingAddress;
                        
                    }
                    shippingSameAsBilling.changed = true;
                },

                cancelChanges = function (type) {
                    $scope.$emit('hideSupervisorEdit');
                },

                hideSupervisorEdit = function () {

                    $scope.$emit('hideSupervisorEdit');

                    jumpToTopOfSupervisorForm();

                },

                jumpToTopOfSupervisorForm = function () {

                    $window.scrollTo(0, $('#section-supervisor-form').offset().top);
                },


                updateBillingAddress = function (form) {

                    var supervisor = ctrl.supervisor,
                        errorMessage = 'Could not create billing address. Please correct errors and try again.',
                        billing = supervisor.BillingAddress,
                        isNew = !supervisor.CustomerId,
                        afterAction = function (response) {
                            jumpToTopOfSupervisorForm();
                            ctrl.showSupervisorForm = false;
                            ctrl.showShippingAddressForm = true;
                            ctrl.supervisor = Campaign.getSupervisor();
                            

                            //address object isn't returned when updated, only when created.
                            if (response.BillingAddress && response.BillingAddress.PartnerNumber) {
                                supervisor.PartnerNumber = response.BillingAddress.PartnerNumber;
                            }
                            
                            form.$submitted = false;
                            $scope.$emit('addressUpdated');
                            Common.hideLoader();

                                        
                        };

                    billing.AddressType = 'Billing';
                    resetCityZipErrors(form);

                    if (form.$dirty) {
                        if (form.$valid) {

                            Common.showLoader('118', true); //creating supervisor message

                            Campaign.getTaxJurisdiction(billing, form)
                                .then(function () {
                                    if (form.$valid) {

                                        if (!supervisor.CustomerId) {
                                            billing.StoreCode = 'DKR';
                                            Campaign.createSupervisor(supervisor)
                                                .then(afterAction, Common.hideLoader);
                                        } else {
                                            Campaign.updateAddress(supervisor.CustomerId, billing)
                                                .then(afterAction, Common.hideLoader);
                                        }

                                    } else {
                                        Common.showMessage('fail', errorMessage);
                                        Common.hideLoader();
                                    }
                                }, function () {
                                    Common.showMessage('fail', errorMessage);
                                    Common.hideLoader();
                                });
                        }
                    } else {
                        if (form.$valid) {
                            afterAction({});
                        } else {
                            Common.showMessage('fail', errorMessage);
                            Common.hideLoader();
                        }
                        
                    }
                },

                updateShippingAddress = function (form, closeOnSuccess) {
                    var address = ctrl.supervisor.ShippingAddress,
                        errorMessage = 'Could not create shipping address. Please correct errors and try again.',
                        supervisor = ctrl.supervisor,
                        customerId = supervisor.CustomerId,
                        previousShipping = supervisor.previousShippingAddress,
                        shippingSameAsBilling = supervisor.shippingSameAsBilling,
                        afterAction = function (response) {
                            $scope.shippingAddressForm.$submitted = false;
                            $scope.shippingAddressForm.$setDirty(false);
                            jumpToTopOfSupervisorForm();

                            $scope.$emit('addressUpdated');

                            if (closeOnSuccess) {
                                hideSupervisorEdit();
                            }
                            Common.hideLoader();

                        };

                    if (!supervisor.shippingSameAsBilling.value) {
                        address.AddressType = 'Shipping';
                        address.Country = 'US';
                        resetCityZipErrors(form);

                        if (form.$valid) {

                            if (form.$dirty) {
                                Common.showLoader('120', true); //creating supervisor message

                                Campaign.getTaxJurisdiction(address, form)
                                    .then(function () {
                                        if (form.$valid) {
                                            
                                            if (address.AddressId && address.AddressId !== address.CustomerId) {
                                                Campaign.updateAddress(customerId, address)
                                                    .then(afterAction, Common.hideLoader);
                                            } else {
                                                Campaign.addAddress(customerId, 'Shipping', address)
                                                   .then(afterAction, Common.hideLoader);
                                            }

                                        } else {
                                            Common.showMessage('fail', errorMessage);
                                            Common.hideLoader();
                                        }
                                    }, function () {
                                        Common.showMessage('fail', errorMessage);
                                        Common.hideLoader();
                                    });
                            } else {
                                if (form.$valid) {
                                    afterAction({});
                                } else {
                                    Common.showMessage('fail', errorMessage);
                                    Common.hideLoader();
                                }
                            }

                        }

                    } else if (shippingSameAsBilling.value && shippingSameAsBilling.changed) {
                        clearpreviousShippingAddresses(customerId, supervisor.previousShippingAddresses)
                        afterAction({});
                    } else {
                        //hide form
                        afterAction({});
                    }
                    

                },

                clearpreviousShippingAddresses = function (customerId, previousShippingAddresses) {

                    var deleteElement = function (array, index) {
                        if (index > -1) {
                           return array.splice(index, 1);
                        }
                    };

                    for (var i = 0, len = previousShippingAddresses.length; i < len; i += 1) {

                        var address = deleteElement(previousShippingAddresses, i);

                        if (address && address[0] && address[0].AddressId) {
                            Campaign.deleteAddress(customerId, address[0])
                            .then(function () {

                                console.log('Deleted previous address from database');
                            }, function () {
                                deleteElement(previousShippingAddresses, i);
                                console.log('Error deleting previous address from database.');
                            });
                        }
                    }
                }

                resetCityZipErrors = function (form) {
                    form.City.$setValidity("taxjurisdiction", true);
                    form.PostalCode.$setValidity("taxjurisdiction", true);
                };

            init();

        }]);
        
;angular
	.module('ecs.service.campaign', [])
	.service('Campaign', [
		'$log',
        '$q',
        'Stores',
        'Rewards',
        'RewardsAddress',
        'Campaigns',
        'Customers',
        function ($log, $q, Stores, Rewards, RewardsAddress, Campaigns, Customers) {

		    var campaign = {},
                states = [],
                stateCallback = {},

		        getGuid = function () {
		            function s4() {
		                return Math.floor((1 + Math.random()) * 0x10000)
                          .toString(16)
                          .substring(1);
		            }
		            return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
                      s4() + '-' + s4() + s4() + s4();
		        },

                setStateCallBack = function (scope, method) {
                    stateCallback.method = method;
                    stateCallback.scope = scope;
                },


                getShippingAddressFromAddresses = function (id, data) {

                    try {
                        var shippingAddresses = data.ShippingAddresses,
                            selectedAddress;

                        for (var i = 0, len = shippingAddresses.length; i < len; i += 1) {
                            if (shippingAddresses[i].PartnerNumber !== id) {
                                selectedAddress = shippingAddresses[i];
                                break;
                            }
                        }

                        return selectedAddress;

                    } catch (e) {
                        console.log('campaignService.js - getShippingAddress(): No data found.');
                    }
                    
                },

                getStates = function () {
                    return RewardsAddress.getStatesOrRegions("US")
                        .then(function (response) {
                            states = response.data;
                            if (stateCallback.method && stateCallback.scope) {
                                stateCallback.method.apply(stateCallback.scope);
                                stateCallback = {};
                            }
                        });
                },

                getCampaignDTO = function (data) {

                    return angular.extend(data, {

                        BillToCustomerId: (data.BillToCustomerId == null) ? campaign.getSupervisor().BillingAddress.PartnerNumber : data.BillToCustomerId,
                        Recipients: toArray(campaign.getAllRecipients())
                    });

                },

                toArray = function (obj) {

                    var arr = [];
                    for (var key in obj) {
                        if (obj.hasOwnProperty(key)) {
                            arr.push(obj[key]);
                        }
                    }

                    return arr;
                },

                getSupervisorDTO = function (data) {
                    return angular.extend(data, {
                        AddressType: 'supervisor'
                    })

                },

                cleanAddress = function (address) {
                    delete address.AddressId;
                    delete address.PartnerNumber;
                    delete address[':addressId'];
                    delete address[':customerId'];

                    return address;
                },

                copyAddress = function (address) {
                    
                    return cleanAddress(angular.copy(address));
                },

                setShippingAddress = function (shippingAddress) {
                    campaign.supervisor.ShippingAddress = shippingAddress;
                    return;
                },

                getShippingAddress = function () {

                    var address = campaign.supervisor.ShippingAddress;
                    if (campaign.supervisor.shippingSameAsBilling.value) {
                        address = campaign.supervisor.BillingAddress;
                    }
                    return address;
                },

		        getTaxJurisdiction = function (data, form) {
		            var hasCity = !!data.City;
		            var hasPostalCode = !!data.PostalCode;
		            var isCountryUS = data.Country === 'US';

		            data.County = null;

		            if (hasCity && hasPostalCode && isCountryUS) {
		                return RewardsAddress.getTaxJurisdictions(data.City, data.PostalCode, data.Country)
                            .then(function (response) {
                                data.Counties = response.data;
                                if (data.Counties.length > 0) {
                                    data.County = data.Counties[0].County;
                                    form.City.$setValidity("taxjurisdiction", true);
                                    form.PostalCode.$setValidity("taxjurisdiction", true);
                                }
                                else {
                                    data.Counties = [];
                                    form.City.$setValidity("taxjurisdiction", false);
                                    form.PostalCode.$setValidity("taxjurisdiction", false);
                                }
                            },
                            function (message) {
                                data.Counties = [];
                                form.City.$setValidity("taxjurisdiction", false);
                                form.PostalCode.$setValidity("taxjurisdiction", false);
                                $log.log('Tax Jurisdiction Error', message);
                            });
		            }
		            else {
		                //Just return a deferred promise.
		                var deferred = $q.defer();
		                deferred.resolve(false);
		                return deferred.promise;
		            }

		        };

		    getStates();


		    campaign.resetCampaign = function () {
		        campaign.recipients = {};
		        campaign.supervisor = undefined;
		    },

		    campaign.getTaxJurisdiction = getTaxJurisdiction;

		    campaign.getStates = function () {
		        return states;
		    };

		    campaign.getShippingAddress = getShippingAddress;
		    campaign.setShippingAddress = setShippingAddress;
		    campaign.setStateCallBack = setStateCallBack;
		    campaign.cleanAddress = cleanAddress;
		    campaign.copyAddress = copyAddress;
		    

		    /*
               Recipient
           */

            campaign.recipients = {};

		    campaign.saveRecipient = function (recipient) {

		        if (!recipient.id) {
		            recipient.id = getGuid();
                    if (!!campaign.supervisor) {
		                var address = getShippingAddress()

		                recipient.AddressType = address.AddressType;
		                recipient.CompanyName = address.CompanyName;
		                recipient.SAPPartnerNumber = address.PartnerNumber;
		                recipient.Address1 = address.Address1;
		                recipient.Address2 = address.Address2;
		                recipient.Address3 = address.Address3;
		                recipient.City = address.City;
		                recipient.Region = address.State;
		                recipient.PostalCode = address.PostalCode;
		                recipient.County = address.County;
		                recipient.Country = address.Country;
		                recipient.PhoneExtension = address.PhoneExtension;
		                recipient.PhoneNumber = address.PhoneNumber;
                    }
		        }

		        /*
		        if (recipient.SendToSupervisor)
		            recipient.ShipToName = campaign.getSupervisor().Name;
		        else
		            recipient.ShipToName = '';
                */

		        campaign.recipients[recipient.id] = angular.copy(recipient);
		    };

		    campaign.removeRecipient = function (recipient) {
		        if (campaign.recipients[recipient.id]) {
		            delete campaign.recipients[recipient.id];
		        }

		        return campaign.recipients;

		    };

		    campaign.getAllRecipients = function () {
		        return campaign.recipients;
		    };

		    campaign.getRecipient = function (guid) {
		        return campaign.recipients[guid];
		    };

		    campaign.hasRecipient = function () {
		        return !$.isEmptyObject(campaign.recipients);
		    };

		    /*
                Supervisor
            */

		    campaign.supervisor;

		    campaign.loadSupervisor = function (supervisor) {


		        return Customers.getCustomer(supervisor.AddressId)
                    .then(function (response) {
                        var supervisorData = response.data,
                            shippingAddress = getShippingAddressFromAddresses(supervisor.AddressId, supervisorData);

                        if (!shippingAddress) {
                            //shippingAddress = angular.copy(supervisorData.BillingAddress);
                            supervisorData.shippingSameAsBilling = { value: true, initialValue: true, changed: false };
                        } else {
                            supervisorData.shippingSameAsBilling = { value: false, initialValue: false, changed: false };
                        }

                        supervisorData.ShippingAddress = shippingAddress;

                        return campaign.supervisor = supervisorData;
                        
                    });


            };



            // call campaign.getCampaign
            campaign.getCampaignTemplate = function (campaignid) {
                return Campaigns.getCampaign(campaignid);
            };

		    campaign.updateAddress = function (id, address) {
		        campaign.supervisor[address.AddressType + 'Address'] = address;
		        return Customers.updateAddress(id, address);

                   
		    },

            campaign.addAddress = function (customerId, type, address) {
                //if we've copied the address from billing it can have a :customerId, :addressId, 
                //addressId/partner# equiv to customer id which results in unable to remove. Hence cleanAddress(addr)
               
                return Customers.addAddress(customerId, type, cleanAddress(address))
                        .then(function(response) {
                            return campaign.supervisor[address.AddressType + 'Address'] = response.data;
                        });

            },

            campaign.deleteAddress = function (id, address) {
                return Customers.removeAddress(id, address);


            },


		    campaign.createSupervisor = function (supervisor) {

		        var billingAddr = supervisor.BillingAddress;

		        return Stores.saveBillingAddress(getSupervisorDTO(angular.copy(billingAddr)))
                        .then(function (response) {
                            var data = response.data;
                            return campaign.supervisor = {
                                AddressId: data.AddressId,
                                AddressType: 'Supervisor',
                                Name: data.Name,
                                StoreCode: data.StoreCode,
                                CustomerId: data.CustomerId || data.PartnerNumber,
                                BillingAddress: response.data,
                                ShippingAddress: supervisor.ShippingAddress,
                                shippingSameAsBilling: supervisor.shippingSameAsBilling,
                                previousShippingAddresses: supervisor.previousShippingAddresses
                            };

                        });



		    };

		    campaign.getSupervisor = function (defaultForm) {
		        return campaign.supervisor || defaultForm || {};
		    };

		    campaign.setSupervisorAddress = function (type, address) {
		        if (!campaign.supervisor) {
		            throw (new Error('No supervisor found.'));
		            return;
		        } else {
		            campaign.supervisor[type || 'BillingAddress'] = address;

		            return campaign.supervisor;
		        }

		    };



		    campaign.createCampaign = function (campaignTemplate) {

                return Rewards.createCampaign(getCampaignDTO(campaignTemplate));


		    };

		    campaign.cancelCampaign = function () {
		        //cancel the campaign
		    };

		    campaign.searchCampaigns = function (skip, top, query) {
		        try {
		            return Campaigns.searchCampaigns(skip, top, query)
                        .then(function (response) {
                            return response;
                        });
		        } catch (e) {
		            $log.warn('searchCampaigns () :: Error ', e);
		        }
		    };

		    campaign.addCampaignException = function (campaignid, campaignException) {
		        try {
		            return Campaigns.addCampaignException(campaignid, campaignException)
                        .then(function (response) {
                            return response;
                        });
		        } catch (e) {
		            $log.warn('addCampaignException () :: Error ', e);
		        }
		    };

		    return campaign;
		}]);;angular
    .module('ecs.ctrl.award-exceptions', [])
    .controller('awardExceptionsCtrl', [
        '$scope',
        'Campaign',
        'Common',
        function ($scope, Campaign, Common) {

            $scope.campaigns = [];
            var searchCampaigns = function () {
                    var query = 'Status!=6';
                    Campaign.searchCampaigns(0, 1000, query)
                    .then(function (response) {
                        $scope.campaigns = response.data;
                    });
                };

            searchCampaigns();

            $scope.continueToSave = function (form) {
                if (form.$valid) {
                    var campaignExceptionDTO = { 
                        CampaignId: $scope.campaignId,
                        Employeeid : $scope.employeeId,
                        FullName : $scope.employeeName,
                        Email : $scope.employeeEmail,
                        Comments: $scope.reasonComments
                    };
                    Campaign.addCampaignException($scope.campaignId, campaignExceptionDTO)
                    .then(function (response) {
                        $scope.exceptionAdded = true;
                    });
                } else {
                    Common.showMessage('error', 'Please complete all required fields.');
                }
            };

            $scope.exceptionAdded = false;

        }]);;angular
    .module('ecs.ctrl.shop-points', [])
    .filter('capitalize', function () {
        return function (input) {
            return (!!input) ? input.charAt(0).toUpperCase() + input.substr(1).toLowerCase() : '';
        }
    })
    .controller('shopPointsCtrl', [
        '$scope',
        '$rootScope',
        '$location',
        '$routeParams',
        '$uibModal',
        '$timeout',
        'Products',
        '$log',
        'Common',
        '$filter',
        'Rewards',
        'ProductUrlService',
        'Campaign',
        function shopPointsCtrl($scope, $rootScope, $location, $routeParams, $uibModal, $timeout, Products, $log, Common, $filter, Rewards, ProductUrlService, Campaign) {
            var facetsObj = {}; /* jshint validthis:true */

            var currentUser = ECSStores.CurrentUser,
                redeemed = false;

            var init = function () {
                getReward();
                getItems();
            };

            var getReward = function () {
                Rewards.getReward($scope.rewardId)
                    .then(function (reward) {
                        if (reward.data.Status != 1) {
                            Common.goHome();
                            return;
                        }

                        $scope.reward = reward.data;
                        $scope.pointsRemaining = calculatePointsRemaining();
                        $scope.shipToAddress = $scope.reward.DefaultShippingAddress;
                        $scope.pack = getPack();

                        $scope.reward.awardConfigJSON = JSON.parse(reward.data.AwardConfigJSON);

                        $scope.reward.PersonalizedName = $scope.reward.RecipientName;
                        $scope.paymentRequired = $scope.reward.PaymentRequired;
                    }, function (reason) {
                        if (reason.status == '400' || reason.status == '401') {
                            $location.path('/awards/error/');
                        } else {
                            var errCode = reason.data ? reason.data.errorCode : undefined;
                            var messageInData = reason.data ? reason.data.message : undefined;
                            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                            Common.showMessage('danger', message, { errorCode: errCode });
                        }
                    });
            };

            var getPack = function () {
                var pack = null;
                var reward = $scope.reward;

                if (!reward || !reward.Packs)
                    return pack;

                $.each(reward.Packs, function (index) {
                    //if (this.RewardPackId == $scope.packId) {
                    pack = this;
                    //}
                });

                if (pack == null) {
                    $location.path('/awards/error/');
                }

                return pack;
            };

            var redeemReward = function () {
                Common.showLoader('119');

                var selectedProduct = [];

                $.each($scope.productsToAdd, function (index) {
                    var product = {};
                    product.ProductNumber = !!this.ChildPurchaseProductNumber ? this.ChildPurchaseProductNumber : this.ProductNumber;
                    product.ProductName = !!this.ChildProductName ? this.ChildProductName : this.Name;
                    product.Quantity = this.Quantity;

                    selectedProduct.push(product);
                });

                var rewardRedemptionDTO = {
                    'RewardId': $scope.reward.RewardId,
                    'Type': 0, //Points
                    'RedeemedAs': 'Shop for SWAG',
                    'PersonalizedName': $scope.reward.PersonalizedName,
                    //'ShippingAddress': $scope.shipToAddress, Don't need to provide the shipping address anymore in the redemption. Is already been set in the DB
                    'RedeemedProducts': selectedProduct,
                    'IsExpired': false,
                    'IncludesBase': false
                };

                $scope.redeeming = true;

                Rewards.redeemRewards($scope.reward.RewardId, rewardRedemptionDTO, '100')
                    .then(function (response) {
                        $log.log(response);
                        $scope.reward.OrderNumber = response.data.OrderNumber;
                        redeemed = true;
                        $scope.redeeming = false;
                        $scope.$scrollTop(0);
                    },
                        function (message) {
                            $scope.redeeming = false;
                            Common.showMessage('error', 'Error redeeming the reward.');
                            $log.log('Error redeeming product', message);
                        });
            };


            var getNoImageurl = function (size) {
                return ProductUrlService.getNoImageurl(size);
            };

            var getItems = function ($event, order, sort, append) {
                if ($event) {
                    $event.preventDefault();
                }

                var searchProducts = $scope.searchProducts,
                    skip = skip || 0,
                    top = sort ? searchProducts.length : $scope.searchSettings.RecordsToReturn;

                //If we're appending the results (i.e. get next 25, then skip all the products we've retrieved.
                if (append) {
                    skip = searchProducts.length;
                    $rootScope.$broadcast('loader_show', '103');
                } else {
                    $rootScope.$broadcast('loader_show', '102');
                    if ($('#sidebar').offset())
                        $scope.$scrollTop();
                }

                Products.searchProducts({
                    'skip': skip,
                    'top': top,
                    'pricelevel': '01',
                    'orderBy': order || $scope.sortOrder,
                    'q': 'keyword=' + $scope.searchTerm + ',rewardscampaign=true' + Common.getFacets($scope)
                }).then(function (response) {
                    $scope.searchResults = response.data;
                    displayResults(append, order);
                })
            };

            //display Search results
            var displayResults = function (append, order) {
                $scope.noResults = false;
                $scope.initialSearch = false;
                $scope.lastSearchTerm = $scope.searchTerm;
                if (!$scope.searchResults) {
                    $scope.noResults = true;
                    return;
                }

                if ($scope.searchResults.ShouldRedirect) {
                    //If we got here something is not right, just show no search results
                    $scope.searchProducts = searchResults.Products;
                    $scope.noResults = true;
                }
                else {
                    $scope.searchProducts = append ? $scope.searchProducts.concat($scope.searchResults.Products) : $scope.searchResults.Products;
                    $scope.facets = $scope.searchResults.Facets;
                    facetsObj = Common.updateFacetsObj($scope);
                    $scope.sortOrder = order || $scope.sortOrder;

                    if ($scope.searchProducts.length === 0) {
                        $scope.noResults = true;
                    } else {
                        for (var z = 0; z < $scope.searchProducts.length; z++) {
                            var product = $scope.searchProducts[z];
                            product.Quantity = 0;
                            product.QuantityToAdd = 1;
                            product.ShowChildProducts = false;
                            product.OptionType = product.IsGroup ? (product.ProductNumber.length == product.TemplateProductNumber.length ? 'Color' : 'Size') : '';
                        }

                        //Don't like this, but don't know a better way
                        for (var i = 0; i < $scope.productsToAdd.length; i++) {
                            var productInList = $scope.productsToAdd[i];
                            for (var j = 0; j < $scope.searchProducts.length; j++) {
                                if (productInList.ProductNumber === $scope.searchProducts[j].ProductNumber) {
                                    $scope.searchProducts[j].Quantity = productinList.Quantity;
                                    break;
                                }
                            }
                        }

                        //Did we get the max records to return from the API, hook up the scroll listener, we're done scrolling.
                        //Commenting out. Will get mike to look at it. For now, we'll return top 100 records
                        //if ($scope.searchResults.Products.length >= $scope.searchSettings.RecordsToReturn) {
                        //    var product = $scope.searchProducts[$scope.searchProducts.length - 1];

                        //    $timeout(function () {
                        //        setScrollListener(product.ProductNumber);

                        //    }, 500);
                        //}
                    }

                }
            };

            var loadChildProducts = function (product) {
                if (!product || !product.IsGroup) {
                    product.selectedConfiguration = null;
                    product.childProducts = null;
                    return;
                }

                product.selectedConfiguration = null;
                product.childProducts = null;

                Products.getBackendChildProducts(product.TemplateProductNumber).then(
                    function (response) {
                        product.childProducts = response.data;

                        for (var z = 0; z < product.childProducts.length; z++) {
                            var childProduct = product.childProducts[z];
                            childProduct.Quantity = 0;
                            childProduct.QuantityToAdd = 0;
                            childProduct.ChildPurchaseProductNumber = (!!childProduct.PurchaseProductNumber ? childProduct.PurchaseProductNumber : childProduct.ProductNumber);
                            childProduct.ChildProductName = product.Name + ' - ' + childProduct.Name;
                        }

                        //Don't like this, but don't know a better way
                        for (var i = 0; i < $scope.productsToAdd.length; i++) {
                            var childProductInList = $scope.productsToAdd[i];
                            for (var j = 0; j < product.childProducts.length; j++) {
                                if (childProductInList.ProductNumber === product.childProducts[j].ProductNumber) {
                                    product.childProducts[j].Quantity = childProductInList.Quantity;
                                    break;
                                }
                            }
                        }
                    },
                    function (message) {
                        $log.log('Error getting child products', message);
                    });
            };

            $scope.addProduct = function (product) {
                if (!!product) {
                    var quantityToAdd = parseInt(product.QuantityToAdd);
                    if (quantityToAdd > 0) {
                        var points = calculatePointsRemaining() - (product.Price * quantityToAdd);
                        if (points >= 0) {
                            //Is this product already added
                            if (product.Quantity > 0) {
                                var index = -1;
                                for (var i = 0; i < $scope.productsToAdd.length; i++) {
                                    if ($scope.productsToAdd[i].ProductNumber === product.ProductNumber) {
                                        index = i;
                                        break;
                                    }
                                }
                                //If we found it, increase quantity
                                if (index >= 0) {
                                    product.Quantity = product.Quantity + quantityToAdd;
                                    $scope.productsToAdd[index].Quantity = product.Quantity;
                                }
                            }
                            else {
                                product.Quantity = quantityToAdd;
                                $scope.productsToAdd.push(product);
                            }
                            $scope.pointsRemaining = calculatePointsRemaining();
                        }
                        else {
                            Common.showMessage('error', 'Sorry! This exceeds your available points.');
                        }
                    }
                }
            };

            $scope.removeProduct = function (product) {
                if (!!product) {
                    var index = -1;
                    for (var i = 0; i < $scope.productsToAdd.length; i++) {
                        if ($scope.productsToAdd[i].ProductNumber === product.ProductNumber) {
                            index = i;
                            break;
                        }
                    }
                    //If we found it, increase quantity
                    if (index >= 0) {
                        product.Quantity = 0;
                        $scope.productsToAdd.splice(index, 1);
                        $scope.pointsRemaining = calculatePointsRemaining();
                    }
                }
            };

            $scope.setReviewOrder = function () {
                $scope.reviewOrder = true;
            };

            $scope.resetReviewOrder = function () {
                $scope.reviewOrder = false;
            };

            $scope.goBack = function () {
                //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
                CampaignWizard.goToComponents();
            };

            var sortItems = function ($event, order) {
                getItems($event, order, true);
            };

            /*
            Method setScrollListener
        
            @param id is the ProductNumber property of the last product in the list. 
        
            ProductSearch.html has a repeater that assigns the ProductNumber as the id attribute for each
            product in the list.  In the method below the ProductNumber of the last item in the current 
            list of products is passed in and jquery is used to fetch the DOM elemenet with that id. 
            An interval is then set up to check every 250ms to see if the user has scrolled to the top 
            value of this element, plus a buffer.  Once its within the buffer area the call to getNext is 
            made and the interval is cancelled.
            */

            var scrollListenerInterval = null;
            var setScrollListener = function (id) {
                var target = $('#' + id),
                    buffer = 750; //num of pixels above the element with this id to trigger getNext()

                if (target && target.length > 0) {
                    scrollListenerInterval = setInterval(function () {
                        if ($(window).scrollTop() + buffer >= target.offset().top) {
                            getNext();
                            clearInterval(scrollListenerInterval);
                        }
                    }, 250);
                }
            };

            var getSortLabel = function () {
                var sortLabels = {
                    'NEWEST': 'Newest',
                    'PRICELOW-HI': 'Lowest Price',
                    'PRICEHI-LOW': 'Highest Price',
                    'NAMEA-Z': 'Alphabetical'
                }

                return sortLabels[$scope.sortOrder] || 'Sort Chosen';
            };

            var getNext = function () {
                getItems(null, null, false, true);
            };

            var lookForFacets = function () {
                $timeout(function () {
                    $scope.noFacetsVisible = $(".facets .facet-value").filter(':visible').length === 0;
                }, 100);
            };

            var refineSearch = function (scope, facetToRemove, value) {
                Common.refineSearch($scope, facetToRemove, value);
            };



            var convertDate = function (date) {
                return Common.convertJsonDateString(date);
            };

            var isRedeemed = function () {
                // There is no OrderNumber created for trophies yet, so we need to also track via
                // the redeemed variable.
                return !!$scope.reward && (!!$scope.reward.OrderNumber || $scope.reward.Status != 1 || redeemed);
            };

            var showAddressForm = function () {

                var reward = $scope.reward,
                    modalInstance = $uibModal.open({
                        templateUrl: 'AddEditRewardShippingAddress.html',
                        controller: 'rewardShippingAddressPointsCtrl as ctrl',
                        size: 'lg',
                        resolve: {
                            campaign: function () {
                                return Campaign;
                            },
                            storeCode: function () {
                                return $rootScope.store.StoreCode;
                            },
                            reward: function () {
                                return {
                                    OverrideAddress: reward.OverrideAddress,
                                    EmailReplyToAddress: reward.EmailReplyToAddress,
                                    Name: reward.Name,
                                    ShipToAddress: $scope.shipToAddress,
                                    CustomerId: reward.CustomerId,
                                    RewardId: reward.RewardId
                                };

                            },
                            scope: function () {
                                return $scope;
                            }
                        }

                    }).result.then(function (shipToAddress) {
                        Common.showMessage('success', 'Address has been updated.');
                        $scope.shipToAddress = shipToAddress;
                    });
            };

            var canRedeem = function () {
                var isReadyToRedeem = false;

                if ($scope.productsToAdd.length > 0) {
                    isReadyToRedeem = true;
                }

                return isReadyToRedeem;
            };

            $scope.$on('onRepeatLast', lookForFacets);

            $scope.searchResults = {
            };
            $scope.productsToAdd = [];
            $scope.searchProducts = [];
            $scope.searchTerm = '';
            $scope.lastSearchTerm = '';
            $scope.noResults = false;
            $scope.sortOrder = 'NEWEST';
            $scope.activeFacets = [];
            $scope.facetHidden = {
            };
            $scope.searchSettings = {
                RecordsToReturn: 100
            };

            //Expose methods to scope
            $scope.toggleFacet = Common.toggleFacet;
            $scope.getNext = getNext;
            $scope.sortItems = sortItems;
            $scope.getItems = getItems;
            $scope.changeFocus = Common.changeFocus;

            $scope.getSortLabel = getSortLabel;
            $scope.refineSearch = refineSearch;

            $scope.initialSearch = true;

            $scope.linkTo = function (path) {
                return Common.linkTo(path);
            };

            $scope.reward = null;
            $scope.redeemed = isRedeemed;
            $scope.rewardId = $routeParams.id;
            $scope.canRedeem = canRedeem;
            $scope.redeemReward = redeemReward;
            $scope.convertDate = convertDate;
            $scope.selectedRedemptionMethod = "Visa Gift Card";

            $scope.pack = {
            };

            $scope.redeeming = false;

            $scope.reviewOrder = false;

            $scope.showAddressForm = showAddressForm;

            $scope.pointsRemaining = 0;

            var calculatePointsRemaining = function () {
                var pointsUsed = 0;
                for (var i = 0; i < $scope.productsToAdd.length; i++) {
                    var product = $scope.productsToAdd[i];
                    pointsUsed = pointsUsed + (product.Price * product.Quantity);
                }
                return $scope.reward.Points - pointsUsed;
            };

            $scope.showChildProducts = function (product) {
                if (!!product) {
                    loadChildProducts(product);
                    product.ShowChildProducts = true;
                }
            };

            $scope.addChildProducts = function (product) {
                for (var z = 0; z < product.childProducts.length; z++) {
                    var childProduct = product.childProducts[z];
                    $scope.addProduct(childProduct);
                    childProduct.QuantityToAdd = 0;
                    product.ShowChildProducts = false;
                }
            };

            init();
        }
    ])
    .controller('rewardShippingAddressPointsCtrl', [
        'Rewards',
        'Common',
        'Stores',
        'Objects',
        '$uibModalInstance',
        '$scope',
        'campaign',
        'storeCode',
        'reward',
        'scope',
        function (Rewards, Common, Stores, Objects, $uibModalInstance, $scope, campaign, storeCode, reward, scope) {
            var ctrl = this,

                init = function () {
                    //Do we actually have an address (just look at Address 1 to determine that)
                    if (!!reward.ShipToAddress && !!reward.ShipToAddress.Address1)
                        newAddress = angular.copy(reward.ShipToAddress);

                    exposeSelf();
                },

                newAddress = {
                    Name: '',
                    FirstName: '',
                    LastName: '',
                    Address1: '',
                    Address2: '',
                    City: '',
                    State: '',
                    PostalCode: '',
                    County: '',
                    Country: 'US',
                    Email: '',
                    PhoneNumber: '',
                    PhoneExtension: ''
                },

                apiStoreCode = storeCode,

                exposeSelf = function () {
                    ctrl.newAddress = newAddress;

                    ctrl.reward = reward || {
                    };

                    ctrl.saveAndUseAddress = saveAndUseAddress;
                    ctrl.cancelChanges = closeModal;

                    ctrl.countries = [];
                    ctrl.countriesLoading = true;
                    Objects.getCountries({ type: 'Shipping' })
                        .then(function (response) {
                            ctrl.countriesLoading = false;
                            ctrl.countries = !!$scope.store.StoreCode && Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                        });

                    ctrl.states = [];
                    ctrl.originalCountry = ctrl.newAddress.Country;
                    Objects.getStateOrRegions({ country: ctrl.originalCountry })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });


                    ctrl.onCountryChanged = onCountryChanged;
                    ctrl.selectOffice = selectOffice;

                    ctrl.close = closeModal;
                    ctrl.scope = scope;
                    ctrl.updateInProgress = false; //I'm doing this because $waiting isn't the best solution for this form.

                    //AR - Leaving in case we ever need to support the address lookup again.
                    ctrl.offices = [];
                    ctrl.officesLoading = false;
                    ctrl.officesPageNum = 1;
                    ctrl.officesTotalNum = 0;
                    ctrl.officesItemsPerPage = 6;
                },

                hideForm = function () {
                    closeModal();
                    ctrl.newAddress = newAddress;
                },

                onCountryChanged = function () {
                    //AR - 78050: All user to enter any address, not just US. I will leave this original code here in case this is something we need to add back in.
                    ctrl.newAddress.State = '';
                    Objects.getStateOrRegions({ country: ctrl.newAddress.Country })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    //AR - Leaving code that toggles between Address Entery form and Address Lookup. In case we ever need to support this again.
                    //if (ctrl.newAddress.Country != 'US') {
                    //    ctrl.officesLoading = true;
                    //    ctrl.officesPageNum = 1;
                    //    ctrl.officesTotalNum = 0;
                    //    Stores.searchAddresses(apiStoreCode, 'Office', "Country=" + ctrl.newAddress.Country)
                    //    .then(function (response) {
                    //        ctrl.officesLoading = false;
                    //        ctrl.officesTotalNum = response.data.length;
                    //        ctrl.offices = segmentize(response.data, ctrl.officesItemsPerPage);
                    //    });
                    //}
                    //else {
                    //    if (ctrl.originalCountry !== 'US') {
                    //        //If the original address that we loaded was not US, then clear out the address fields
                    //        ctrl.newAddress = {
                    //            Address1: '',
                    //            Address2: '',
                    //            City: '',
                    //            State: '',
                    //            PostalCode: '',
                    //            County: '',
                    //            CompanyName: '',
                    //            Country: 'US',
                    //            Email: '',
                    //            PhoneNumber: '',
                    //            PhoneExtension: ''
                    //        }
                    //    }
                    //}
                },

                //AR - Leaving in case we ever need to support the address lookup again.
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },

                closeModal = function () {
                    $uibModalInstance.dismiss('cancel');
                },

                //AR - Leaving in case we ever need to support the address lookup again.
                selectOffice = function (selectedAddress) {
                    ctrl.updateInProgress = true;
                    var model = angular.copy(selectedAddress);
                    //Specify that it is a shipping address and use the existing ShipToName 
                    model.AddressType = 'Shipping';
                    model.CompanyName = model.Name;
                    model.Name = reward.ShipToAddress.Name;
                    updateRewardAddress(reward, model);
                },

                saveAndUseAddress = function (form, newAddress) {

                    ctrl.updateInProgress = true;
                    campaign.getTaxJurisdiction(newAddress, form)
                        .then(function () {
                            if (form.$valid) {
                                var model = {
                                    'AddressType': 'Shipping',
                                    'Name': newAddress.FirstName + ' ' + newAddress.LastName, //reward.ShipToAddress.Name,
                                    'FirstName': newAddress.FirstName,
                                    'LastName': newAddress.LastName,
                                    'Address1': newAddress.Address1,
                                    'Address2': newAddress.Address2,
                                    'Country': newAddress.Country,
                                    'City': newAddress.City,
                                    'State': newAddress.State,
                                    'PostalCode': newAddress.PostalCode,
                                    'Email': newAddress.Email,
                                    'Phone': newAddress.Phone
                                };

                                updateRewardAddress(reward, model);
                            } else {
                                Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                                ctrl.updateInProgress = false;
                                //Common.hideLoader();
                            }
                        }, function () {
                            Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                            ctrl.updateInProgress = false;
                            //Common.hideLoader();
                        });
                },

                updateRewardAddress = function (reward, address) {
                    Rewards.updateRewardShippingAddress(reward.RewardId, address)
                        .then(function (response) {
                            $uibModalInstance.close(address);
                        },
                            function (message) {
                                ctrl.updateInProgress = false;
                                Common.showMessage('error', 'Error saving address.');
                            });
                };

            init();

        }]);
;angular
    .module('ecs.ctrl.rewards', [])
    .controller('rewardsCtrl', [
        '$scope',
        '$uibModal',
        'EcsResource',
        'CartService',
        'ProductUrlService',
        'Customers',
        'Common',
        'Rewards',
        'EcsLocale',
        '$log',
        '$sce',
        function ($scope, $uibModal, EcsResource, CartService, ProductUrlService, Customers, Common, Rewards, EcsLocale, $log, $sce) {

            var rewardsCtrl = this,

                currentReward = null,

                trophyPack = null,
                swagPack = null,

                availableProducts = {},

                initializeRewards = function (rewards) {
                    var unclaimedRewards = [],
                        historicalRewards = {},
                        historicalRewardTypes = [];

                    for (var i = 0, len = rewards.length; i < len; i += 1) {
                        var reward = rewards[i],
                            type = (!!reward.RewardCategory) ? reward.RewardCategory : "Other " + App.Session.RewardCampaignNamingConvention + "s";


                        reward.expirationDateObj = Common.convertJsonDateObject(reward.ExpirationDate);
                        reward.htmlDescription = $sce.trustAsHtml(reward.Description)

                        var redeemedOn = null;
                        var orderNumber = null;
                        reward.redemptions = [];
                        
                        angular.forEach(reward.RedeemedProducts, function (rp) {

                            if (redeemedOn !== rp.RedeemedDate || orderNumber != rp.OrderNumber) {
                                var redemption = {};
                                var redeemedAs = "";

                                redeemedOn = rp.RedeemedDate;
                                orderNumber = rp.OrderNumber;
                                redemption.redeemedOn = EcsLocale.convertDate(Common.convertJsonDateObject(rp.RedeemedDate));
                                redemption.orderNumber = orderNumber;

                                var redeemedProducts = reward.RedeemedProducts.filter(p => p.RedeemedDate === redeemedOn && p.OrderNumber === orderNumber);

                                var redeemedProductNames = redeemedProducts.map(rp => rp.RedeemedAs);
                                redeemedProductNames = [...new Set(redeemedProductNames)];

                                angular.forEach(redeemedProductNames, function (rpn) {
                                    redeemedAs = redeemedAs + ", " + rpn;
                                })
                                redemption.redeemedAs = redeemedAs.substring(2);
                                redemption.redeemedProducts = redeemedProducts;
                                reward.redemptions.push(redemption);
                            }
                        });

                        if (reward.Status === 1) {
                            reward.redirectText = 'OK, I want to see my options...';
                            //If it's Just Award or Just SWAG and we don't have any points, check if there is only one product available
                            //If there really is only 1 product, the button should just be "Confirm My Info".
                            if ((reward.CampaignComponentType === 1 || reward.CampaignComponentType === 2) && reward.Points <=0 ) {
                                var packProducts = getPackProducts(reward.Packs[0]);
                                if (packProducts != undefined && packProducts.length == 1) {
                                    reward.redirectText = 'Confirm My Info';
                                }
                            }
                            unclaimedRewards.push(setUnclaimedRewardOptions(reward));
                        } else if (reward.Status === 2){
                            
                            if ($.inArray(type, historicalRewardTypes) === -1) {
                                historicalRewardTypes.push(type);
                                historicalRewards[type] = [];
                            }
                            
                            historicalRewards[type].push(setRewardImagePaths(reward));
                        }
                    }

                    for (var i = 0, len = historicalRewardTypes.length; i < len; i += 1) {
                        historicalRewards[historicalRewardTypes[i]] = sortyByExpirationDate(historicalRewards[historicalRewardTypes[i]]);
                    }

                    rewardsCtrl.unclaimedRewards = sortyByExpirationDate(unclaimedRewards);
                    rewardsCtrl.historicalRewards = historicalRewards;
                    rewardsCtrl.historicalRewardTypes = historicalRewardTypes;
                    
                    setCurrentReward();
                    
                    
                },

                mobileRewardLinks = undefined,

                toggleMobileRewardSelector = function () {
                    rewardsCtrl.showMobileRewardSelector = !rewardsCtrl.showMobileRewardSelector;
                    if (!mobileRewardLinks) {
                        mobileRewardLinks = $('#mobileRewardSelector a').not('.accordion-toggle');
                        mobileRewardLinks.click(toggleMobileRewardSelector);
                    }
                
                },

                setCurrentReward = function (reward) {

                    
                    if (!reward) {
                        //Not passed in, then just grap first uncalaimed if we have one.
                        rewardsCtrl.currentReward = null;
                        if (rewardsCtrl.unclaimedRewards.length > 0) {
                            rewardsCtrl.currentReward = rewardsCtrl.unclaimedRewards[0];
                        }
                    }
                    else {
                        rewardsCtrl.currentReward = reward;
                        if (!!rewardsCtrl.unclaimedSelector)
                            rewardsCtrl.unclaimedSelector.open = false;
                    }
                },

                sortyByExpirationDate = function (rewards) {
                    return rewards.sort(function (a, b) {
                        if (a.expirationDateObj < b.expirationDateObj) {
                            return -1;
                        } else if (b.expirationDateObj < a.expirationDateObj) {
                            return 1;
                        } else {
                            return 0;
                        }
                    });

                },

                getRewards = function () {
                    Customers.getAwards($scope.user.CustomerId)
                    .then(function (response) {
                        if (!!response.data && response.data.length > 0) {

                            initializeRewards(response.data); 
                            
                        }
                        setPageReady();
                    });
                },

                setRewardImagePaths = function (reward) {
                    angular.forEach(reward.redemptions, function (redemption) {
                        angular.forEach(redemption.redeemedProducts, function (product, i) {
                            var imageUrls = {};

                            if (!!product.Image) {
                                imageUrls.lg = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, 'L');
                                imageUrls.md = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension);
                            }
                            else {
                                product.Image = {};
                                imageUrls.lg = '';
                                imageUrls.md = '';
                            }

                            $.extend(product.Image, imageUrls);
                        });
                    });
                                                                
                    return reward;
                },

                setUnclaimedRewardOptions = function (reward) {
                    var trophyPack,
                        swagPack;

                    for (var i = 0; i < reward.Packs.length; i++) {
                        if (!trophyPack && reward.Packs[i].IsDefault) {
                            trophyPack = reward.Packs[i];
                        }
                            
                        if (!swagPack && !reward.Packs[i].IsDefault) {
                            swagPack = reward.Packs[i];
                        }

                        if (!!trophyPack && !!swagPack) {
                            break;
                        }
                            
                    };

                    if (!!trophyPack) {
                        setImageUrls(trophyPack);
                    }

                    if (!!swagPack) {
                        setImageUrls(swagPack);
                    }


                            
                    reward.trophyPack = trophyPack;
                    reward.swagPack = swagPack;

                    return reward;
                },

                setImageUrls = function (pack) {
                    var urls = {};

                    urls.lg = getMainImageUrl(pack, 'l');
                    urls.md = getMainImageUrl(pack);
                    urls.sm = getMainImageUrl(pack, 'tt');

                    pack.imageUrls = urls;
                },

                setPageReady = function () {
                    rewardsCtrl.pageReady = true;
                },

                getMainImageUrl = function (pack, size) {
                    var imageUrl,
                        product = getProduct(pack);

                    if (product) {
                        imageUrl = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                    } else {
                        imageUrl = ProductUrlService.getNoImageUrl(size);
                    }

                    return imageUrl;
                },


                linkTo = function (path) {
                    Common.linkTo(path);
                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },

                showMyOptions = function () {

                    rewardsCtrl.landing = false;

                },

                // Phase 1, packs only have 1 group with 1 product
                getProduct = function (pack) {
                    if (!!pack.Groups && !!pack.Groups[0] && !!pack.Groups[0].Products && !!pack.Groups[0].Products[0])
                        return pack.Groups[0].Products[0];
                    return null;
                },

                //redirect to pages based on award offerings

                redirectTo = function () {
                    var reward = rewardsCtrl.currentReward;

                    //Is this a campaign based 
                    if (reward.CampaignComponentType == 5) {
                        rewardsCtrl.linkTo('/awards/select-catalog-award/' + reward.RewardId);
                        return;
                    }

                    if (!reward.Packs)
                        return;

                    //Do we have more than 1 pack or do we have points, go to select-pack to choose the options
                    if (reward.Packs.length > 1 || reward.Points > 0) {
                        rewardsCtrl.linkTo('/awards/select-pack/' + reward.RewardId);
                        return;
                    }

                    //Bad data - No Group in Pack
                    if (!reward.Packs[0].Groups)
                        return;

                    //We've got a single pack, but with more than 1 group, go to select-group to choose
                    if (reward.Packs[0].Groups.length > 1) {
                        rewardsCtrl.linkTo('/awards/select-group/' + reward.RewardId + '/' + reward.Packs[0].RewardPackId);
                        return;
                    }

                    //Otherwise it's based on the number of products in the pack, if only one go straight to Review Order page
                    var products = getPackProducts(reward.Packs[0]);
                    if (products.length > 1) {
                        rewardsCtrl.linkTo('/awards/select-award/' + reward.RewardId + '/' + reward.Packs[0].RewardPackId);
                        return;
                    }
                    else {
                        rewardsCtrl.linkTo("/awards/review-order/" + reward.RewardId + "/" + reward.Packs[0].RewardPackId + "/" + "[" + reward.Packs[0].Groups[0].Products[0].RewardProductId + "]");
                        return;
                    }

                    return;
                },

                showHistoricalReward = function (reward) {

                    //rewardCtrl.currentHistoricalReward = reward;

                    var modalInstance = $uibModal.open({
                        templateUrl: 'historicalRewardTemplate',
                        controller: 'HistoricalRewardModalCtrl',
                        resolve: {
                            reward: function () {
                                return reward;
                            }

                    }
                    });
                    
                },

                getPackProducts = function (pack) {
                    var packProducts = [];

                    for (var i = 0; i < pack.Groups.length; i++) {
                        var group = pack.Groups[i];
                        if (!!group.Products) {
                            packProducts = $.extend(packProducts, group.Products);
                        }
                    }

                    return packProducts;
                };


            rewardsCtrl.showHistoricalReward = showHistoricalReward;
            rewardsCtrl.currentReward = currentReward;
            rewardsCtrl.trophyPack = trophyPack;
            rewardsCtrl.swagPack = swagPack;

            rewardsCtrl.linkTo = linkTo;
            rewardsCtrl.convertDate = convertDate;
            rewardsCtrl.getProduct = getProduct;
            rewardsCtrl.showMyOptions = showMyOptions;
            rewardsCtrl.landing = true;

            rewardsCtrl.redirectTo = redirectTo;
            rewardsCtrl.setCurrentReward = setCurrentReward;
            rewardsCtrl.toggleMobileRewardSelector = toggleMobileRewardSelector;

            getRewards();

            


        }])
    .controller('HistoricalRewardModalCtrl', [
        '$scope',
        '$uibModalInstance',
        'reward',
        function ($scope, $uibModalInstance, reward) {
            
            $scope.reward = reward;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);
        ;angular
    .module('ecs.ctrl.search-rewards', [])
    .controller('searchRewardsCtrl', [
        '$scope',
        'Common',
        'Customers',
        'Rewards',
        'RewardService',
        '$uibModal',
        function ($scope, Common, Customers, Rewards, RewardService, $uibModal) {

            var showIfNoData = false,

                searchByDateRange = function ($event, filter) {
                    if ($event)
                        $event.preventDefault();

                    if (filter) {
                        $scope.selectedFilter = filter;
                    }
                    var query = 'STORECODE=' + $scope.store.StoreCode + ',' + 'LAUNCHDATE:' + $scope.selectedFilter.query + ',' + 'globalsearch=' + $scope.searchQuery;
                    Common.showLoader('132');
                    Rewards.searchRewards(0, 10000, query)
                        .then(function (response) {
                            setRewards(response.data);
                        });
                },

                setRewards = function (data) {
                    searchRewards = data;

                    $scope.showIfNoData = true;
                    var today = new Date();

                    for (var i = 0; i < searchRewards.length; i++) {

                        searchRewards[i].ExpirationDate = Common.convertJsonDateString(searchRewards[i].ExpirationDate);
                        var expirationDate = Date.parse(searchRewards[i].ExpirationDate);
                        searchRewards[i].CanReset = (searchRewards[i].Status === 2 && expirationDate > today);
                        searchRewards[i].CanResend = (searchRewards[i].Status === 1 && expirationDate > today && searchRewards[i].PromoCode == null);
                        searchRewards[i].LaunchDate = Common.convertJsonDateString(searchRewards[i].LaunchDate);

                        if (searchRewards[i].Status === 3)
                            searchRewards[i].StatusName = 'Expired/Not Redeemed'
                        else if (searchRewards[i].Status === 0)
                            searchRewards[i].StatusName = 'Pending Email'
                        else if (searchRewards[i].Status === 1)
                            searchRewards[i].StatusName = 'Pending Redemption'
                        else if (searchRewards[i].Status === 2) {

                            // EST-410413: Get RedeemedAs value from RedeemedProducts objectCanReset
                            if (searchRewards[i].RedeemedProducts.length > 0) {
                                
                                searchRewards[i].RedeemedProducts.forEach((item) => {
                                    if (item.RedeemedAs) {
                                        if (!searchRewards[i].StatusName) {
                                            searchRewards[i].StatusName = 'Redeemed as ';
                                        }
                                        searchRewards[i].StatusName += `${item.RedeemedAs}, `;
                                    }
                                    
                                });
                            } else {
                                searchRewards[i].StatusName = "";
                            }
                        };

                        $scope.showIfNoData = false;

                    }

                    $scope.searchRewards = searchRewards;
                },

                showResetRewardModal = function (reward) {

                    var modalInstance = $uibModal.open({
                        templateUrl: 'ResetReward.html',
                        controller: 'ResetRewardCtrl as ctrl',
                        resolve: {
                            reward: function () {
                                return reward;
                            }
                        }
                    });

                    modalInstance.result.then(function (reward) {
                        resetReward(reward.RewardId);
                    });
                },

                showResendRewardModal = function (reward) {

                    var modalInstance = $uibModal.open({
                        templateUrl: 'ResendReward.html',
                        controller: 'ResendRewardCtrl as ctrl',
                        resolve: {
                            reward: function () {
                                return reward;
                            }
                        }
                    });

                    modalInstance.result.then(function (reward) {
                        resendReward(reward);
                    });
                },

                resendReward = function (reward) {
                    Common.showLoader('133');
                    Rewards.resendReward(reward.RewardId, reward.RecipientEmail).then(function (response) {
                        for (var i in $scope.searchRewards) {
                            if ($scope.searchRewards[i].RewardId == reward.RewardId) {
                                $scope.searchRewards[i].Status = 0;
                                $scope.searchRewards[i].StatusName = 'Pending Email';
                                $scope.searchRewards[i].CanResend = false;
                                $scope.searchRewards[i].CanReset = false;
                                break;
                            }
                        }
                        Common.showMessage('success', '673');


                    });
                },

                resetReward = function (rewardId) {
                    Common.showLoader('131');
                    Rewards.resetReward(rewardId).then(function (response) {

                        for (var i in $scope.searchRewards) {
                            if ($scope.searchRewards[i].RewardId == rewardId) {
                                $scope.searchRewards[i].Status = 1;
                                $scope.searchRewards[i].StatusName = 'Pending Redemption';
                                $scope.searchRewards[i].CanResend = true;
                                $scope.searchRewards[i].CanReset = false;
                                break;
                            }
                        }
                        Common.showMessage('success', '672');
                    });
                }

            $scope.searchByDateRange = searchByDateRange;
            $scope.showIfNoData = showIfNoData;
            $scope.searchQuery = '';
            $scope.dateFilters = Common.getStandardDateRangeFilter();
            $scope.showResetRewardModal = showResetRewardModal;
            $scope.showResendRewardModal = showResendRewardModal;
            $scope.getCampaignTypeText = RewardService.getCampaignTypeText;
            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;

            if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                $scope.selectedFilter = $scope.dateFilters[0];
            }
        }])

    .controller('ResetRewardCtrl', [
        '$scope',
        '$uibModalInstance',
        'reward',
        function ($scope, $uibModalInstance, reward) {

            resetReward = function (reward) {
                $uibModalInstance.close(reward);
            };

            $scope.resetReward = resetReward;
            $scope.reward = reward;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }])

    .controller('ResendRewardCtrl', [
        '$scope',
        '$uibModalInstance',
        'reward',
        function ($scope, $uibModalInstance, reward) {

            resendReward = function (reward) {
                reward.RecipientEmail = $scope.newEmail;
                $uibModalInstance.close(reward);
            };

            $scope.resendReward = resendReward;
            $scope.reward = reward;
            $scope.newEmail = reward.RecipientEmail;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };
        }]);
;angular
    .module('ecs.ctrl.dashboard-rewards', [])
    .controller('dashboardRewardsCtrl', [
        '$scope',
        'Common',
        'Rewards',
        'RewardService',
        'Campaign',
        '$uibModal',
        'CampaignWizard',
        '$window',
        function ($scope, Common, Rewards, RewardService, Campaign, $uibModal, CampaignWizard, $window) {

            var showIfNoData = false,

                searchByDateRange = function ($event, filter, reward) {
                    if ($event)
                        $event.preventDefault();

                    if (filter)
                        $scope.selectedDateFilter = filter;

                    if (reward)
                        $scope.selectedReward = reward;

                    if ($scope.selectedReward) {
                        var query = 'STORECODE=' + $scope.store.StoreCode + ',' + 'LaunchDate:' + $scope.selectedDateFilter.query + ',' + 'Name=' + $window.encodeURIComponent($scope.selectedReward.Name);

                        Common.showLoader('132');
                        Campaign.searchCampaigns(0, 1000, query)
                            .then(function (response) {
                                setCampaigns(response.data);
                            });
                    }
                },

                convertJsonDateToDateObj = function (json) {
                    var dateNumber = json.replace(/\/Date\((.*?)\)\//gi, "$1");
                    return new Date(Number(dateNumber.split("-")[0]));
                },

                getAvailableRewards = function () {
                    var query = 'isTemplate=true';
                    Campaign.searchCampaigns(0, 1000, query)
                        .then(function (response) {
                            setAvailableRewardsArray(response.data);
                        });
                },

                setAvailableRewardsArray = function (data) {

                    $scope.availableRewards = data;

                    if ($scope.availableRewards.length > 0)
                        $scope.selectedReward = $scope.availableRewards[0];

                    searchByDateRange();
                },

                setCampaigns = function (data) {
                    searchCampainData = data;
                    $scope.showIfNoData = true;
                    var today = new Date();

                    for (var i = 0; i < searchCampainData.length; i++) {
                        searchCampainData[i].ExpirationDateDisplay = Common.convertJsonDateString(searchCampainData[i].ExpirationDate);
                        searchCampainData[i].LaunchDateDisplay = Common.convertJsonDateString(searchCampainData[i].LaunchDate);
                        searchCampainData[i].CreateDateObj = convertJsonDateToDateObj(searchCampainData[i].CreateDate);
                        var expirationDate = Date.parse(searchCampainData[i].ExpirationDateDisplay);
                        searchCampainData[i].ShowAddRecipient = (expirationDate > today);
                        $scope.showIfNoData = false;
                    }

                    $scope.sorting = {
                        column: 'CreateDateObj',
                        isAscending: false
                    };
                    searchCampainData = sortRewards(searchCampainData, $scope.sorting);
                    $scope.searchCampainData = searchCampainData;
                },

                showUpdateEndDateModal = function (campaign) {
                    campaign.expirationForDatepicker = new Date(campaign.ExpirationDateDisplay);
                    var modalInstance = $uibModal.open({
                        templateUrl: 'UpdateEndDate.html',
                        controller: 'UpdateEndDateCtrl as ctrl',
                        resolve: {
                            campaign: function () {
                                return campaign;
                            }
                        }
                    });

                    modalInstance.result.then(function (campaign) {
                        updateEndDate(campaign);
                    });
                },

                showRecipientForm = function (campaign) {

                    var modalInstance = $uibModal.open({
                        templateUrl: 'AddRecipient.html',
                        controller: 'AddRecipientCtrl as ctrl',
                        resolve: {
                            campaign: function () {
                                return campaign;
                            }
                        }
                    });

                    modalInstance.result.then(function (newCampaign) {
                        addRecipient(newCampaign);
                    });
                },

                addRecipient = function (campaign) {
                    Common.showLoader('134');
                    CampaignWizard.addRecipient(campaign.CampaignId, campaign.NewRecipient)
                        .then(function (response) {
                            Common.showMessage('success', '675');
                            campaign.NumberOfRecipients++;
                        },
                            function (error) {
                                console.log('update Campaign error', error);
                            });
                },

                updateEndDate = function (campaign) {
                    Common.showLoader('131');
                    CampaignWizard.updateCampaign(campaign.CampaignId, campaign)
                        .then(function (response) {
                            Common.showMessage('success', '674');
                        },
                            function (error) {
                                console.log('update Campaign error', error);
                            });
                },

                sortRewards = function (rewards, sortOptions) {
                    if (rewards.length === 0) {
                        return rewards;
                    }
                    else {
                        var toReturn = Common.orderBy(rewards, sortOptions.isAscending, sortOptions.column);
                        return toReturn;
                    }
                },

                handleSortClick = function (sortCol) {
                    //already sorted ascending, switch to descending sort
                    if ($scope.sorting.column == sortCol) {
                        $scope.sorting.isAscending = !$scope.sorting.isAscending;
                    } else {
                        $scope.sorting.column = sortCol;
                        $scope.sorting.isAscending = true;

                    }

                    Common.showLoader('132');
                    $scope.searchCampainData = sortRewards($scope.searchCampainData, $scope.sorting);
                    Common.hideLoader();
                }

            $scope.searchByDateRange = searchByDateRange;
            $scope.showIfNoData = showIfNoData;
            $scope.dateFilters = Common.getStandardDateRangeFilter();
            $scope.showUpdateEndDateModal = showUpdateEndDateModal;
            $scope.showRecipientForm = showRecipientForm;
            $scope.getCampaignTypeText = RewardService.getCampaignTypeText;
            $scope.changeFocus = Common.changeFocus;
            $scope.$scrollTop();
            $scope.sorting = null;
            $scope.handleSortClick = handleSortClick;
            getAvailableRewards();

            if ($scope.dateFilters && $scope.dateFilters.length > 0)
                $scope.selectedDateFilter = $scope.dateFilters[0];

        }])

    .controller('UpdateEndDateCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'campaign',
        function ($scope, Common, $uibModalInstance, campaign) {

            updateEndDate = function (campaign) {
                var formattedEndDate = campaign.expirationForDatepicker;
                var formattedLaunchDate = new Date(campaign.LaunchDateDisplay);
                var diffTime = Math.abs(formattedEndDate - formattedLaunchDate);
                campaign.DaysToRedeem = Math.round(diffTime / (1000 * 3600 * 24));

                campaign.ExpirationDate = Common.convertToJsonDateString(formattedEndDate);
                campaign.ExpirationDateDisplay = Common.convertJsonDateString(campaign.ExpirationDate, true);
                
                $uibModalInstance.close(campaign);
            };

            $scope.openDatePicker = function ($event) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.datePickerOpened = true;
            };

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

            $scope.updateEndDate = updateEndDate;
            $scope.campaign = campaign;

            var today = new Date();
            var priorDate = new Date().setDate(today.getDate());
            $scope.eventDateOptions = {
                minDate: priorDate,
            }

        }])

    .controller('AddRecipientCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'campaign',
        function ($scope, Common, $uibModalInstance, campaign) {

            addRecipient = function (campaign, form) {
                if (form.$valid) {
                    $uibModalInstance.close(campaign);
                }
            };

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

            campaign.NewRecipient = {
                Email: '',
                FirstName: '',
                LastName: '',
            },

            $scope.campaign = campaign;
            $scope.addRecipient = addRecipient;

        }]);;angular
    .module('ecs.ctrl.cartSummary', [])
    .controller('cartSummaryCtrl', [
        '$rootScope',
        '$scope',
        'CheckoutService',
        'ChiliService',
        'Common',
        '$log',
        function ($rootScope, $scope, CheckoutService, ChiliService, Common, $log) {
            $scope.cart = CheckoutService.cartCheckout;
            $scope.CheckoutService = CheckoutService;            
            $scope.$watch(
                function () { return CheckoutService.cartCheckout; },

                function (newValue, oldValue) {
                    if (newValue !== oldValue) {
                        $scope.cart = CheckoutService.cartCheckout;
                        $scope.cart.HasSellAndDisplayPriceProducts = $scope.cart.Items.some(i => i.DisplayPrice != null);
                    }
                },

                true // indicates object equaility comparison
            ),

            applyPromoCode = function () {

                var code = $scope.promoCodeToApply;

                if (code && code !== '') {
                    $log.log('Applying Promo Code to CheckOut Cart' + code);

                    CheckoutService.applyPromoCodeOnCheckout(code)
                        .then($scope.cart);

                    $scope.promoCodeToApply = "";
                }
                else {
                    Common.showMessage('danger', '407');
                }

                },

            getRenderPDF = function (guid) {
                ChiliService.getRenderPDF(guid);
            },

            $scope.applyPromoCode = applyPromoCode;
            $scope.getRenderPDF = getRenderPDF;

            ////Original code reloaded the cart anytime "Checkout" was in the path
            ////This handled the onCartChange event which is broadcast anytime an items
            ////it added, removed, or broadcasted. Reduces (hopefully) the number times we need to do this

            ////TODO: Determine if this is the best location for this. This controller get's loaded
            ////in multiple places so it is still firing multiple times when an order changes
            //$rootScope.$on("onCartChange", function () {
                
            //    if (Common.getCartInitialized()) {
            //        CheckoutService.getCheckoutCart();
            //    }
            //    //result = $.inArray('checkout', next.split('/'));
            //    //if ( result && result !== -1 && Common.getCartInitialized()) {
            //    //    CheckoutService.getCheckoutCart();
            //    //}
            //});

            //$rootScope.$on("onMyAccountInfoChanged", function () {

            //    if (Common.getCartInitialized()) {
            //        CheckoutService.getCheckoutCart();
            //    }
            //});


            
            
        }]);

;angular
    .module('ecs.ctrl.payment', [])
    .controller('paymentCtrl', [
        '$rootScope',
        '$scope',
        'Common',
        '$location',
        'CheckoutService',
        '$log',
        function ($rootScope, $scope, Common, $location, CheckoutService, $log) {

            var updateCheckoutCart = function (paymentDetailCaptured) {
                return CheckoutService.updateCheckoutCart(paymentDetailCaptured);
            },

            

            setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {
                    $scope.cartCheckout = CheckoutService.cartCheckout;
                    $scope.selectedPaymentMethod.Code = CheckoutService.cartCheckout.PaymentMethod.PaymentMethodCode;
                } else {
                    CheckoutService.getCheckoutCart()
                        
                }
                
            },

            disableWatcher = undefined,

            enableWatcher = function () {

                disableWatcher = $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        //If cartCheckout value is valid determine if we update our cart in the scope
                        if (newValue) {
                            //If we haven't set it in the scope, then set it
                            if (!$scope.cartCheckout)
                                setCartCheckout();
                                //If the Billing Address is changed (due to Payment method selection), then set it.
                            else if (CheckoutService.paymentDetailRefreshNeeded) {
                                setCartCheckout();
                                CheckoutService.paymentDetailRefreshNeeded = false;
                            }
                        }
                    },

                    true // indicates object equaility comparison
                );
            },

            initBilling = function () {

                $scope.$scrollTop();

                setCartCheckout();
                enableWatcher();
            },

            setDefaults = function () {
                
            },

            updatePaymentMethod = function (method) {
                Common.showLoader('124');
                //If we're capturing the payment method here, it's because the shipping info is dependent upon payment method. Clear out any saved shipping data
                Common.clearStoredShippingData();
                CheckoutService.updatePaymentMethod(method);
            },

            goToShipping = function ($event) {
                if ($event)
                    $event.preventDefault();

                var coCart = $scope.cartCheckout;
                //If we already have the address, go directly to the shipping step, otherwise, have them select the address
                if (!!coCart.ShippingAddress) {
                    $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                }
                else {
                    $location.path('/checkout/shipping/select-shipping-address/' + Common.getCurrentCheckoutUTSID());
                }
                
            };

            
            $scope.selectedPaymentMethod = {};
            $scope.updatePaymentMethod = updatePaymentMethod;
            $scope.paymentMethods = $scope.store.PaymentMethods;
            $scope.goToShipping = goToShipping;

            setDefaults();
            initBilling();


        }]);;angular
    .module('ecs.ctrl.billing', [])
    .controller('billingCtrl', [
        '$rootScope',
        '$scope',
        'Common',
        '$location',
        '$sce',
        'Customers',
        'CheckoutService',
        'BudgetsService',
        '$log',
        '$window',
        '$uibModal',
        function ($rootScope, $scope, Common, $location, $sce, Customers, CheckoutService, BudgetsService, $log, $window, $uibModal) {

            $scope.userSSO = {
                office: '',
                company: '',
                department: ''
            }

            var disableWatcher = undefined,

                setUserSSO = function (office, company, department) {
                    //'Bill Back To Business'
                    if ($scope.store.StoreCode == 'STX') {
                        $scope.userSSO = {
                            office: office,
                            company: company,
                            department: department
                        }
                        setCustomFields();
                    }
                },

                setCustomFields = function () {
                    //'Bill Back To Business'
                    if ($scope.store.StoreCode == 'STX' && $scope.selectedPaymentMethod.Code == 'BU-NT30') {
                        $scope.cartCheckout.OrganizationInfo.BusinessReasonCode = $scope.userSSO.office;
                        $scope.cartCheckout.OrganizationInfo.CostCenter = $scope.userSSO.company;
                        $scope.cartCheckout.PONumber = $scope.userSSO.department;
                    }
                },

                editBillingAddress = function ($event) {
                    $event.preventDefault();
                    $location.path('/checkout/billing/billing-address/' + Common.getCurrentCheckoutUTSID());
                },

                updateCheckoutCart = function (paymentDetailCaptured) {
                    return CheckoutService.updateCheckoutCart(paymentDetailCaptured);

                },

                showSelectedCreditCard = false,

                useExistingCard = function (card) {
                    card.Last4 = card.CardNumber.substr(-4);
                    CheckoutService.cartCheckout.PaymentCard = $scope.NewPaymentCard = card;
                    $scope.showNewCardForm = false;
                    $scope.showSelectedCreditCard = true;
                    $scope.useNewCard = false;
                },

                usediffCard = function ($event) {
                    if ($event) $event.preventDefault();

                    if ($scope.NewPaymentCard) {
                        $scope.NewPaymentCardView = angular.copy($scope.NewPaymentCard);
                    }
                    if ($scope.paymentCards.length === 0) {
                        $scope.showNewCardForm = true;
                    } else {
                        $scope.showSelectedCreditCard = false;
                    }
                },

                addNewCard = function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }
                    $scope.NewPaymentCard = getEmtpyCard();
                    //Set name if needed
                    if ($scope.restrictBillingNameEdits) {
                        $scope.NewPaymentCard.Name = $scope.cartCheckout.BillingAddress.Name;
                    }

                    $scope.showNewCardForm = true;
                },

                useThisNewCard = function () {

                    CheckoutService.cartCheckout.PaymentCard = $scope.NewPaymentCard;
                    $scope.useNewCard = true;
                    $scope.showNewCardForm = false;
                    $scope.showSelectedCreditCard = true;
                },

                cancelNewCard = function () {

                    $scope.NewPaymentCard = undefined;
                    $scope.showNewCardForm = false;
                    $scope.useNewCard = false;

                    if ($scope.NewPaymentCardView) {
                        $scope.NewPaymentCard = $scope.NewPaymentCardView;
                        $scope.NewPaymentCardView = undefined;
                    } else {
                        $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                    }

                },

                getCVVErrorMessage = function (errorObj) {
                    var message = "*Please enter your credit card security code.";

                    if (errorObj.minlength) {
                        message = "*CVV security code should be at least 3 digits.";
                    }

                    return message;

                },

                setCartCheckout = function () {

                    if (CheckoutService.cartCheckout) {
                        $scope.cartCheckout = CheckoutService.cartCheckout;

                        if (CheckoutService.cartCheckout.PaymentMethod) {
                            $scope.selectedPaymentMethod.Code = CheckoutService.cartCheckout.PaymentMethod.PaymentMethodCode;
                            $scope.selectedPaymentMethod.ApprovalTypeId = CheckoutService.cartCheckout.PaymentMethod.ApprovalTypeId;
                            // hotfix for CTD dealers not to edit bill to
                            $scope.selectedPaymentMethod.canEditBilling = !CheckoutService.cartCheckout.PaymentMethod.PayerCustomerId && $scope.selectedPaymentMethod.Code !== "DE-NT30";
                            $scope.selectedPaymentMethod.canCombineWithGiftCertificate = CheckoutService.cartCheckout.PaymentMethod.CombineWithGiftCertificate;
                            $scope.selectedPaymentMethod.paymentConfig = JSON.parse(CheckoutService.cartCheckout.PaymentMethod.CaptureConfig);
                            if ($scope.cartCheckout.PaymentMethod.ApprovalTypeId == 149) {
                                $scope.paymentMethodApproverGroups = CheckoutService.paymentMethodApproverGroups;
                            };
                            if (!!$scope.selectedPaymentMethod.paymentConfig.AlertMessage && !!$scope.selectedPaymentMethod.paymentConfig.AlertMessage)
                                $scope.selectedPaymentMethod.paymentConfig.AlertMessage = $sce.trustAsHtml($scope.selectedPaymentMethod.paymentConfig.AlertMessage);

                            if (!!$scope.selectedPaymentMethod.paymentConfig.Heading)
                                $scope.selectedPaymentMethod.paymentConfig.Heading = $sce.trustAsHtml($scope.selectedPaymentMethod.paymentConfig.Heading);

                            if (!$scope.selectedPaymentMethod.canCombineWithGiftCertificate)
                                $scope.selectedPaymentMethod.applyGiftCert = false;
                            else if ($scope.giftCertificateTotal > 0 && !CheckoutService.paymentCardToUse)
                                $scope.selectedPaymentMethod.applyGiftCert = true;

                            if ($scope.selectedPaymentMethod.paymentConfig.Type === 'MultiPartPONumber' || $scope.selectedPaymentMethod.paymentConfig.Type === 'FSHGPDollars') {
                                var separator = $scope.selectedPaymentMethod.paymentConfig.FieldSeparator;
                                if ($scope.selectedPaymentMethod.paymentConfig.Type === 'FSHGPDollars')
                                    separator = '.';

                                if (!!$scope.cartCheckout.PONumber && $scope.cartCheckout.PONumber !== '') {
                                    $scope.cartCheckout.multipPartPO = $scope.cartCheckout.PONumber.split(separator);
                                }
                                else {
                                    $scope.cartCheckout.multipPartPO = [];
                                }
                            }
                            //For BudgetCode payment emthod, default the PO number to the first budget code if not yet provided
                            if ($scope.selectedPaymentMethod.paymentConfig.Type === 'BudgetCode' && ($scope.cartCheckout.PONumber == null || $scope.cartCheckout.PONumber === '') && $scope.budgets.length > 0) {
                                $scope.cartCheckout.PONumber = $scope.budgets[0].BudgetCode;
                            }

                            if ($scope.NewPaymentCard && $scope.restrictBillingNameEdits)
                                $scope.NewPaymentCard.Name = $scope.cartCheckout.BillingAddress.Name;

                            setCustomFields();
                        }
                    } else {
                        CheckoutService.getCheckoutCart();

                    }

                },

                enableWatcher = function () {

                    disableWatcher = $scope.$watch(
                        function () { return CheckoutService.cartCheckout; },

                        function (newValue, oldValue) {
                            //If cartCheckout value is valid determine if we update our cart in the scope
                            if (newValue) {
                                //If we haven't set it in the scope, then set it
                                if (!$scope.cartCheckout)
                                    setCartCheckout();
                                else if (newValue.PromoCodes.length != $scope.cartCheckout.PromoCodes.length) {
                                    //PromoCode was applied, does it cover the payment
                                    if (newValue.PaymentMethod.PaymentMethodCode === 'PC-PROMO') {
                                        goToReview();
                                    }
                                    else {
                                        setCartCheckout();
                                    }
                                }
                                //If the Billing Address is changed (due to Payment method selection), then set it.
                                else if (CheckoutService.paymentDetailRefreshNeeded) {
                                    setCartCheckout();
                                    CheckoutService.paymentDetailRefreshNeeded = false;
                                }
                            }
                        },

                        true // indicates object equaility comparison
                    );
                },

                initBilling = function () {

                    $scope.$scrollTop();

                    setCartCheckout();
                    enableWatcher();

                    if ($scope.store.Functionality.GiftCertificates) {
                        getGiftCertificate();

                        //Customers.getGiftCertificates({ ':customerId': $scope.user.CustomerId })
                        //    .then(function (res) {
                        //        $scope.giftCertificateTotal = getGiftCertificateTotal(res.data);
                        //        if ($scope.giftCertificateTotal > 0 && !!$scope.selectedPaymentMethod && $scope.selectedPaymentMethod.canCombineWithGiftCertificate && !CheckoutService.paymentCardToUse)
                        //            $scope.selectedPaymentMethod.applyGiftCert = true;
                        //    });
                    }
                    else {
                        $scope.giftCertificateTotal = 0;
                        $scope.selectedPaymentMethod.applyGiftCert = false;
                    }

                    if (BudgetsService.budgetsEnabled)
                        BudgetsService.getBudgets()
                            .then(function (response) {
                                $scope.budgets = response;
                            });


                    if ($scope.store.Functionality.ManagePaymentCards) {
                        Customers.getPaymentCards($scope.user.CustomerId)
                            .then(function (res) {
                                $scope.paymentCards = res.data;
                                //If we don't have any existing cards NOR do we have the card to use, show the new card form
                                if ($scope.paymentCards.length === 0 && !CheckoutService.paymentCardToUse)
                                    $scope.showNewCardForm = true;
                            });
                    }
                    else {
                        //No support for saved cards, show either new card form or CC that has already been entered
                        $scope.showNewCardForm = !CheckoutService.paymentCardToUse;
                    }

                    //If we have an existing card... show the selected credit card
                    if (CheckoutService.paymentCardToUse) {
                        $scope.showSelectedCreditCard = true;
                    }

                    if ($location.search().update === 'billing') {
                        Common.clearQueryStringValue('update');
                        usediffCard();
                    }

                    getPaymentMethods();
                },

                getPaymentMethods = function () {
                    CheckoutService.getCustomerPaymentMethods($scope.user.CustomerId, $scope.cartCheckout.CartId)
                        .then(function (res) {
                            $scope.paymentMethods = CheckoutService.customerPaymentMethods;
                        });
                },

                getGiftCertificate = function () {
                    if ($scope.user.CustomerId) {
                        Customers.getGiftCertificates({ ':customerId': $scope.user.CustomerId })
                            .then(function (res) {
                                $scope.giftCertificateTotal = getGiftCertificateTotal(res.data);
                                if ($scope.giftCertificateTotal > 0 && !!$scope.selectedPaymentMethod && $scope.selectedPaymentMethod.canCombineWithGiftCertificate && !CheckoutService.paymentCardToUse)
                                    $scope.selectedPaymentMethod.applyGiftCert = true;
                            });
                    }
                }

            getGiftCertificateTotal = function (certArray) {

                var certTotal = 0;

                angular.forEach(certArray, function (cert) {
                    certTotal += cert.RemainingAmount;
                });

                return certTotal;
            },

                setDefaults = function () {

                    //Need this set first. Will load the exisitng card the customer has chosen to use or initializes it to a empty card
                    $scope.NewPaymentCard = getPaymentCard();
                    $scope.selectedPaymentMethod.applyGiftCert = false; //this will be updated to true if we have any gift certificates

                },

                formatPaymentCard = function (data) {

                    data.CardNumber = data.CardNumber.substr(-4);

                    return data;
                },

                updatePaymentMethod = function (method) {
                    Common.showLoader('124');
                    CheckoutService.updatePaymentMethod(method);
                },

                goToReview = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    if (CheckoutService.cartCheckout.TermsRequired && !CheckoutService.cartCheckout.TermsAccepted) {
                        $location.path('/checkout/purchase-agreement/' + Common.getCurrentCheckoutUTSID());
                    } else {
                        $location.path('/checkout/review/' + Common.getCurrentCheckoutUTSID());
                    }

                },

                checkNewCardExpDate = function () {

                    var month = $scope.NewPaymentCard.ExpirationMonth,
                        year = $scope.NewPaymentCard.ExpirationYear,
                        expDate = new Date(year, month, 0),
                        dateValid = false;

                    if (expDate.getTime() >= new Date().getTime()) {
                        dateValid = true;
                    };

                    return dateValid;
                },

                submitBillingWithNewCreditCard = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    //At this point, the card number and token should have been set
                    $scope.isValidCard = Common.validateCreditCard($scope.NewPaymentCard.CardNumber, $scope.NewPaymentCard.CardType);
                    //$scope.isValidCard = true;
                    $scope.newCCExpDateValid = checkNewCardExpDate();
                    $scope.newCCFormSubmitted = true;

                    if (submitForm.$valid && $scope.newCCExpDateValid && $scope.isValidCard) {

                        //Check if we have applied the Gift Cert and it can be used with our selected payment method. Set the Amount and force ShipItemsTogether
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        CheckoutService.cartCheckout.OrganizationInfo.BusinessReasonCode = $scope.cartCheckout.OrganizationInfo.BusinessReasonCode;
                        CheckoutService.cartCheckout.OrganizationInfo.CostCenter = $scope.cartCheckout.OrganizationInfo.CostCenter;

                        if ($scope.NewPaymentCard.saveThisCard) {
                            //Put the full details of the payment card in Checkout service
                            CheckoutService.paymentCardToUse = $scope.NewPaymentCard;


                            $scope.submitted = false;
                            //If we've asked to save this, then go ahead and save it on the account
                            Customers.addPaymentCard($scope.user.CustomerId, $scope.NewPaymentCard)
                                .then(function (response) {

                                    Common.showMessage('success', '682'); //'Your new credit card has been added to your account.',

                                    //Save it on the cart. That way if the customer refreshes their screen we'll have it
                                    Common.showLoader('125');

                                    CheckoutService.cartCheckout.PaymentCard = response.data;
                                    updateCheckoutCart(true)
                                        .then(function () {
                                            goToReview();
                                        });
                                });
                        }
                        else {

                            //Specify that this card it to not be saved
                            $scope.NewPaymentCard.doNotSave = true;
                            //Put the full details of the payment card in Checkout service
                            CheckoutService.paymentCardToUse = $scope.NewPaymentCard;

                            Common.showLoader('125');
                            //Using a card that is not saved, clearn out the payment card
                            CheckoutService.cartCheckout.PaymentCard = null;
                            updateCheckoutCart(true)
                                .then(function () {
                                    goToReview();
                                });
                        }
                    }
                    else {
                        if (!$scope.isValidCard)
                            Common.showMessage('danger', '620');

                        else if (!$scope.newCCExpDateValid)
                            Common.showMessage('danger', '618');

                        else
                            Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithExistingCreditCard = function (submitForm) {

                    var self = this;
                    $scope.submitted = true;

                    if (submitForm.$valid) {
                        //Put the full details of the payment card in Checkout service
                        CheckoutService.paymentCardToUse = $scope.NewPaymentCard;

                        //Check if we have applied the Gift Cert. Set the Amount and force ShipItemsTogether
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        CheckoutService.cartCheckout.OrganizationInfo.BusinessReasonCode = $scope.cartCheckout.OrganizationInfo.BusinessReasonCode;
                        CheckoutService.cartCheckout.OrganizationInfo.CostCenter = $scope.cartCheckout.OrganizationInfo.CostCenter;

                        //Check to see if we can save this card in the cart
                        Common.showLoader('125');
                        if (!$scope.NewPaymentCard.doNotSave) {
                            CheckoutService.cartCheckout.PaymentCard = $scope.NewPaymentCard;
                            updateCheckoutCart(true)
                                .then(function () {
                                    goToReview();
                                });
                        }
                        else {
                            updateCheckoutCart(true)
                                .then(function () {
                                    goToReview();
                                });
                        }
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithPONumber = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        CheckoutService.paymentCardToUse = null;

                        //FP - gift certificates can be combined for terms payment if the flag is set for each store
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        //Set the PO number 
                        CheckoutService.cartCheckout.PONumber = $scope.cartCheckout.PONumber;

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithMultiPartPONumber = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        CheckoutService.paymentCardToUse = null;

                        //FP - gift certificates can be combined for terms payment if the flag is set for each store
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        var poParts = [];
                        var numOfInputs = $scope.selectedPaymentMethod.paymentConfig.InputFields.length;
                        for (var i = 0; i < numOfInputs; i++) {
                            poParts[i] = $scope.cartCheckout.multipPartPO[i];
                        }

                        //Set the PO number 
                        CheckoutService.cartCheckout.PONumber = poParts.join($scope.selectedPaymentMethod.paymentConfig.FieldSeparator);

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithPOAndOrgInfo = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        CheckoutService.paymentCardToUse = null;

                        //FP - gift certificates can be combined for terms payment if the flag is set for each store
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        //Set the PO number and the Organization info
                        CheckoutService.cartCheckout.PONumber = $scope.cartCheckout.PONumber;
                        CheckoutService.cartCheckout.OrganizationInfo = $scope.cartCheckout.OrganizationInfo;

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithApproverEmail = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        //We're not using a payment card and gift certificates can never be combined
                        CheckoutService.paymentCardToUse = null;
                        CheckoutService.cartCheckout.GiftCertificateAmount = 0;

                        //Set the PO number 
                        CheckoutService.cartCheckout.CartApprovalApproverEmail = $scope.cartCheckout.CartApprovalApproverEmail;

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithFSHGPDollars = function (submitForm) {
                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        CheckoutService.paymentCardToUse = null;

                        //FP - gift certificates can be combined for terms payment if the flag is set for each store
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        var poParts = [];
                        for (var i = 0; i < 4; i++) {
                            poParts[i] = $scope.cartCheckout.multipPartPO[i];
                        }

                        //Set the PO number 
                        CheckoutService.cartCheckout.PONumber = poParts.join('.');

                        //Set Organization fields (FSH GP Dollars uses Division, Budget Code, Cost Center, BizUnit 
                        CheckoutService.cartCheckout.OrganizationInfo = $scope.cartCheckout.OrganizationInfo;

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }

                },

                submitBillingWithOrgInfo = function (submitForm) {

                    var self = this;
                    submitForm.$submitted = true;

                    if (submitForm.$valid) {

                        CheckoutService.paymentCardToUse = null;

                        //FP - gift certificates can be combined for terms payment if the flag is set for each store
                        if ($scope.selectedPaymentMethod.applyGiftCert && $scope.selectedPaymentMethod.canCombineWithGiftCertificate) {
                            CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                            CheckoutService.cartCheckout.ShipItemsTogether = true;
                        }
                        else {
                            CheckoutService.cartCheckout.GiftCertificateAmount = 0;
                        }

                        //Set the PO number 
                        CheckoutService.cartCheckout.OrganizationInfo = $scope.cartCheckout.OrganizationInfo;

                        Common.showLoader('125');
                        updateCheckoutCart(true)
                            .then(function () {
                                goToReview();
                            });
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }
                },

                submitBillingWithGiftCertificateOnly = function (submitForm) {

                    var self = this;
                    submitForm.submitted = true;

                    if (submitForm.$valid) {
                        //We're not using a payment card
                        CheckoutService.paymentCardToUse = null;

                        //Set the GC Amount and force ShipItemsTogether
                        CheckoutService.cartCheckout.GiftCertificateAmount = $scope.giftCertificateTotal;
                        CheckoutService.cartCheckout.ShipItemsTogether = true;

                        updateCheckoutCart(true);
                        goToReview();
                    }
                    else {
                        Common.showMessage('danger', '638');
                    }

                },

                showBudgetInfo = function () {
                    var self = this,
                        modalInstance = $uibModal.open({
                            templateUrl: 'purchaseBalanceModalContent', //This content can be found in Shared/_BalanceInfo.cshtml, and each store has their own custom partial view content
                            controller: 'PurchaseBalanceModalCtrl',
                            size: 'lg',
                            resolve: {
                                balances: function () {
                                    return $scope.budgets;
                                },
                                locale: function () {
                                    return $scope.locale;
                                }
                            }
                        });

                    modalInstance.result.then(function () {

                        $log.log('Dismissing modal');
                    }, function () {
                        //when cancelled do nothing
                    });

                },


                showPaymentDetailsAdditionalInfo = function (pmtDetailAdditionalInfo) {
                    var modalInstance = $uibModal.open({
                        templateUrl: 'COPaymentDetailsAdditionalInfo.html',
                        controller: 'showCOPaymentDetailsAdditionalInfoCtrl',
                        size: 'lg',
                        resolve: {
                            pmtDetailAdditionalInfo: function () {
                                return pmtDetailAdditionalInfo;
                            }

                        }

                    });
                },

                getPaymentCard = function () {

                    if (CheckoutService.paymentCardToUse) {
                        data = CheckoutService.paymentCardToUse;
                        data.Last4 = data.CardNumber.substr(-4);
                        return data;
                    }
                    else {
                        return getEmtpyCard();
                    }

                },

                getEmtpyCard = function () {

                    var monthTmp = (new Date().getMonth() + 1).toString(),
                        month = (monthTmp > 9) ? month : '0' + monthTmp,
                        year = new Date().getFullYear().toString();

                    return {

                        CustomerId: $scope.user.CustomerId,
                        CardType: null,
                        CardNumber: "",
                        Last4: "",
                        ExpirationMonth: "01",
                        ExpirationYear: year,
                        Name: "",
                        CVV: "",
                        IsDefault: false
                    };
                },

                goToPayment = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    $location.path('/checkout/payment/' + Common.getCurrentCheckoutUTSID());

                },

                setCardToken = function (token, cardType) {

                    if (!!token && token !== '') {
                        $scope.NewPaymentCard.CardNumber = token;
                        $scope.NewPaymentCard.CardType = setCardTypeFromBrand(cardType) || setCardTypeFromToken(token);
                    }
                    else {
                        $scope.NewPaymentCard.CardNumber == null;
                        $scope.NewPaymentCard.CardType == null;
                    }
                    $scope.$apply();
                },

                setCardTypeFromToken = function (token) {
                    if (!!token && token !== '') {
                        var ccFirstDigit = token.substring(1, 2);
                        if (ccFirstDigit == '4')
                            return "VISA"
                        else if (ccFirstDigit == '5' || ccFirstDigit == '2')
                            return "MC"
                        else if (ccFirstDigit == '6')
                            return "DISC"
                        else if (ccFirstDigit == '3')
                            return "AMEX"
                        else
                            return null;
                    }
                    else {
                        return null;
                    }
                },
                setCardTypeFromBrand = function (name) {
                    if (!name)
                        return null;
                    else
                    {
                        var upper = name.toUpperCase();
                        switch (upper) {
                            case "VISA":
                                return "VISA";
                            case "MC":
                            case "MASTERCARD":
                                return "MC";
                            case "DISC":
                            case "DISCOVER":
                                return "DISC";
                            case "AMEX":
                                return "AMEX";
                            default:
                                return null;
                        }
                    } 
                },

                activateGiftCertificate = function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }
                    var modalInstance = $uibModal.open({
                        templateUrl: 'ActivatGiftCertificateModalContent',
                        controller: 'activateGiftCertificateModalCtrl',
                        scope: $scope,
                        resolve: {
                            giftActivation: function () {
                                return $scope.giftActivation;
                            }
                        }
                    });
                },

                giftActivation = {
                    GiftCertificateNumber: '',
                    AuthorizationCode: ''
                };

            setCCHandler = function () {
                var self = this;
                $window.addEventListener('message', function (e) {
                    Common.parseCreditCardTokenMessage(e, (token, cardType) => {
                        self.setCardToken(token, cardType);
                    });
                });
            };
            setCCHandler();

            $scope.setUserSSO = setUserSSO;
            $scope.editBillingAddress = editBillingAddress;
            $scope.useExistingCard = useExistingCard;
            $scope.usediffCard = usediffCard;
            $scope.addNewCard = addNewCard;
            $scope.showCVVImage = false;
            $scope.approverEmailAddressPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
            $scope.paymentCards = [];
            $scope.paymentDetails = {};
            $scope.selectedPaymentMethod = {};
            $scope.updatePaymentMethod = updatePaymentMethod;
            $scope.paymentMethods = $scope.store.PaymentMethods;
            $scope.goToPayment = goToPayment;

            $scope.useThisNewCard = useThisNewCard;
            $scope.cancelNewCard = cancelNewCard;
            $scope.getCVVErrorMessage = getCVVErrorMessage;
            $scope.activateGiftCertificate = activateGiftCertificate;
            //Three methods. Not elegant, but simplier and easier to work with
            $scope.submitBillingWithNewCreditCard = submitBillingWithNewCreditCard;
            $scope.submitBillingWithExistingCreditCard = submitBillingWithExistingCreditCard;
            $scope.submitBillingWithGiftCertificateOnly = submitBillingWithGiftCertificateOnly;
            $scope.submitBillingWithOrgInfo = submitBillingWithOrgInfo;
            $scope.submitBillingWithPONumber = submitBillingWithPONumber;
            $scope.submitBillingWithPOAndOrgInfo = submitBillingWithPOAndOrgInfo;
            $scope.submitBillingWithApproverEmail = submitBillingWithApproverEmail;
            $scope.submitBillingWithMultiPartPONumber = submitBillingWithMultiPartPONumber;
            $scope.submitBillingWithFSHGPDollars = submitBillingWithFSHGPDollars;

            $scope.showPaymentDetailsAdditionalInfo = showPaymentDetailsAdditionalInfo;
            $scope.showBudgetInfo = showBudgetInfo;

            $scope.years = Common.getYears();
            $scope.months = Common.getMonths();

            $scope.showApplyGiftCertificate = false;
            $scope.getGiftCertificate = getGiftCertificate;
            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.restrictBillingNameEdits = $scope.store.Functionality.RestrictBillingNameEdits;
            $scope.giftActivation = giftActivation;
            $scope.budgets = [];
            setDefaults();
            initBilling();


        }])
    .controller('showCOPaymentDetailsAdditionalInfoCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'pmtDetailAdditionalInfo',
        function ($scope, Common, $uibModalInstance, pmtDetailAdditionalInfo) {

            $scope.pmtDetailAdditionalInfo = pmtDetailAdditionalInfo;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }])
    .controller('activateGiftCertificateModalCtrl', [
        '$scope',
        'Common',
        'Customers',
        'EcsLocale',
        'giftActivation',
        '$uibModalInstance',
        function ($scope, Common, Customers, EcsLocale, giftActivation, $uibModalInstance) {

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };
            submitForm = function (form) {

                if (form.$valid) {
                    Customers.activateGiftCertificate($scope.user.CustomerId, $scope.giftActivation)
                        .then(function (response) {
                            Common.showMessage('success', '688');//Gift card activated successfully.
                            $scope.giftActivation = {};
                            $scope.getGiftCertificate();
                            $scope.close();
                        },
                            function (error) {
                                $scope.activationFailed = true;
                            }
                        );
                }
            },
                giftActivation = {
                    GiftCertificateNumber: '',
                    AuthorizationCode: ''
                };
            $scope.activationFailed = false;
            $scope.submitForm = submitForm;
            $scope.giftActivation = giftActivation;
            $scope.close();
        }]);angular
    .module('ecs.ctrl.billingAddress', [])
    .controller('billingAddressCtrl', [
        '$rootScope',
        '$scope',
        'Common',
        '$location',
        'Customers',
        'CheckoutService',
        'AddressService',
        '$log',
        function ($rootScope, $scope, Common, $location, Customers, CheckoutService, AddressService, $log) {

            var cancelChangeAddress = function () {

                window.history.back();
            },

            checkForShippingSameAsBillingAddress = function () {
                var tmpBill = angular.copy(CheckoutService.cartCheckout.BillingAddress),
                    tmpShip = angular.copy(CheckoutService.cartCheckout.ShippingAddress);

                if (!!tmpBill)
                    delete tmpBill.AddressType;
                if (!!tmpShip)
                    delete tmpShip.AddressType;

                return angular.equals(tmpBill, tmpShip);

            }

            saveBillingAddress = function () {

                var self = this;
                $scope.submitted = true;

                if ($scope.customer.BillingAddress.Country === 'US' && ($scope[$scope.activeForm].City.$dirty || $scope[$scope.activeForm].PostalCode.$dirty)) {

                    AddressService.updateTaxJurisdictions($scope, $scope.activeForm)
                    .then(function (response) {
                        self.saveBillingAddress();
                    });

                } else {

                    if ($scope[$scope.activeForm].$valid) {

                        //Make sure the state is not set if the country doesn't have states
                        if ($scope.states.length === 0) {
                            $scope.customer.BillingAddress.State = "";
                        }

                        var isDigitalDownloadOnly = CheckoutService.cartCheckout.IsDownloadOnly;
                        var shippingSameAsBillingAddress = false;
                        newBillingAddress = CheckoutService.cartCheckout.BillingAddress = $scope.customer.BillingAddress;

                        if (CheckoutService.cartCheckout.SoldToCustomerId == CheckoutService.cartCheckout.ShippingAddress.AddressId) {
                            shippingSameAsBillingAddress = true;
                            CheckoutService.cartCheckout.ShippingAddress = newBillingAddress;
                        }

                        newBillingAddress.UpdateFlags = 1;
                        Customers.updateAddress($scope.user.CustomerId, newBillingAddress)
                            .then(function () {
                                updateCheckoutCart();
                                $scope.submitted = false;
                                $scope[$scope.activeForm].$setPristine();
                            })
                            .then(function (response) {
                                $rootScope.$broadcast('onUserNameChanged');

                                if (shippingSameAsBillingAddress && !isDigitalDownloadOnly) {
                                    $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                                    Common.showMessage('warning', '619');
                                } else {
                                    Common.showMessage('success', '680'); //'Your billing address has been updated.';
                                    $location.path('/checkout/billing/' + Common.getCurrentCheckoutUTSID());
                                }

                            });

                    } else {
                        Common.showMessage('danger', '615');
                    }

                }


            },

            updateCheckoutCart = function () {
                return CheckoutService.updateCheckoutCart();
            },

            setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {
                    $scope.cartCheckout = CheckoutService.cartCheckout;
                    $scope.customer = {};
                    $scope.customer.BillingAddress = $scope.cartCheckout.BillingAddress;

                    //Load the states (which will load the tax jurisdictions if necessary)
                    onCountryChanged();

                    $scope.renderPage = true;

                } else {
                    CheckoutService.getCheckoutCart()

                }

            },

            disableWatcher = undefined,

            enableWatcher = function () {

                disableWatcher = $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                        if (newValue && !$scope.cartCheckout) {
                            setCartCheckout();
                        }
                    },

                    true // indicates object equaility comparison
                );
            },

            init = function () {

                $scope.$scrollTop();

                setCartCheckout();

                enableWatcher();

            },


            setDefaults = function () {

                AddressService.getCountries($scope, 'Billing');

            },

            updateCheckoutCart = function () {

                return CheckoutService.updateCheckoutCart();
            },

            updateTaxJurisdictions = function (reset, form) {

                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            },

            onCountryChanged = function () {
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);
            };



            $scope.renderPage = false;
            $scope.addressType = 'BillingAddress';
            $scope.activeForm = 'billingForm';
            $scope.cancelChangeAddress = cancelChangeAddress;
            $scope.saveBillingAddress = saveBillingAddress;
            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.restrictBillingNameEdits = $scope.store.Functionality.RestrictBillingNameEdits;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;
            $scope.showCountyAndJurisdiction = false;

            setDefaults();
            init();


        }]);;angular
    .module('ecs.ctrl.guestBillingAddress', [])
    .controller('guestBillingAddressCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        '$log',
        'Common',
        'CheckoutService',
        'AddressService',
        function ($rootScope, $scope, $location, $log, Common, CheckoutService, AddressService) {
            var cancelChangeAddress = function () {
                window.history.back();
            };

            var updateTaxJurisdictions = function (reset, form) {
                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            };

            var onCountryChanged = function () {
                if ($scope.customer[$scope.addressType].Country) {
                    return AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);
                } else {
                    return new Promise((resolve) => { resolve(); });
                }
            };

            var gotoNextStep = function () {
                $location.path('/guestcheckout/shippingaddress');
            };

            var save = function () {
                $scope.submitted = true;

                if (!$scope[$scope.activeForm].$valid) {
                    Common.showMessage('danger', '615');
                } else {
                    $scope.saving = true;

                    //Make sure the state is not set if the country doesn't have states
                    if (!$scope.states || $scope.states.length === 0) {
                        $scope.customer.BillingAddress.State = "";
                    }

                    CheckoutService.cartCheckout.BillingAddress = $scope.customer.BillingAddress;
                    CheckoutService.updateCartBillingAddress().then(() => {
                        $scope.saving = false;
                        $scope.submitted = false;
                        $scope[$scope.activeForm].$setPristine();
                        gotoNextStep();
                    }, () => {
                        $scope.submitted = false;
                        $scope.saving = false;
                        Common.showMessage('error', '200');
                    });
                }
            };

            var renderPage = function () {
                $scope.cartCheckout = CheckoutService.cartCheckout;
                $scope.customer.BillingAddress = $scope.cartCheckout.BillingAddress || {};
                onCountryChanged().then(() => {
                    $scope.renderPage = true;
                });
            };

            (function init() {
                $scope.$scrollTop();

                $scope.renderPage = false;
                $scope.addressType = 'BillingAddress';
                $scope.activeForm = 'billingForm';
                $scope.cancelChangeAddress = cancelChangeAddress;
                $scope.save = save;
                $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
                $scope.onCountryChanged = onCountryChanged;
                $scope.updateTaxJurisdictions = updateTaxJurisdictions;
                $scope.showCountyAndJurisdiction = false;
                $scope.customer = {
                    enableEmail: true,
                    BillingAddress: {}
                };

                AddressService.getCountries($scope, 'Billing', () => {
                    if (CheckoutService.cartCheckout) {
                        renderPage();
                    } else {
                        CheckoutService.getCheckoutCart(() => {
                            renderPage();
                        });
                    }
                });
            })();
        }]);;angular
    .module('ecs.ctrl.guestShippingAddress', [])
    .controller('guestShippingAddressCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        '$log',
        'Common',
        'CheckoutService',
        'AddressService',
        function ($rootScope, $scope, $location, $log, Common, CheckoutService, AddressService) {            
            var cancelChangeAddress = function () {
                window.history.back();
            };

            var toggleSameAddress = function () {
                if ($scope.useBillingAddress) {
                    var billingCopy = angular.copy(CheckoutService.cartCheckout.BillingAddress);
                    $scope.customer.ShippingAddress = billingCopy;
                    $scope.customer.ShippingAddress.__type = 'ShippingAddress:#ECS.Core.DTO';
                    onCountryChanged();
                } else {
                    $scope.customer.ShippingAddress = {};
                }
            };

            var updateTaxJurisdictions = function (reset, form) {
                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            };

            var onCountryChanged = function () {
                if ($scope.customer[$scope.addressType].Country) {
                    return AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);
                } else {
                    return new Promise((resolve) => { resolve(); });
                }
            };

            var gotoNextStep = function () {
                //$location.path('/guestcheckout/shippingoptions');
            };

            var save = function () {
                $scope.submitted = true;

                if (!$scope[$scope.activeForm].$valid) {
                    Common.showMessage('danger', '615');
                } else {
                    $scope.saving = true;

                    //Make sure the state is not set if the country doesn't have states
                    if (!$scope.states || $scope.states.length === 0) {
                        $scope.customer.ShippingAddress.State = "";
                    }

                    CheckoutService.cartCheckout.ShippingAddress = $scope.customer.ShippingAddress;
                    CheckoutService.updateCartShippingAddress().then(() => {
                        $scope.saving = false;
                        $scope.submitted = false;
                        $scope[$scope.activeForm].$setPristine();
                        gotoNextStep();
                    }, () => {
                        $scope.submitted = false;
                        $scope.saving = false;
                        Common.showMessage('error', '200');
                    });
                }
            };

            var renderPage = function () {
                $scope.cartCheckout = CheckoutService.cartCheckout;
                $scope.customer.ShippingAddress = $scope.cartCheckout.ShippingAddress || {};
                toggleSameAddress();
                onCountryChanged().then(() => {
                    
                    $scope.renderPage = true;
                }); 
            };

            (function init() {
                $scope.$scrollTop();

                $scope.renderPage = false;
                $scope.addressType = 'ShippingAddress';
                $scope.activeForm = 'shippingForm';
                $scope.cancelChangeAddress = cancelChangeAddress;
                $scope.save = save;
                $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
                $scope.onCountryChanged = onCountryChanged;
                $scope.updateTaxJurisdictions = updateTaxJurisdictions;
                $scope.toggleSameAddress = toggleSameAddress;
                $scope.showCountyAndJurisdiction = false;
                $scope.useBillingAddress = false;
                $scope.customer = {
                    enableEmail: true,
                    ShippingAddress: {}
                };

                AddressService.getCountries($scope, 'Shipping', () => {
                    if (CheckoutService.cartCheckout) {
                        renderPage();
                    } else {
                        CheckoutService.getCheckoutCart(() => {                            
                            renderPage();
                        });
                    }
                });
            })();
    }]);;angular
    .module('ecs.ctrl.shipping', [])
    .controller('shippingCtrl', [
        '$log',
        '$scope',
        '$location',
        'Constants',
        'Objects',
        'Common',
        '$timeout',
        '$sce',
        'ShoppingCarts',
        'Customers',
        'AddressService',
        'CheckoutService',
        '$uibModal',
        'Stores',
        function ($log, $scope, $location, Constants, Objects, Common, $timeout, $sce, ShoppingCarts, Customers, AddressService, CheckoutService, $uibModal, Stores) {

            $scope.useThirdPartyShipping = false;
            var disableWatcher,


                goToBilling = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    $timeout(function () {
                        $location.path('/checkout/billing/' + Common.getCurrentCheckoutUTSID());
                    }, 100);

                },

                goToPayment = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    $location.path('/checkout/payment/' + Common.getCurrentCheckoutUTSID());

                },

                goToSelectAddress = function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }

                    $location.path('/checkout/shipping/select-shipping-address/' + Common.getCurrentCheckoutUTSID());
                },


                goToReview = function () {
                    if (CheckoutService.cartCheckout.TermsRequired && !CheckoutService.cartCheckout.TermsAccepted) {
                        $location.path('/checkout/purchase-agreement/' + Common.getCurrentCheckoutUTSID());
                    } else {
                        $location.path('/checkout/review/' + Common.getCurrentCheckoutUTSID());
                    }
                },

                updateCheckoutCart = function () {

                    return CheckoutService.updateCheckoutCart();
                },

                shippingMethodObj,

                getShippingMethods = function (cartCheckout) {

                    $scope.shippingMethods = [];
                    $scope.showShippingOptions = false;
                    var shippingData = Common.getStoredShippingData();

                    if ($scope.useThirdPartyShipping != shippingData.thirdPartyShipping || !angular.equals(cartCheckout.ShippingAddress, shippingData.address) || shippingData.shipOptions.data.length === 0 || CheckoutService.shippingMethodRefreshNeeded) {

                        CheckoutService.shippingMethodRefreshNeeded = false;
                        ShoppingCarts.getShippingMethods({ ':cartId': $scope.cartCheckout.CartId })
                            .then(function (response) {
                                //Convert the Date
                                for (var i = 0; i < response.data.length; i++) {
                                    if (!!response.data[i].EstimatedDeliveryDate)
                                        response.data[i].estimatedDeliveryDateDisplay = Common.convertJsonDateDOWString(response.data[i].EstimatedDeliveryDate, true);
                                }

                                populateShippingMethods(response);
                                Common.storeShippingData({ address: cartCheckout.ShippingAddress, shipOptions: response, thirdPartyShipping: $scope.useThirdPartyShipping });
                                $scope.showShippingOptions = true;
                            });

                    } else {
                        populateShippingMethods(shippingData.shipOptions);
                        $scope.showShippingOptions = true;
                    }
                },

                populateShippingMethods = function (data) {

                    shippingMethodObj = Common.convertArrayToObj(data.data, 'ShippingMethodCode');
                    $scope.shippingMethods = data.data;
                    $scope.showFreeShippingHelpMessage = false;
                    getFreeShippingHelpMessage($scope, CheckoutService.cartCheckout.Items, $scope.shippingMethods);

                    if ($scope.shippingMethods.length === 0) {
                        //No shipping methods, cannot ship to this address
                        Common.showMessage('danger', '616');
                    }
                    else {
                        var shipMethod = CheckoutService.cartCheckout.ShippingMethod;

                        if (shipMethod && shipMethod.ShippingMethodCode) {
                            //If we have a previously saved method, check to see if it is one of the methods returned
                            var method = shippingMethodObj[shipMethod.ShippingMethodCode];

                            //If yes, use it if not, just pick the first one
                            if (method) {
                                $scope.selectedShippingOption.code = shipMethod.ShippingMethodCode;
                                if (method.Category === 'Express' || method.Category === 'Premium')
                                    $scope.cartCheckout.onDemandShippingConfirmSelected = true;
                            }
                            else {
                                $scope.selectedShippingOption.code = data.data[0].ShippingMethodCode;
                                $scope.cartCheckout.onDemandShippingConfirmSelected = false;
                            }
                        } else {
                            $scope.selectedShippingOption.code = data.data[0].ShippingMethodCode;
                            $scope.cartCheckout.onDemandShippingConfirmSelected = false;
                        }

                        updateShippingMethod();
                    }

                },

                updateShippingMethod = function () {
                    CheckoutService.cartCheckout.ShippingMethod = shippingMethodObj[$scope.selectedShippingOption.code];
                    $scope.selectedShippingOption.showWarning = CheckoutService.cartCheckout.ShippingMethod.ShowWarning;
                    if ($scope.selectedShippingOption.showWarning) {
                        $scope.selectedShippingOption.warningConfig = JSON.parse(CheckoutService.cartCheckout.ShippingMethod.WarningConfig);
                        $scope.selectedShippingOption.warningConfig.Caption = $sce.trustAsHtml($scope.selectedShippingOption.warningConfig.Caption);
                    }

                    $scope.updatingCart = true;
                    CheckoutService.updateCheckoutCart().finally(x => {
                        $scope.updatingCart = false;
                    });
                },

                updateOnDemandShippingConfirm = function () {
                    if ($scope.cartCheckout.onDemandShippingConfirmSelected == false) {
                        var method = shippingMethodObj[$scope.selectedShippingOption.code]
                        if (method.Category === 'Express' || method.Category === 'Premium') {
                            $scope.selectedShippingOption.code = $scope.shippingMethods[0].ShippingMethodCode;
                            updateShippingMethod();
                        }
                    }
                },

                saveAndProceed = function (submitForm, location) {
                    //Ok, we need to look at how we can refactor this. This will cause a bug again some day
                    //before updating the checkout cart, ensure the cart in the Checkout service is updated with any values
                    //that could have changed in the $scope.cartCheckout
                    submitForm.$submitted = true;
                    if (submitForm.$valid) {
                        const dateOptions = { month: 'numeric', day: 'numeric', year: 'numeric' };
                        CheckoutService.cartCheckout.ShipItemsTogether = $scope.cartCheckout.ShipItemsTogether;
                        if (CheckoutService.cartCheckout.ShippingCaptureConfig && CheckoutService.cartCheckout.ShippingCaptureConfig.OrderedForField) {
                            CheckoutService.cartCheckout.OrderedFor = $scope.cartCheckout.OrderedFor;
                        }
                        if (CheckoutService.cartCheckout.ShippingCaptureConfig && CheckoutService.cartCheckout.ShippingCaptureConfig.NeedByDateField && $scope.cartCheckout.NeedByDate) {
                            CheckoutService.cartCheckout.NeedByDate = $scope.cartCheckout.NeedByDate.toLocaleDateString("en-US", dateOptions);
                        }
                        if (CheckoutService.cartCheckout.ShippingCaptureConfig && CheckoutService.cartCheckout.ShippingCaptureConfig.NeedByInventoryField && $scope.cartCheckout.NeedByInventory) {
                            if ($scope.cartCheckout.NeedByInventory > new Date().setDate(new Date().getDate() + 60)) {
                                Common.showMessage('danger', '642');
                                return; 
                            } else {
                                CheckoutService.cartCheckout.NeedByInventory = $scope.cartCheckout.NeedByInventory.toLocaleDateString("en-US", dateOptions);
                            }
                            
                        }

                        CheckoutService.updateCheckoutCart()
                            .then(function () {
                                if (location === 'review' || CheckoutService.cartCheckout.PaymentMethod.PaymentMethodCode === 'PC-PROMO') {
                                    goToReview();
                                } else {
                                    goToBilling();
                                }
                            });
                    } else {
                        Common.showMessage('danger', '641');
                    }

                },

                showShippingDetailsInfo = function (shippingMethods, shippingAddress) {
                    var modalInstance = $uibModal.open({
                        templateUrl: 'COShippingDetails.html',
                        controller: 'showCOShippingDetailsInfoCtrl',
                        size: 'lg',
                        resolve: {
                            shippingMethods: function () {
                                return shippingMethods;
                            },
                            shippingAddress: function () {
                                return shippingAddress;
                            }
                        }

                    });
                },

                showRealTimeShippingDetailsInfo = function (shippingMethods, shippingAddress) {
                    var modalInstance = $uibModal.open({
                        templateUrl: 'CORealTimeShippingDetails.html',
                        controller: 'showCORealTimeShippingDetailsInfoCtrl',
                        size: 'lg',
                        resolve: {
                            shippingMethods: function () {
                                return shippingMethods;
                            },
                            shippingAddress: function () {
                                return shippingAddress;
                            }
                        }

                    });
                },

                setCartCheckout = function () {

                    if (CheckoutService.cartCheckout) {

                        var cartCheckout = CheckoutService.cartCheckout,
                            cartEmpty = cartCheckout.Items.length === 0;

                        $scope.cartCheckout = cartCheckout;

                        $scope.showThirdPartyShippingAccountSection = !!$scope.cartCheckout.ShippingCaptureConfig && !!$scope.cartCheckout.ShippingCaptureConfig.UseCustomAccount ? $scope.cartCheckout.ShippingCaptureConfig.UseCustomAccount : false;
                        //Do we have validation errors
                        if (cartCheckout.ValidationErrors && cartCheckout.ValidationErrors.length > 0) {

                            //cartCheckout.ValidationErrors = [];
                            CheckoutService.cartCheckout = undefined;
                            $scope.cartCheckout = undefined;

                            var d = new Date().getTime();
                            var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
                                var r = (d + Math.random() * 16) % 16 | 0;
                                d = Math.floor(d / 16);
                                return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
                            });

                            var checkoutPath = 'checkout/validation/';

                            $scope.$scrollTop();
                            $location.path(checkoutPath + uuid);
                        }
                        //Digital Download Only
                        else if (cartCheckout.IsDownloadOnly && !cartEmpty) {
                            goToBilling();
                        }
                        //empty cart
                        else if (cartEmpty) {
                            Common.linkTo('cart');
                        }
                        //Missing Shipping Address
                        else if (!cartCheckout.ShippingAddress) {
                            goToSelectAddress();
                        }
                        else {
                            //reformat needbydate for model and reset if date isn't 7 or more days out
                            if ($scope.cartCheckout.NeedByDate) {
                                $scope.cartCheckout.NeedByDate = new Date($scope.cartCheckout.NeedByDate);
                                if ($scope.cartCheckout.NeedByDate < new Date().setDate(new Date().getDate() + 7)) {
                                    $scope.cartCheckout.NeedByDate = null;
                                }
                            }
                            if ($scope.cartCheckout.NeedByInventory) {
                                $scope.cartCheckout.NeedByInventory = new Date($scope.cartCheckout.NeedByInventory);
                                if ($scope.cartCheckout.NeedByInventory < new Date().setDate(new Date().getDate() + 7)) {
                                    $scope.cartCheckout.NeedByInventory = null;
                                }
                            }
                            //Good to go, get the shipping options
                            if (!$scope.showThirdPartyShippingAccountSection) {
                                getShippingMethods(cartCheckout);
                            }

                            $scope.renderShipping = true;
                        }


                    } else {
                        //Get it from the service
                        $scope.cartCheckout = undefined;
                        CheckoutService.getCheckoutCart()
                    }

                },


                initShipping = function () {

                    setCartCheckout();
                    $scope.$scrollTop();

                    disableWatcher = $scope.$watch(
                        function () { return CheckoutService.cartCheckout; },

                        function (newValue, oldValue) {
                            //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                            if (newValue && (!$scope.cartCheckout || newValue.PromoCodes.length != $scope.cartCheckout.PromoCodes.length)) {
                                setCartCheckout();
                            }
                        },
                        true // indicates object equaility comparison
                    );


                },

                setDefaults = function () {
                    //After cleanup, there wasn't anything that was needed here.
                },

                isPromotionalProduct = function (productNumber) {
                    return Common.isPromotionalProduct(productNumber);
                },

                isMsDcProduct = function (productNumber) {
                    return Common.isMsDcProduct(productNumber);
                },

                getFreeShippingHelpMessage = function (scope, cartItems, shippingMethods) {
                    return Common.getFreeShippingHelpMessage(scope, cartItems, shippingMethods);
                },

                isFreeShippingStores = function (storeCode) {
                    return Common.isFreeShippingStores(storeCode);
                },

                getFreeShippingThreshold = function () {
                    return Common.getFreeShippingThreshold();
                },

                getShippingChargeAmount = function () {
                    return Common.getShippingChargeAmount();
                },

                hasMsDcProduct = function () {
                    return $scope.cartCheckout.Items.some(ci => isMsDcProduct(ci.ProductNumber));
                },

                isAllMsDcProducts = function () {
                    return $scope.cartCheckout.Items.every(ci => isMsDcProduct(ci.ProductNumber));
                },

                checkQueryString = function () {
                    Common.clearQueryStringValue('pid');
                },

                displayShippingOptions = function () {
                    $scope.cartCheckout.ShippingAccountNumber = null;
                    $scope.useThirdPartyShipping = false;
                    CheckoutService.cartCheckout.ShippingAccountNumber = $scope.cartCheckout.ShippingAccountNumber;
                    CheckoutService.updateCheckoutCart().then(function (response) {
                        $scope.showThirdPartyShippingAccountSection = false;
                        getShippingMethods($scope.cartCheckout);
                    });
                },

                displayThirdPartyAccountEntry = function () {
                    $scope.showThirdPartyShippingAccountEntry = true;
                    $scope.showShippingOptions = false;
                },

                dispalyThirdPartyShippingAccountSection = function () {
                    $scope.showThirdPartyShippingAccountSection = true;
                    $scope.showThirdPartyShippingAccountEntry = true;
                    $scope.showShippingOptions = false;
                },

                validateCustomShippingAccountNumber = function () {
                    $scope.useThirdPartyShipping = !!$scope.cartCheckout.ShippingAccountNumber ? true : false;
                    CheckoutService.cartCheckout.ShippingAccountNumber = $scope.cartCheckout.ShippingAccountNumber;
                    CheckoutService.updateCheckoutCart().then(function (response) {
                        $scope.showThirdPartyShippingAccountEntry = true;
                        $scope.showThirdPartyShippingAccountSection = false;
                        getShippingMethods($scope.cartCheckout);
                    });
                };

            openDatePicker = function ($event, elementOpened) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.model[elementOpened] = !$scope.model[elementOpened];
            };

            clearDatePicker = function ($event) {
                $event.preventDefault();
                $scope.cartCheckout.NeedByDate = null;
                $scope.cartCheckout.NeedByInventory = null;
            }

            getBusinessDaysForward = function (daysOut) {
                var today = new Date();
                var date = new Date();
                for (i = 0; i < daysOut; i++) {
                    date.setDate(today.getDate() + i + 1);
                    var dayOfWeek = date.getDay();
                    if (dayOfWeek == 0 || dayOfWeek == 6) {
                        daysOut++;
                    }
                }
                return daysOut;
            }

            checkQueryString();
            $scope.renderShipping = false;
            $scope.toggleHelp = Common.toggleHelp;
            $scope.showShippingOptions = false;
            $scope.updateShippingMethod = updateShippingMethod;
            $scope.updateOnDemandShippingConfirm = updateOnDemandShippingConfirm;
            $scope.showShippingDetailsInfo = showShippingDetailsInfo;
            $scope.showRealTimeShippingDetailsInfo = showRealTimeShippingDetailsInfo;
            $scope.goToPayment = goToPayment;
            $scope.goToSelectAddress = goToSelectAddress;
            $scope.showThirdPartyShippingAccountEntry = false;
            $scope.displayShippingOptions = displayShippingOptions;
            $scope.isMsDcProduct = isMsDcProduct;
            $scope.isFreeShippingStores = isFreeShippingStores;
            $scope.getFreeShippingThreshold = getFreeShippingThreshold;
            $scope.isPromotionalProduct = isPromotionalProduct;
            $scope.isAllMsDcProducts = isAllMsDcProducts;
            $scope.hasMsDcProduct = hasMsDcProduct;
            $scope.displayThirdPartyAccountEntry = displayThirdPartyAccountEntry;
            $scope.validateCustomShippingAccountNumber = validateCustomShippingAccountNumber;
            $scope.dispalyThirdPartyShippingAccountSection = dispalyThirdPartyShippingAccountSection;
            $scope.model = {};
            $scope.openDatePicker = openDatePicker;
            $scope.clearDatePicker = clearDatePicker;

            $scope.orderedForDateOptionsOnDemand = {
                minDate: new Date().setDate(new Date().getDate() + getBusinessDaysForward(7))
            };
            $scope.orderedForDateOptions = {
                minDate: new Date().setDate(new Date().getDate() + getBusinessDaysForward(2))
            };

            $scope.selectedShippingOption = {
                code: '',
                showWarning: false,
                warningConfig: null
            };

            $scope.saveAndProceed = saveAndProceed;

            setDefaults();
            initShipping();

        }])
    .controller('showCOShippingDetailsInfoCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'shippingMethods',
        'shippingAddress',
        function ($scope, Common, $uibModalInstance, shippingMethods, shippingAddress) {
            /* get a copy of shippingMethods to avoid mutating original codes
             * copies will be truncated for display purposes only */
            $scope.shippingMethods = shippingMethods.map(function (elem) {
                var newElem = angular.copy(elem);
                newElem.ShippingMethodCode = newElem.ShippingMethodCode.substring(0, 2);
                return newElem;
            });
            $scope.shippingAddress = shippingAddress;
            $scope.showFedExMap = false;
            $scope.showFedExPolicy = false;
            $scope.showUPSMap = false;
            $scope.showUPSPolicy = false;
            $scope.showBCSExPolicy = false;
            $scope.isDomestic = (shippingAddress.Country == 'US');

            //Examine the options and set the flags
            for (var i = 0; i < $scope.shippingMethods.length; i++) {
                var code = $scope.shippingMethods[i].ShippingMethodCode;

                switch (code) {
                    //UPS Ground
                    case '27':
                    case '17':
                    case '37':
                    case '03':
                    case '11':
                    case '36':
                    case '43':
                    case '62':
                    case '81':
                    case '85':
                        $scope.showUPSMap = true;
                        $scope.showUPSPolicy = true;
                        break;
                    //Other UPS
                    case '39':
                    case '02':
                    case '16':
                    case '35':
                    case '42':
                    case '25':
                    case '15':
                    case '34':
                    case '01':
                    case '14':
                    case '41':
                    case '33':
                    case '04':
                    case '18':
                    case '44':
                    case '26':
                    case '28':
                    case '32':
                    case '06':
                    case '07':
                    case '08':
                    case '52':
                    case '09':
                    case '30':
                    case '10':
                    case '31':
                    case '79':
                    case '80':
                    case '82':
                    case '83':
                    case '84':
                        $scope.showUPSPolicy = true;
                        break;
                    //FedEx Ground
                    case '23':
                    case '66':
                    case '24':
                    case '23F':
                    case '24F':
                    case '87':
                        $scope.showFedExMap = true;
                        $scope.showFedExPolicy = true;
                        break;
                    //Other FedEx
                    case '20':
                    case '21':
                    case '22':
                    case '50':
                    case '51':
                    case '63':
                    case '64':
                    case '65':
                    case '68':
                    case '69':
                    case '70':
                    case '71':
                    case '72':
                    case '73':
                    case '74':
                    case '75':
                    case '50F':
                        $scope.showFedExPolicy = true;
                        break;
                    case '86':
                        $scope.showBCSPolicy = true;
                        break;
                    default:
                        $scope.showUPSPolicy = true;
                }

            }

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }])
    .controller('showCORealTimeShippingDetailsInfoCtrl', [
        '$scope',
        '$sce',
        '$uibModalInstance',
        'shippingMethods',
        'shippingAddress',
        function ($scope, $sce, $uibModalInstance, shippingMethods, shippingAddress) {
            /* get a copy of shippingMethods to avoid mutating original codes
             * copies will be truncated for display purposes only */
            $scope.shippingMethods = shippingMethods;
            $scope.shippingAddress = shippingAddress;
            $scope.showFedExMap = false;
            $scope.showUPSMap = false;

            $scope.isDomestic = (shippingAddress.Country == 'US');
            const map = new Map();
            $scope.shippingPolicies = [];
            //Examine the options and set the flags
            for (var i = 0; i < $scope.shippingMethods.length; i++) {

                var carrierName = $scope.shippingMethods[i].Carrier.toLowerCase();

                if (!$scope.showFedExMap && carrierName === "fedex" && $scope.shippingMethods[i].IsGround)
                    $scope.showFedExMap = true;

                if (!$scope.showUPSMap && carrierName === "ups" && $scope.shippingMethods[i].IsGround)
                    $scope.showUPSMap = true;

                $scope.isMicrosoft = $scope.$parent.store.StoreCode === 'MEC' || $scope.$parent.store.StoreCode === 'MIC'
                if (!map.has(carrierName)) {
                    map.set(carrierName, true);    // set any value to Map
                    $scope.shippingPolicies.push({
                        carrierName: $scope.shippingMethods[i].Carrier,
                        shippingPolicy: $scope.isDomestic ? $sce.trustAsHtml($scope.shippingMethods[i].CarrierPolicies) : $sce.trustAsHtml($scope.shippingMethods[i].CarrierIntlPolicies)
                    });
                }
            }

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };


        }]);
;angular
    .module('ecs.ctrl.selectAddress', [])
    .controller('selectAddressCtrl', [
        '$log',
        '$scope',
        '$location',
        '$sce',
        'Constants',
        'Objects',
        'Common',
        'ShoppingCarts',
        'Customers',
        'AddressService',
        'CheckoutService',
        'Stores',
        function ($log, $scope, $location, $sce, Constants, Objects, Common, ShoppingCarts, Customers, AddressService, CheckoutService, Stores) {

            var loadingShippingAddresses = true,
                loadingReadOnlyAddresses = true,
                loadingConfirmAddresses = false,


                useAddress = function (address, type) {
                    var addressList = [];
                    if ($scope.cartCheckout.ShippingCaptureConfig && ((type == 'readonly' && $scope.cartCheckout.ShippingCaptureConfig.ReadOnlyEditRecipient) ||
                        (type == 'lookup' && $scope.cartCheckout.ShippingCaptureConfig.LookupEditRecipient))) {
                        $scope.loadingConfirmAddresses = true;
                        $scope.cartCheckout.ShippingAddress = address;
                        $scope.cartCheckout.ShippingAddress.CompanyName = $scope.cartCheckout.ShippingAddress.Name;
                        $scope.cartCheckout.ShippingAddress.Name = "ATTN: " + $scope.user.Name;
                    } else {
                        CheckoutService.cartCheckout.ShippingAddress = address;
                        CheckoutService.updateCheckoutCart()
                            .then(function () {
                                //they can't edit - send them on their way
                                $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                            });
                    }
                    if (!!$scope.cartCheckout.ShippingAddress)
                        addressList.push($scope.cartCheckout.ShippingAddress);

                    getFreeShippingHelpMessage($scope, CheckoutService.cartCheckout.Items, addressList);
                },


                updateCheckoutCart = function () {

                    return CheckoutService.updateCheckoutCart();
                },
                editAddress = function (address) {
                    $location.path('/checkout/shipping/shipping-address/' + Common.getCurrentCheckoutUTSID()).search('pid', address.AddressId);
                },

                addNewAddress = function () {
                    $location.path('/checkout/shipping/shipping-address/' + Common.getCurrentCheckoutUTSID());

                },

                cancelAddressChange = function () {
                    $scope.cartCheckout.ShippingAddress.Name = $scope.cartCheckout.ShippingAddress.CompanyName;
                    $scope.cartCheckout.ShippingAddress.CompanyName = "";
                    $scope.loadingConfirmAddresses = false;
                },

                confirmAddressChange = function () {

                    if (!$scope.cartCheckout.ShippingAddress.Name) {
                        Common.showMessage('error', 'Please provide a contact name for this order.');
                        return;
                    }

                    if ($scope.cartCheckout.ShippingAddress.Country !== 'US' && !$scope.cartCheckout.ShippingAddress.Phone) {
                        Common.showMessage('error', 'Please provide a contact phone number for this order.');
                        return;
                    }

                    //by setting UpdateFlags to 2 api will create it on the fly
                    $scope.cartCheckout.ShippingAddress.UpdateFlags = 2;
                    CheckoutService.cartCheckout.ShippingAddress = $scope.cartCheckout.ShippingAddress;
                    CheckoutService.updateCheckoutCart()
                        .then(function () {
                            //they can't edit - send them on their way
                            $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                        });
                },


                getShippingAddress = function (customerId) {

                    AddressService.getShippingAddress(customerId, "CO")
                        .then(function (response) {
                            $scope.shipping.shippingAddress = response.data;
                            $scope.loadingShippingAddresses = false;

                            if ($scope.shipping.shippingAddress.length === 0 && (!$scope.cartCheckout.ShippingCaptureConfig || $scope.cartCheckout.ShippingCaptureConfig.Type === 'Standard')) {
                                addNewAddress();
                            }
                        });

                },

                getReadOnlyAddress = function (shippingCaptureConfig) {

                    if (!shippingCaptureConfig.ReadOnlyType || shippingCaptureConfig.ReadOnlyType === '') {
                        //We don't have the configuration for the Ready Only type... just get out of here
                        $scope.loadingReadOnlyAddresses = false;
                    }
                    else {
                        Stores.searchAddresses($scope.store.StoreCode, shippingCaptureConfig.ReadOnlyType, "")
                            .then(function (response) {
                                $scope.shipping.readOnlyAddresses = response.data;
                                $scope.loadingReadOnlyAddresses = false;
                            });
                    }

                }

            setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {

                    var cartCheckout = CheckoutService.cartCheckout;
                    $scope.showFreeShippingHelpMessage = false;
                    $scope.cartCheckout = cartCheckout;
                    var addressList = [];

                    if (!!$scope.cartCheckout.ShippingAddress)
                        addressList.push($scope.cartCheckout.ShippingAddress);

                    getFreeShippingHelpMessage($scope, CheckoutService.cartCheckout.Items, addressList);
                    $scope.cartCheckout.ShippingAddress = addressList[0];

                    //Check the Shipping Capture config to see if we need to load the customers shipping addresses
                    if (!cartCheckout.ShippingCaptureConfig || cartCheckout.ShippingCaptureConfig.Type === 'Standard' || cartCheckout.ShippingCaptureConfig.Type === 'StandardAndAddressLookUp' || cartCheckout.ShippingCaptureConfig.Type === 'StandardAndReadOnly' || cartCheckout.ShippingCaptureConfig.Type === 'All') {
                        if (!!cartCheckout.ShippingCaptureConfig && !!$scope.cartCheckout.ShippingCaptureConfig.StandardCaption)
                            $scope.cartCheckout.ShippingCaptureConfig.StandardCaption = $sce.trustAsHtml($scope.cartCheckout.ShippingCaptureConfig.StandardCaption);
                        getShippingAddress(cartCheckout.SoldToCustomerId);
                    }
                    else
                        $scope.loadingShippingAddresses = false;


                    //Check if we need to load the read only addresses for the store
                    if (!!cartCheckout.ShippingCaptureConfig && (cartCheckout.ShippingCaptureConfig.Type === 'ReadOnly' || cartCheckout.ShippingCaptureConfig.Type === 'StandardAndReadOnly' || cartCheckout.ShippingCaptureConfig.Type === 'All')) {
                        $scope.cartCheckout.ShippingCaptureConfig.ReadOnlyCaption = $sce.trustAsHtml($scope.cartCheckout.ShippingCaptureConfig.ReadOnlyCaption);
                        getReadOnlyAddress(cartCheckout.ShippingCaptureConfig);
                    }
                    else
                        $scope.loadingReadOnlyAddresses = false;

                    //check if we have a default value for the address lookup
                    if (!!cartCheckout.ShippingCaptureConfig && (cartCheckout.ShippingCaptureConfig.Type === 'AddressLookUp' || cartCheckout.ShippingCaptureConfig.Type === 'StandardAndAddressLookUp' || cartCheckout.ShippingCaptureConfig.Type === 'All') && !!cartCheckout.ShippingCaptureConfig.AddressLookUpDefault) {
                        $scope.cartCheckout.ShippingCaptureConfig.AddressLookUpCaption = $sce.trustAsHtml($scope.cartCheckout.ShippingCaptureConfig.AddressLookUpCaption);
                        $scope.shipping.addressLookUpValue = cartCheckout.ShippingCaptureConfig.AddressLookUpDefault;
                        lookupAddress();
                    }

                } else {
                    $scope.cartCheckout = undefined;
                    CheckoutService.getCheckoutCart()
                }

            },


                init = function () {

                    $scope.$scrollTop();

                    setCartCheckout();

                    $scope.$watch(
                        function () { return CheckoutService.cartCheckout; },

                        function (newValue, oldValue) {
                            //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                            if (newValue && !$scope.cartCheckout) {
                                setCartCheckout();
                            }
                        },

                        true // indicates object equaility comparison
                    );

                },

                getFreeShippingHelpMessage = function (scope, cartItems, shippingMethods) {
                    if(shippingMethods.length > 0)
                        shippingMethods[0].IsInternational = shippingMethods[0].Country !== "US";
                    
                    return Common.getFreeShippingHelpMessage(scope, cartItems, shippingMethods);
                },

                setDefaults = function () {
                    Common.clearQueryStringValue('pid');
                },

                lookupAddress = function ($event) {
                    $scope.shipping.lookupAddressResult = null;
                    Stores.getAddressByAddressId($scope.store.StoreCode, $scope.cartCheckout.ShippingCaptureConfig.AddressLookUpType, $scope.shipping.addressLookUpValue)
                        .then(function (response) {
                            $scope.shipping.lookupAddressResult = response.data;
                        });
                },
                goToPayment = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    $location.path('/checkout/payment/' + Common.getCurrentCheckoutUTSID());

                },
                standardAddressFilter = function (address) {
                    return addressFilterByTerm(address, $scope.shipping.addressStandardFilterValue.toUpperCase());
                },
                readOnlyAddressFilter = function (address) {
                    return addressFilterByTerm(address, $scope.shipping.addressReadOnlyFilterValue.toUpperCase());
                },
                addressFilterByTerm = function (address, searchTerm) {

                    if ($scope.cartCheckout.IsPunchout && $scope.currentCustomerId == address.PartnerNumber) {

                        return false;
                    }
                    else {
                        return (searchTerm === ''
                            || (!!address.Name && address.Name.toUpperCase().match(searchTerm))
                            || (!!address.City && address.City.toUpperCase().match(searchTerm))
                            || (!!address.State && address.State.toUpperCase().match(searchTerm)));
                    }
                };

            $scope.shipping = {};
            $scope.shipping.shippingAddress = [];
            $scope.shipping.readOnlyAddresses = [];
            $scope.shipping.lookupAddressResult = null;
            $scope.shipping.addressReadOnlyFilterValue = '';
            $scope.shipping.addressStandardFilterValue = '';
            $scope.loadingShippingAddresses = loadingShippingAddresses;
            $scope.loadingReadOnlyAddresses = loadingReadOnlyAddresses;
            $scope.loadingConfirmAddresses = loadingConfirmAddresses;
            $scope.useAddress = useAddress;
            $scope.goToPayment = goToPayment;

            $scope.editAddress = editAddress;
            $scope.addNewAddress = addNewAddress;
            $scope.lookupAddress = lookupAddress;
            $scope.standardAddressFilter = standardAddressFilter;
            $scope.readOnlyAddressFilter = readOnlyAddressFilter;

            $scope.cancelAddressChange = cancelAddressChange;
            $scope.confirmAddressChange = confirmAddressChange;

            $scope.getFreeShippingHelpMessage = getFreeShippingHelpMessage;
            //Used to identify the customer's billing address 
            $scope.currentCustomerId = $scope.user.CustomerId;

            setDefaults();
            init();

        }]);;angular
    .module('ecs.ctrl.selectThirdPartyShipping', [])
    .controller('selectThirdPartyShippingCtrl', [
        '$log',
        '$rootScope',
        '$scope',
        '$location',
        'Common',
        'CheckoutService',
        'Stores',
        function ($log, $rootScope, $scope, $location, Common, CheckoutService, Stores) {

            $scope.selectedThirdPartyShippingAccountNumber = {};
            var loadingThirdPartyShippingAccount = true,

            getThirdPartyShippingAccountNumbers = function () {
                var storeCode = $rootScope.store.StoreCode;
                Stores.getThirdPartyShippingAccountNumbers(storeCode)
                    .then(function (response) {
                        $scope.thirdPartyShippingAccountNumbers = response.data;
                        $scope.loadingThirdPartyShippingAccount = false;
                    });
            },

            setCartCheckout = function () {
                if (CheckoutService.cartCheckout) {
                    var cartCheckout = CheckoutService.cartCheckout;
                    $scope.cartCheckout = cartCheckout;

                    getThirdPartyShippingAccountNumbers();
                } else {
                    $scope.cartCheckout = undefined;
                    CheckoutService.getCheckoutCart()
                }
            },

            init = function () {

                $scope.$scrollTop();

                setCartCheckout();

                $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                        if (newValue && !$scope.cartCheckout) {
                            setCartCheckout();
                        }
                    },

                    true // indicates object equaility comparison
                );
           
            },

            setDefaults = function () {
                Common.clearQueryStringValue('pid');
            },

            goToPayment = function ($event) {
                if ($event)
                    $event.preventDefault();

                $location.path('/checkout/payment/' + Common.getCurrentCheckoutUTSID());

            },

            goToShipping = function ($event) {
                if ($event)
                    $event.preventDefault();

                if (!!$scope.cartCheckout.selectedThirdPartyShippingAccountNumber) {
                    CheckoutService.cartCheckout.ThirdPartyShippingAccountNumber = $scope.cartCheckout.selectedThirdPartyShippingAccountNumber.AccountNumber;
                    CheckoutService.updateCheckoutCart()
                        .then(function () {
                            $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                        });
                } else {
                    $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                }
                };

            $scope.loadingThirdPartyShippingAccount = loadingThirdPartyShippingAccount;
            $scope.goToPayment = goToPayment;
            $scope.goToShipping = goToShipping;
            $scope.currentCustomerId = $scope.user.CustomerId;

            setDefaults();
            init();

        }]);;angular
    .module('ecs.ctrl.addOrEditAddress', [])
    .controller('addOrEditAddressCtrl', [
        '$log',
        '$scope',
        '$location',
        'Constants',
        'Objects',
        'Common',
        'ShoppingCarts',
        'Customers',
        'AddressService',
        'CheckoutService',
        function ($log, $scope, $location, Constants, Objects, Common, ShoppingCarts, Customers, AddressService, CheckoutService) {


            var loadingShippingAddresses = true,
            
                
            useAddress = function (address) {

                CheckoutService.cartCheckout.ShippingAddress = address;
                CheckoutService.updateCheckoutCart()
                    .then(function () {
                        $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                    });
            },



            useEditedAddress = function () {
                var err = $scope[$scope.activeForm].$error,
                    address = $scope.customer.ShippingAddress,
                    self = this;

                $scope.submitted = true;
                $scope.showAddressEditMessage = false;

                if (address.Country === 'US' && ($scope[$scope.activeForm].City.$dirty || $scope[$scope.activeForm].PostalCode.$dirty)) {

                    return AddressService.updateTaxJurisdictions($scope, $scope.activeForm)
                            .then(function (response) {
                                useEditedAddress();
                            });

                } else {

                    if ($scope[$scope.activeForm].$valid) {
                        if ($scope.customer.ShippingAddress.Name.trim().split(/\W+/).length >= 2) {
                            //Make sure the state is not set if the country doesn't have states
                            if ($scope.states.length === 0) {
                                address.State = "";
                            }

                            if ($scope.isAddNewAddress) {
                                if ($scope.cartCheckout.IsPunchout) {
                                    address.UpdateFlags = 3;
                                }

                                return Customers.addAddress($scope.user.CustomerId, 'shipping', address)
                                    .then(function (response) {
                                        $scope.submitted = false;
                                        $scope.isAddNewAddress = false;
                                        $scope[$scope.activeForm].$setPristine();
                                        useAddress(response.data);
                                    });
                            }
                            else {
                                //Let's call useAddress to be consistent with code above
                                //CheckoutService.cartCheckout.ShippingAddress = address;
                                return Customers.updateAddress($scope.user.CustomerId, address)
                                    .then(function () {
                                        $scope.submitted = false;
                                        $scope[$scope.activeForm].$setPristine();
                                        useAddress(address);
                                        //This happens in useAddress along with a few other things
                                        //updateCheckoutCart()

                                    });

                            }
                        } else {
                            Common.showMessage('danger', '643');
                        }
                    } else {
                        Common.showMessage('danger', '615');
                    }

                }

            },

            
            updateCheckoutCart = function () {

                return CheckoutService.updateCheckoutCart();
            },

            
            cancelEditAddress = function () {
                
                $location.path('/checkout/shipping/select-shipping-address/' + Common.getCurrentCheckoutUTSID());

            },

            getShippingAddress = function (customerId, addressId) {

                AddressService.getAddress(customerId, 'shipping', addressId)
                    .then(function (response) {
                        $scope.customer = {};
                        $scope.customer.ShippingAddress = response.data;
                        $scope.loadingShippingAddresses = false;

                        //Get the states/regions (which will also get the Tax Juridiction if necessary) for our address
                        AddressService.getStateOrRegions($scope, $scope.customer.ShippingAddress.Country);
                    });

            },
            setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {

                    var cartCheckout = CheckoutService.cartCheckout;
                    $scope.cartCheckout = cartCheckout;

                } else {
                    $scope.cartCheckout = undefined;
                    CheckoutService.getCheckoutCart()

                }

            },


            init = function () {

                var id = $location.search().pid;
                $('#Name').keydown(e => {
                    var charCode = event.keyCode;

                    if ((charCode > 64 && charCode < 91) || (charCode > 96 && charCode < 123) || charCode == 8 || charCode == 32)

                        return true;
                    else
                        return false;
                });
                $scope.$scrollTop();
                setCartCheckout();

                $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                        if (newValue && !$scope.cartCheckout) {
                            setCartCheckout();
                        }
                    },

                    true // indicates object equaility comparison
                );


                if (!id) {
                    $scope.isAddNewAddress = true;
                    $scope.loadingShippingAddresses = false;

                    //New address, create empty Shipping Address in US for start
                    createDefaultEmptyAddress();
                    

                } else {
                    $scope.showAddressEditMessage = true;
                    getShippingAddress($scope.user.CustomerId, id);
                }
                
            },

            setDefaults = function () {

                AddressService.getCountries($scope, 'Shipping');

            },
            createDefaultEmptyAddress = function () {

                $scope.customer = {};
                $scope.customer.ShippingAddress = {};
                $scope.customer.ShippingAddress.Country = 'US';

                //Go ahead and load the US states, clear out any tax juridictions
                $scope.taxJurisdictions = [];
                AddressService.getStateOrRegions($scope, $scope.customer.ShippingAddress.Country);
            },


            onCountryChanged = function () {
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);

            },

            updateTaxJurisdictions = function (reset, form) {
                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            },

            addNewAddress = function () {
                createDefaultEmptyAddress();
                $scope.isAddNewAddress = true;
                $scope.loadingShippingAddresses = false;
                $scope.showAddressEditMessage = false;
            };

            $scope.addressType = 'ShippingAddress';
            $scope.activeForm = 'shippingForm';
            $scope.loadingShippingAddresses = loadingShippingAddresses;
            $scope.useEditedAddress = useEditedAddress;
            $scope.addNewAddress = addNewAddress;
            $scope.cancelEditAddress = cancelEditAddress;
            $scope.showCountyAndJurisdiction = false;
           
            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.isAddNewAddress = false;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;

            init();
            setDefaults();

        }]);;angular
    .module('ecs.ctrl.register', [])
    .controller('registerCtrl', [
        '$scope',
        '$location',
        'AddressService',
        'Constants',
        'Common',
        'Objects',
        'Customers',
        'Employees',
        'StorePasses',
        '$log',
        '$window',
        '$http',

        function ($scope, $location, AddressService, Constants, Common, Objects, Customers, Employees, StorePasses, $log, $window, $http) {


            /*
            This method just populates dummy data into the $scope.

            */
            var getCustomer = function () {

                var customer = {
                    FullName: '',
                    firstName: null,
                    lastName: null,
                    Email: '',
                    EmailConfirm: '',
                    Phone: '',
                    Extension: '',
                    Fax: '',
                    BillingAddress: {
                        Name: '',
                        AddressType: '',
                        CompanyName: '',
                        Phone: '',
                        Extension: '',
                        Email: '',
                        EmailConfirm: '',
                        Address1: '',
                        Address2: '',
                        City: '',
                        State: '',
                        PostalCode: '',
                        Country: 'US',
                        TaxJurisdictionCode: ''
                    },
                    PasswordReminder: '',
                    NotificationSettings: {
                        //NewsletterEmails: true,
                        MarketingEmails: true
                    },

                    CustomerCredentials: {
                        UserName: '',
                        Password: '',
                        PasswordVerify: ''

                    },
                    enableEmail: true,
                    Organization: { CostCenter: '' },
                    EmployeeType: ''


                }

                return customer;
            },

            initPaymentCard = function () {

                var year = new Date().getFullYear().toString();

                var paymentCard = {
                    CardType: null,
                    CardNumber: '',
                    ExpirationMonth: "01",
                    ExpirationYear: year,
                    Name: '',
                    CVV: ''

                }

                return paymentCard;
            },
            setDefaults = function () {
                var customer = getCustomer();

                $scope.customer = customer;
                $scope.addressType = 'BillingAddress';

                AddressService.getCountries($scope, 'Billing');
                AddressService.getStateOrRegions($scope, customer[$scope.addressType].Country);

                var paymentCard = initPaymentCard();
                $scope.storePassCC = paymentCard;


            },


            getNotificationSettings = function () {

                $scope.customer.NotificationSettings = $scope.customer.NotificationSettings || {};

                var notifications = [],
                        newsletterEmails = { Type: 'Newsletters', Enabled: $scope.customer.NotificationSettings.NewsletterEmails },
                        marketingEmails = { Type: 'Emails', Enabled: $scope.customer.NotificationSettings.MarketingEmails };

                if (newsletterEmails) {
                    notifications.push(newsletterEmails);
                }

                if (marketingEmails) {
                    notifications.push(marketingEmails);
                }

                return notifications;

            },


            submitForm = function (form, returnUrl) {

                var self = this;
                $scope.returnUrl = returnUrl;
                $scope.submitted = true;



                if ($scope.customer.firstName !== null && $scope.customer.lastName !== null) {
                    if (!AddressService.testNameValidity(form, $scope.customer)) {
                        Common.showMessage('danger', '678');
                        return;
                    }
                    $scope.customer.FullName = $scope.customer.firstName + ' ' + $scope.customer.lastName;
                }

                // This is to handle in MIP, and since this is the only store we hide the data consent checkbox
                // in the registration, the user is automatically agree to the data consent upon registering the account
                if ($scope.hideDataConsentCheckbox) {
                    $scope.customer.DataConsent = true;
                }

                if (!$scope.customer.DataConsent) {
                    Common.showMessage('error', 'You must accept the Data Subject Consent policy before continuing.');
                    return;
                }

                $scope.customer[$scope.addressType].Name = $scope.customer.FullName;
                $scope.customer.CompanyName = $scope.customer[$scope.addressType].CompanyName;
                $scope.customer.Phone = $scope.customer[$scope.addressType].Phone;
                $scope.customer.Extension = $scope.customer[$scope.addressType].Extension;
                $scope.customer.Email = $scope.customer[$scope.addressType].Email;
                $scope.customer.EmailConfirm = $scope.customer[$scope.addressType].EmailConfirm;
                
                //$scope.customer.DataConsent = $scope.customer[$scope.addressType].DataConsent;

                form.$valid = true;

                if (form.$valid) {

                    $scope.customer.NotificationSettings = getNotificationSettings();


                    //Make sure the state is not set if the country doesn't have states
                    if ($scope.states.length === 0) {
                        $scope.customer[$scope.addressType].State = "";
                    }

                    //Passholders have to authorize CC before settting Username

                    if (!$scope.StorePass || $scope.customer.VerifyCreditCard == 0) {
                        $scope.customer.CustomerCredentials.SkipCreatingUserName = false;
                        $scope.customer.CustomerCredentials.SkipCreatingSAPCustomer = false;
                        Common.showLoader('106');
                    }
                    else {
                        $scope.customer.CustomerCredentials.SkipCreatingUserName = true;
                        Common.showLoader('123');
                    }



                    Customers.createCustomer($scope.customer)
                      .then(function (response) {
                          $scope.$scrollTop();
                          $log.log('Customer created!');
                          $scope.submitted = false;
                          $scope.customer.Organization.CostCenter = response.data.CostCenter;
                          
                          if (!$scope.StorePass || $scope.customer.VerifyCreditCard == 0) {
                              $scope.isRedirectToLogin = true;
                              loginNewCustomer($scope.returnUrl, response.data);
                          }
                          else {
                              $scope.isRegisteredStorePass = true;
                              $scope.storePassCC.Name = $scope.customer.FullName;
                              $scope.storePassCC.VerifyCreditCard = $scope.customer.VerifyCreditCard;
                              $scope.storePassCC.CardType = null; //default to visa but they can change
                              $scope.customer.CustomerId = response.data.CustomerId;
                          }

                          //$rootScope.$broadcast('loader_hide');
                      });


                } else {
                    Common.showMessage('danger', '615');
                }

            },


            verifyEmployee = function (form) {
                $scope.verifySubmitted = true;
                if (form.$valid) {

                    var data = {};
                    data.EmployeeId = $scope.employeeCredentials.employeeId;
                    data.LastName = $scope.employeeCredentials.employeeLastName;


                    Employees.verifyEmployee(data)
                      .then(function (response) {
                          $log.log('Verify Employee Response Received!');
                          $scope.employee = response.data;
                          $scope.isVerified = true;
                          //Default in the fields you can about the User

                          $scope.customer.FullName = $scope.employee.EmployeeName;
                          $scope.customer.firstName = $scope.employee.EmployeeFirstName;
                          $scope.customer.lastName = $scope.employee.EmployeeLastName;
                          $scope.customer.CustomerCredentials.UserName = $scope.employeeCredentials.employeeId;
                          $scope.customer.VerifiedStoreCode = true;
                          $scope.customer.enableEmail = true;
                          if (!!$scope.employee.EmployeeEmail && $scope.employee.EmployeeEmail !== '') {
                              $scope.customer.enableEmail = false;
                              $scope.customer.Email = $scope.employee.EmployeeEmail;
                              $scope.customer[$scope.addressType].Email = $scope.employee.EmployeeEmail;
                          }
                          $scope.customer.EmployeeType = $scope.employee.EmployeeType;
                      });
                }

            },
            verifyRegAccessCode = function (form) {
                $scope.verifySubmitted = true;
                if (form.$valid) {
                    var verifyAccessCodeApi = App.Configuration.RootPath + 'User/RegistraionAccessCode',
                                        request;

                    var data = {};
                    data.AccessCode = $scope.accessCodeCredentials.accessCode;

                    request = $http({
                        method: "post",
                        url: verifyAccessCodeApi,
                        data: JSON.stringify(data)
                    });

                    request.success(function (response) {

                        if (response && response.IsVerified) {
                            $scope.isVerifiedAccessCode = true;
                            $scope.customer.CustomerCredentials.IdentityProviderName = "PWPTS";
                            $scope.customer.CustomerCredentials.IdentityProviderToken = response.IdToken;
                        }
                        else {
                            $scope.isVerifiedAccessCode = false;
                            $scope.accessCodeCredentials.failedAttempts += 1;
                            Common.showMessage('danger', '626');
                        }
                    });

                    request.error(function (response) {
                        $scope.isVerifiedAccessCode = false;
                        Common.showMessage('danger', '624');
                    });
                }
            },
            verifyStorePass = function (form) {
                $scope.verifySubmitted = true;
                //$scope.isVerifiedStorePass = true;
                if (form.$valid) {

                    var data = {};
                    data.StorePassNumber = $scope.storePassCredentials.storePassNumber;
                    data.AuthorizationCode = $scope.storePassCredentials.storePassAuthCode;

                    StorePasses.verifyStorePass(data)
                        .then(function (response) {
                            $log.log('Verify Store Pass Response Received!');
                            $scope.StorePass = response.data;
                            $scope.isVerifiedStorePass = true;
                            $scope.isStorePassAlreadyRegistered = false;

                            $scope.customer.FullName = $scope.StorePass.PassholderName;
                            $scope.customer.firstName = $scope.StorePass.FirstName;
                            $scope.customer.lastName = $scope.StorePass.LastName;
                            $scope.customer.CustomerCredentials.UserName = $scope.storePassCredentials.storePassNumber;
                            $scope.customer.VerifiedStoreCode = true;
                            $scope.customer.VerifyCreditCard = $scope.StorePass.VerifyCreditCard;
                            $scope.showConfirmCountry = $scope.StorePass.ConfirmCountry;
                            if (!$scope.showConfirmCountry) {
                                $scope.showTerms = $scope.StorePass.ConfirmTerms;
                                if (!$scope.showTerms)
                                    $scope.showRegitration = true;
                            }
                            else
                            {
                                $scope.StorePass.confirmedCountry = $scope.StorePass.Country;
                                //Go get the specific FAF countries
                                $scope.countries = [];
                                AddressService.getCountries($scope, 'FAF');
                            }
                            $scope.customer.enableEmail = true;
                            if (!!$scope.StorePass.PassholderEmail && $scope.StorePass.PassholderEmail !== '') {
                                $scope.customer.enableEmail = false;
                                $scope.customer.Email = $scope.StorePass.PassholderEmail;
                                $scope.customer[$scope.addressType].Email = $scope.StorePass.PassholderEmail;
                            }
                        },
                        function (errResponse) {
                            if (errResponse.data.errorCode === "412")
                                $scope.isStorePassAlreadyRegistered = true;
                        });
                }
            },
            
            acceptTermsAndCondition = function () {
                $scope.showRegitration = true;
                $scope.showTerms = false;
            },

            confirmCountry = function () {
                if ($scope.StorePass.confirmedCountry !== '') {
                    $scope.showTerms = true;
                    $scope.showConfirmCountry = false;


                    var countryFromDropDown = IESUCKS_ArrayFind($scope.countries, function (country) {
                        return country.CountryCode == $scope.StorePass.confirmedCountry;
                    });

                    if (!countryFromDropDown) {
                        Common.showMessage('danger', '637');
                        return;
                    }

                    var confirmedCountry = {}
                        , overrideCountriesArray = [];
                    confirmedCountry.CountryCode = $scope.StorePass.confirmedCountry
                    confirmedCountry.CountryName = countryFromDropDown.CountryName;
                    overrideCountriesArray.push(confirmedCountry);

                    $scope.countries = overrideCountriesArray;
                    $scope.customer.BillingAddress.Country = $scope.StorePass.confirmedCountry;
                    AddressService.getStateOrRegions($scope, $scope.StorePass.confirmedCountry);
                }
                else {
                    //Something is not right, must select their country
                    Common.showMessage('danger', '637');
                }
            },

            IESUCKS_ArrayFind = function(arr, callback) {
                for (var i = 0; i < arr.length; i++) {
                    var match = callback(arr[i]);
                    if (match) {
                        return arr[i];
                        break;
                    }
                }
            }

            verifyCCForStorePass = function (form) {

                var self = this;

                if ($scope.storePassCC.VerifyCreditCard == 2 && !$scope.storePassCC.ack) {
                    Common.showMessage('danger', '625');
                }
                else {
                    $scope.storePassCCExpDateValid = checkCardExpDate();
                    $scope.isValidCard = Common.validateCreditCard($scope.storePassCC.CardNumber, $scope.storePassCC.CardType);

                    $scope.verifyCCSubmitted = true;
                    if (form.$valid && $scope.storePassCCExpDateValid && $scope.isValidCard) {

                        Common.showLoader('122');

                        Customers.authorizeCreditCards($scope.customer.CustomerId, $scope.storePassCC)
                            .then(function (response) {
                                $log.log('Authorize Store Pass Response Received!');
                                $scope.ccAuth = response.data;

                                if ($scope.ccAuth.IsAuthorized) {

                                    $scope.customer.CustomerCredentials.SkipCreatingUserName = false;
                                    $scope.customer.CustomerCredentials.SkipCreatingSAPCustomer = true;

                                    $scope.$scrollTop();
                                    //Even though they are technically are not done with registration, I'm going to go ahead and show this message
                                    $scope.isRedirectToLogin = true;

                                    Customers.createCustomer($scope.customer)
                                      .then(function (response) {
                                          $log.log('Customer created!');
                                          $scope.submitted = false;
                                          loginNewCustomer($scope.returnUrl, response.data);
                                      });
                                }
                                else {
                                    Common.showMessage('danger', '420');
                                }

                            });
                    }
                    else {

                        if (!$scope.isValidCard)
                            Common.showMessage('danger', '620');
                        else if (!$scope.storePassCCExpDateValid)
                            Common.showMessage('danger', '618');
                        else
                            Common.showMessage('danger', '615');
                    }
                }


            },

            checkCardExpDate = function () {

                var month = $scope.storePassCC.ExpirationMonth,
                    year = $scope.storePassCC.ExpirationYear,
                    expDate = new Date(year, month, 0),
                    dateValid = false;

                if (expDate.getTime() >= new Date().getTime()) {
                    dateValid = true;
                };

                return dateValid;
            },


            cancelRegistration = function (returnUrl, customer) {

                var redirectPathBuilder = [App.Configuration.RootPath];
                $window.location.href = redirectPathBuilder.join("");

            },

            loginNewCustomer = function (returnUrl, customer) {

                var redirectPathBuilder = [App.Configuration.RootPath + "Home/Logon/?token=", customer.CustomerCredentials.LoginToken, "&returnUrl=", returnUrl];
                $window.location.href = redirectPathBuilder.join("");

            },

            onCountryChanged = function () {
                resetSelectedStateValue();
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);

            },

            resetSelectedStateValue = function () {
                $scope.customer[$scope.addressType].State = "";
            },

            updateTaxJurisdictions = function (reset, form) {

                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            },

            setCardToken = function (token, cardType) {
                if (!!token && token !== '') {
                    $scope.storePassCC.CardNumber = token;
                    $scope.storePassCC.CardType = setCardTypeFromBrand(cardType) || setCardTypeFromToken(token);
                }
                else {
                    $scope.storePassCC.CardNumber == null;
                    $scope.storePassCC.CardType == null;
                }
                $scope.$apply();
            },

            setCardTypeFromToken = function (token) {
                if (!!token && token !== '') {
                    var ccFirstDigit = token.substring(1, 2);
                    if (ccFirstDigit == '4')
                        return "VISA"
                    else if (ccFirstDigit == '5' || ccFirstDigit == '2')
                        return "MC"
                    else if (ccFirstDigit == '6')
                        return "DISC"
                    else if (ccFirstDigit == '3')
                        return "AMEX"
                    else
                        return null;
                }
                else {
                    return null;
                }
            },
            setCardTypeFromBrand = function (name) {
                if (!name)
                    return null;
                else {
                    var upper = name.toUpperCase();
                    switch (upper) {
                        case "VISA":
                            return "VISA";
                        case "MC":
                        case "MASTERCARD":
                            return "MC";
                        case "DISC":
                        case "DISCOVER":
                            return "DISC";
                        case "AMEX":
                            return "AMEX";
                        default:
                            return null;
                    }
                }
            },

            setCCHandler = function () {
                var self = this;
                $window.addEventListener('message', function (e) {
                    Common.parseCreditCardTokenMessage(e, (token, cardType) => {
                        self.setCardToken(token, cardType);
                    });
                });
            };

            setCCHandler();
            setDefaults();

            $scope.activeForm = 'regForm';

            $scope.hideDataConsentCheckbox = $scope.store.StoreCode == "MIP"
            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.isRedirectToLogin = false;
            $scope.isVerified = false;
            $scope.isVerifiedAccessCode = false;
            $scope.isVerifiedStorePass = false;
            $scope.isRegisteredStorePass = false; //These names are really close. This flag is indicates once we've registered a new pass.
            $scope.isStorePassAlreadyRegistered = false; //This flag indicates the pass was already registered. We'd find that out when verifying the pass.
            $scope.isAuthenticatedStorePass = false;
            $scope.verifyCCSubmitted = false;
            $scope.verifySubmitted = false;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;
            $scope.submitForm = submitForm;
            $scope.preventDefault = Common.preventDefault;
            $scope.verifyEmployee = verifyEmployee;
            $scope.verifyStorePass = verifyStorePass;
            $scope.verifyCCForStorePass = verifyCCForStorePass;
            $scope.verifyRegAccessCode = verifyRegAccessCode;
            $scope.cancelRegistration = cancelRegistration;
            $scope.showMarketingEmails = $scope.store.Functionality.MarketingEmails;
            $scope.showNewsletterEmails = $scope.store.Functionality.NewsletterEmails;
            $scope.acceptTermsAndCondition = acceptTermsAndCondition;
            $scope.confirmCountry = confirmCountry;
            $scope.showRegitration = false;
            $scope.showTerms = false;
            $scope.showConfirmCountry = false;

            $scope.storePassCredentials = {};
            $scope.employeeCredentials = {};
            $scope.accessCodeCredentials = {};
            $scope.accessCodeCredentials.failedAttempts = 0;

            $scope.years = Common.getYears();
            $scope.months = Common.getMonths();
            $scope.toggleHelp = Common.toggleHelp;
            $scope.testNameValidity = AddressService.testNameValidity;
        }]);



/*


Create a new MVC View for the Register New User page.
 
User should enter:
 
Contact Info (Name, Email, Phone, Fax)
Billing Address (Addr1, Addr2, City, Country, State, Postal Code, County/Jurisdiction)
UserLogin Info (username, password 2x, password reminder, notification prefs)
 
Use the same UI from the Checkout - Register page
 
Logic.
 
- done - Country should default to US and the US states are loaded by default. 
- done - If Store is not US only, then the Country can be a drop down and the States are refreshed when the country is selected
- done - By default the County/Jurisdiction dropdown is not visible. After the user enters both the City and PostalCode and country is US, get the TaxJurisdictions for the City and Postal Code via the API. If more than 1 jurisdiction is returned, show the County/Jurisdiction drop down

- not done - do not implement (per andy) - After the username is entered, should validate the username is available for the store code - do not implement. (per andy)

- done - Password must be entered twice and match.
- Show Notification Preferences for MarketingEmail and NewsletterEmails if enabled for store. If yes, these preferences should default to checked/true.
 
- Create a new Customer with the information provided via the API.
- If Customer is successfully created, login the new customer via Identity Server



*/;angular
    .module('ecs.ctrl.review', [])
    .controller('reviewCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        'CheckoutService',
        'Customers',
        'Common',
        '$log',
        'Stores',
        'ChiliService',
        'PetVetService',
        '$uibModal',
        function ($rootScope, $scope, $location, CheckoutService, Customers, Common, $log, Stores, ChiliService, PetVetService, $uibModal) {

            var customerNotificationSettings = [];
            var customerId;
            $scope.CheckoutService = CheckoutService;

            var setCartCheckout = async function () {

                if (CheckoutService.cartCheckout) {
                    var cartCheckout = $scope.cartCheckout = CheckoutService.cartCheckout;
                    //CCIE-246 to make a mandatory acknowledgement checkbox for MIC, MEC, MSE if there is an AOC or MS DC Products (MS28T or MS29T)
                    if (cartCheckout.Items.length > 0 && (cartCheckout.StoreCode === 'MSE' || cartCheckout.StoreCode === 'MIC' || cartCheckout.StoreCode === 'MEC')) {
                        $scope.isNonCancelable = cartCheckout.Items.some(function (v) {
                            return (Common.isMsDcProduct(v.ProductNumber));
                        });
                    }
                    if (!$rootScope.store.Functionality.Points && !(cartCheckout.PaymentMethod && cartCheckout.PaymentMethod.IsTerms) && !CheckoutService.paymentCardToUse && cartCheckout.GiftCertificateAmount < cartCheckout.TotalAmount) {
                        Common.showMessage('danger', '617');
                        goToBilling();
                    }

                    $scope.selectedPaymentMethod.paymentConfig = JSON.parse(cartCheckout.PaymentMethod.CaptureConfig);

                    if (!!$scope.selectedPaymentMethod.paymentConfig && !!$scope.selectedPaymentMethod.paymentConfig.OrgValueStringFormat) {


                        $scope.cartCheckout.OrganizationInfo.orgValueString = formatOrgValue($scope.cartCheckout.OrganizationInfo, $scope.selectedPaymentMethod.paymentConfig.OrgValueStringFormat)

                    }
                    if (Array.isArray(CheckoutService.paymentMethodApproverGroups) && !!cartCheckout.ChosenApproverGroupId) {
                        var approverGroup = CheckoutService.paymentMethodApproverGroups.find(function (value) {
                            return value.Id == cartCheckout.ChosenApproverGroupId;
                        })
                        if (!!approverGroup) {
                            $scope.cartCheckout.ChosenApproverGroupName = approverGroup.GroupName;
                        }
                    }
                    if (cartCheckout.HasOnDemandItems) {
                        CheckoutService.cartCheckout.ShipItemsTogether = false;
                    }
                } else {
                    await CheckoutService.getCheckoutCart();
                }

                if (!!$scope.cartCheckout && !!$scope.cartCheckout.CapturePurchaseReason) {
                    var storeCode = $rootScope.store.StoreCode;
                    Stores.getPurchaseReasonCodes(storeCode)
                        .then(function (response) {
                            $scope.purchaseReasons = response.data;
                        });
                }

                if (!!$scope.cartCheckout && !!$scope.cartCheckout.ShippingAddress && $scope.cartCheckout.ShippingAddress.Country == 'FR') {
                    CheckoutService.getCopyrightLevyFeeByCart();
                }
                if ($scope.CheckoutService.cartCheckout.Items) {
                    $scope.CheckoutService.cartCheckout.HasSellAndDisplayPriceProducts = $scope.CheckoutService.cartCheckout.Items.some(i => i.DisplayPrice != null);
                }
                
            },

                getRenderPDF = function (guid) {
                    ChiliService.getRenderPDF(guid);
                },

                getAdditionalInfo = function (infoItem) {
                    var info = infoItem.toLowerCase(),
                        isSoftware = info.substr(0, 4) === 'type',
                        isDigital = info.indexOf('digital') !== -1,
                        softwareMessage = isDigital ? 'Type: Digital Download - Product key(s) will be sent via e-mail.' : 'Type: Physical Box - This item will be shipped.';

                    return isSoftware ? softwareMessage : infoItem;
                },

                toggleAddGiftMessage = function ($event) {
                    if ($event) {
                        $event.preventDefault();
                    }

                    $scope.cartCheckout.GiftMessage = '';
                    $scope.showAddGiftMessage = !$scope.showAddGiftMessage;
                },

                showPromoCodeView = function ($event) {

                    if ($event) {
                        $event.preventDefault();
                    }

                    $scope.showPromoCode = !$scope.showPromoCode;

                },

                applyPromoCode = function () {

                    var code = $scope.promoCodeToApply;

                    if (code && code !== '') {
                        $log.log('Applying Promo Code to CheckOut Cart' + code);

                        CheckoutService.applyPromoCodeOnCheckout(code)
                            .then(setCartCheckout);

                        $scope.promoCodeToApply = "";
                    }
                    else {
                        Common.showMessage('danger', '407');
                    }


                },

                removePromoCode = function ($event, data) {
                    if ($event) {
                        $event.preventDefault();
                    }
                    CheckoutService.removePromoCodeOnCheckout(data)
                        .then(setCartCheckout);
                },

                placeOrder = function () {
                    checkRequiredFields();
                    if ((!$scope.isNonCancelable || ($scope.isNonCancelable && $scope.cancellationAck.noCancellationAcknowledged)) && $scope.requiredFieldCheck) {
                        $scope.submitted = true;

                        //CheckoutService.cartCheckout.PriceConditionCode = '0001';
                        CheckoutService.cartCheckout.DefaultBillingInfo = $scope.cartCheckout.DefaultBillingInfo;
                        CheckoutService.cartCheckout.DefaultShippingInfo = $scope.cartCheckout.DefaultShippingInfo;
                        CheckoutService.cartCheckout.GiftMessage = $scope.cartCheckout.GiftMessage;
                        CheckoutService.cartCheckout.UserCulture = $scope.user.DefaultCulture;
                        CheckoutService.cartCheckout.UserIP = $scope.user.UserIPAddress;
                        angular.forEach($scope.cartCheckout.Items, function (item, index) {
                            CheckoutService.cartCheckout.Items[index].PurchaseReason = item.PurchaseReason;
                        });

                        if ($rootScope.store.StoreCode === 'PVT') {
                            var customFieldInfo = PetVetService.getCustomField();
                            CheckoutService.cartCheckout.AdditionalInfo = JSON.stringify(customFieldInfo);
                        } else {
                            if ($scope.user.UserName) {
                                // CCIE-573
                                // Pass the email address to additional info in cartCheckOut object to check if the account is inactive
                                CheckoutService.cartCheckout.AdditionalInfo = `{'UserName':'${$scope.user.UserName}'}`;
                            }
                        }

                        $scope.$scrollTop(0);

                        //make sure we set any other values that can change on the review page in the Checkout Service Cart
                        CheckoutService.placeOrder('100')
                            .then(function (response) {
                                CheckoutService.paymentCardToUse = undefined;
                                $scope.OrderNumber = response.data.OrderNumber;
                                $scope.OrderDate = response.data.OrderDate;
                                CheckoutService.lastOrderConfirmation = response.data;
                                $rootScope.$broadcast('onOrderCreate');
                                $location.path('/checkout/complete/' + Common.getCurrentCheckoutUTSID());
                            }, function (response) {
                                //if (response.data && response.data.errorCode === '420') {
                                //    goToBilling(null, true);
                                //}

                                if (response != null) {
                                    let data = response.data;
                                    if (data != null && data.additionalInfo != null && checkShippingOptionError(data.additionalInfo)) {
                                        $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                                    }
                                }
                            });
                    }


                },

                requestApproval = function () {
                    checkRequiredFields();
                    if ((!$scope.isNonCancelable || ($scope.isNonCancelable && $scope.cancellationAck.noCancellationAcknowledged)) && $scope.requiredFieldCheck) {
                        //make sure we set any other values that can change on the review page in the Checkout Service Cart

                        if ($rootScope.store.StoreCode === 'PVT') {
                            var customFieldInfo = PetVetService.getCustomField();
                            CheckoutService.cartCheckout.AdditionalInfo = JSON.stringify(customFieldInfo);
                        }

                        $scope.$scrollTop();
                        CheckoutService.requestCartApproval('110')
                            .then(function (response) {
                                CheckoutService.paymentCardToUse = undefined;
                                $scope.OrderNumber = response.data.OrderNumber;
                                $scope.OrderDate = response.data.OrderDate;
                                CheckoutService.lastOrderConfirmation = response.data;
                                $scope.OrderNumber = 'pending';
                                $rootScope.$broadcast('onOrderCreate');
                                $location.path('/checkout/complete/' + Common.getCurrentCheckoutUTSID());
                            })
                            .catch(function(error) {
                                if (error != null) {
                                    let data = error.data;
                                    if (data != null && data.additionalInfo != null && checkShippingOptionError(data.additionalInfo)) {
                                        $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                                    }
                                }
                            });

                    }
                },

                checkShippingOptionError = function (msg) {
                    return msg.toUpperCase().indexOf("SHIPPING OPTION VALUE IS INCORRECT") !== -1;
                },

                getPaymentCard = function () {
                    if (CheckoutService.paymentCardToUse) {
                        data = CheckoutService.paymentCardToUse;
                        data.Last4 = data.CardNumber.substr(-4);
                        return data;
                    }
                    else {
                        //If we don't have it, just set it to some empty data
                        return {

                            CustomerId: $scope.user.CustomerId,
                            CardType: "",
                            CardNumber: "",
                            Last4: "",
                            ExpirationMonth: "",
                            ExpirationYear: "",
                            Name: "",
                            CVV: "",
                            IsDefault: false
                        };
                    }
                },

                goToShipping = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    //$scope.$scrollTop();
                    $location.path('/checkout/shipping/' + Common.getCurrentCheckoutUTSID());
                },

                goToBilling = function ($event, holdMessage) {
                    var qs = holdMessage ? { update: 'billing' } : {};
                    if ($event)
                        $event.preventDefault();

                    //$scope.$scrollTop();
                    $location.path('/checkout/billing/' + Common.getCurrentCheckoutUTSID()).search(qs);
                },

                getAppliedCopyrightLevyFee = function (copyrightLevyFee, totalAmount, baseCurrency, currencyExchangeRates) {

                    if (!angular.isDefined(copyrightLevyFee)) return false;

                    var locale = $scope.locale,
                        clAmount = Number(locale.exchangeRate(copyrightLevyFee, baseCurrency, currencyExchangeRates)),
                        totAmount = Number(locale.exchangeRate(totalAmount, baseCurrency, currencyExchangeRates));

                    if (clAmount > totAmount) {
                        clAmount = totAmount;
                    }

                    return locale.formatCurrency(clAmount, baseCurrency, currencyExchangeRates);

                },

                getAppliedGiftCertificateAmount = function (giftCertificateAmount, totalAmount, baseCurrency, currencyExchangeRates) {

                    if (!angular.isDefined(giftCertificateAmount)) return false;

                    var locale = $scope.locale,
                        gcAmount = Number(locale.exchangeRate(giftCertificateAmount, baseCurrency, currencyExchangeRates)),
                        totAmount = Number(locale.exchangeRate(totalAmount, baseCurrency, currencyExchangeRates));

                    if (gcAmount > totAmount) {
                        gcAmount = totAmount;
                    }

                    return locale.formatCurrency((gcAmount * -1), baseCurrency, currencyExchangeRates);

                },

                cfForm,

                registerItem = function (form) {
                    cfForm = form;
                },

                initReview = function () {

                    $scope.$scrollTop();

                    setCartCheckout();

                    $scope.$watch(
                        function () { return CheckoutService.cartCheckout; },

                        function (newValue, oldValue) {
                            //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                            if (newValue && !$scope.cartCheckout) {
                                setCartCheckout();
                            }
                        },

                        true // indicates object equaility comparison
                    );

                },

                formatOrgValue = function (organizationInfo, orgValueStringFormat) {
                    var s = orgValueStringFormat;
                    var arguments = [organizationInfo.CostCenter, organizationInfo.Division, organizationInfo.BudgetCode, organizationInfo.BusinessUnit, organizationInfo.ReasonCode];
                    for (var i = 0; i < arguments.length; i++) {
                        var reg = new RegExp("\\{" + i + "\\}", "gm");
                        s = s.replace(reg, arguments[i]);
                    }

                    return s;
                },

                applyReasonForAllItems = function (purchaseReason) {
                    var count = 0;
                    angular.forEach($scope.cartCheckout.Items, function (item) {
                        if (item.PurchaseReason) {
                            count++;
                        }
                    });
                    if ($scope.cartCheckout.Items.length == 1) {
                        $scope.purchaseReasonComplete = true;
                        return;
                    }
                    else if ($scope.cartCheckout.Items.length > 1 && count > 1) {
                        return;
                    }
                    else {
                        var modalInstance = $uibModal.open({
                            templateUrl: 'PurchaseReason.html',
                            controller: 'showPurchaseReasonCtrl',
                            size: 'lg',
                            resolve: {
                                purchaseReason: function () {
                                    return purchaseReason
                                },
                                items: function () {
                                    return $scope.cartCheckout.Items;
                                }

                            }

                        });

                        modalInstance.result.then(function () {
                            $scope.purchaseReasonComplete = true;
                        }, function () {
                            $log.info('Modal dismissed at: ' + new Date());
                        });
                    }
                },

                checkRequiredFields = function () {
                    if ($rootScope.store.StoreCode === 'PVT') {
                        $scope.requiredFieldCheck = PetVetService.hasCompleteData();
                    }
                    else {
                        $scope.requiredFieldCheck = true;
                    }
                }


            $scope.selectedPaymentMethod = {};
            $scope.purchaseReasons = [];
            $scope.purchaseReasonComplete = false;


            initReview();

            $scope.requiredFieldCheck = true;
            $scope.getAdditionalInfo = getAdditionalInfo;
            $scope.toggleHelp = Common.toggleHelp;
            $scope.placeOrder = placeOrder;
            $scope.requestApproval = requestApproval;
            $scope.promoCodeToApply = "";
            $scope.showPromoCodeView = showPromoCodeView;
            $scope.applyPromoCode = applyPromoCode;
            $scope.removePromoCode = removePromoCode;
            $scope.toggleAddGiftMessage = toggleAddGiftMessage;
            $scope.paymentCardUsed = getPaymentCard();
            $scope.goToBilling = goToBilling;
            $scope.goToShipping = goToShipping;
            $scope.getAppliedGiftCertificateAmount = getAppliedGiftCertificateAmount;
            $scope.getAppliedCopyrightLevyFee = getAppliedCopyrightLevyFee;
            $scope.getGrandTotal = Common.getGrandTotal;
            $scope.registerItem = registerItem;
            $scope.applyReasonForAllItems = applyReasonForAllItems;
            $scope.getRenderPDF = getRenderPDF;

            $scope.cancellationAck = { noCancellationAcknowledged: false };

        }])

    .controller('showPurchaseReasonCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'purchaseReason',
        'items',
        function ($scope, Common, $uibModalInstance, purchaseReason, items) {

            $scope.purchaseReason = purchaseReason;

            $scope.yes = function () {
                angular.forEach(items, function (item) {
                    if (item.PurchaseReason == null || item.PurchaseReason == '') {
                        item.PurchaseReason = purchaseReason;
                    }
                });

                $uibModalInstance.close();
            }

            $scope.no = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);;angular
    .module('ecs.ctrl.complete', [])
    .controller('completeCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        'CheckoutService',
        'Customers',
        'Common',
        '$log',
        function ($rootScope, $scope, $location, CheckoutService, Customers, Common, $log) {

            var initCheckoutComplete = function () {

                $scope.$scrollTop();
                if (!!CheckoutService.lastOrderConfirmation) {
                    $scope.OrderNumber = CheckoutService.lastOrderConfirmation.OrderNumber;
                    $scope.relatedProducts = CheckoutService.lastOrderConfirmation.RelatedProducts;
                    $scope.approverEmail = CheckoutService.lastOrderConfirmation.ApproverEmail;
                    loadCustomerNotificationSettings();
                }
                else {
                    Common.goHome();
                }
            },

            loadCustomerNotificationSettings = function () {
                customerId = $scope.user.CustomerId;
                Customers.getNotificationPreferences(customerId)
                    .then(function (response) {
                        customerNotificationSettings = response.data;
                        var emailIndex = getEmailIndex(customerNotificationSettings);

                        $scope.emailPref = (emailIndex > -1) ? customerNotificationSettings[emailIndex] : null;
                    });
            },

            getEmailIndex = function (notificationSettings) {

                var index = -1;

                for (var i = 0, len = notificationSettings.length; i < len; i += 1) {
                    if (notificationSettings[i].Type === 'Emails') {
                        index = i;
                    }
                }

                return index;
            },

            setNotificationSetting = function (enabled) {
                if (!!$scope.emailPref) {
                    if (enabled) {
                        $scope.emailPref.Enabled = true;
                        Customers.updateNotificationPreferences(customerId, $scope.emailPref);
                        Common.showMessage('success', '628');
                    }
                    else {
                        $scope.emailPref = null;
                    }

                }

            };

            $scope.emailPref = null;
            
            $scope.setNotificationSetting = setNotificationSetting;

            initCheckoutComplete();

        }]);;
angular
    .module('ecs.ctrl.terms', [])
    .controller('termsCtrl', [
        '$scope',
        'Common',
        'CheckoutService',
        '$location',
        function ($scope, Common, CheckoutService, $location) {

            var setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {
                    $scope.cartCheckout = CheckoutService.cartCheckout;
                    $scope.purchaseAgreement = $scope.cartCheckout.TermsAndConditions;

                } else {
                    CheckoutService.getCheckoutCart();

                }

            },

            disableWatcher = undefined,

            enableWatcher = function () {

                disableWatcher = $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        if (newValue !== oldValue) {

                            setCartCheckout();
                        }
                    },

                    true // indicates object equaility comparison
                );
            },

            updateCheckoutCart = function () {
                return CheckoutService.updateCheckoutCart();
            },

            initTerms = function () {

                $scope.$scrollTop();
                enableWatcher();
                setCartCheckout();

            },

            goToReview = function () {

                if ($scope.acceptAgreement) {

                    CheckoutService.cartCheckout.TermsAccepted = true;

                    CheckoutService.updateCheckoutCart()
                    .then(function () {
                        $scope.$scrollTop();
                        disableWatcher();
                        $location.path('/checkout/review/' + Common.getCurrentCheckoutUTSID());
                    });
                   
                }
            },

            updateAgreementStatus = function () {
                CheckoutService.cartCheckout.TermsAccepted = acceptAgreement; 

            };

            initTerms();
            
            $scope.acceptAgreement = false;
            $scope.continueCheckout = goToReview;
            $scope.continueDisabled = true;
            $scope.updateAgreementStatus = updateAgreementStatus;

        }]);
;angular
    .module('ecs.ctrl.validation', [])
    .controller('validationCtrl', [
        '$log',
        '$scope',
        '$location',
        'Constants',
        'Objects',
        'Common',
        '$timeout',
        'ShoppingCarts',
        'Customers',
        'AddressService',
        'CheckoutService',
        function ($log, $scope, $location, Constants, Objects, Common, $timeout, ShoppingCarts, Customers, AddressService, CheckoutService) {
            var setCartCheckout = function () {

                if (CheckoutService.cartCheckout) {

                    var cartCheckout = CheckoutService.cartCheckout,
                        cartEmpty = cartCheckout.Items.length === 0;

                    $scope.cartCheckout = cartCheckout;

                    if (cartCheckout.ValidationErrors && cartCheckout.ValidationErrors.length > 0) {
                        $scope.cartCheckout = undefined;
                        $scope.errorArray = CheckoutService.errorArray;
                        $scope.getMessage = function (code) {
                            var altMsg = 'We are sorry but this item is unavailable.',
                                msg = Constants.ERROR_MESSAGES["en-US"][code] || altMsg;

                            return msg;
                        };
                        $scope.renderValidation = true;
                    }
                    else if (cartEmpty) {
                        Common.linkTo('cart');
                    } else {
                        $goCheckout();
                    }

                } else {
                    $scope.cartCheckout = undefined;
                    CheckoutService.getCheckoutCart()
                }
            },

            initValidation = function () {

                setCartCheckout();

                $scope.$scrollTop();

                disableWatcher = $scope.$watch(
                    function () { return CheckoutService.cartCheckout; },

                    function (newValue, oldValue) {
                        //If cartCheckout value is valid and we have not set it in our scope yet, go set it
                        if (newValue && !$scope.cartCheckout) {
                            setCartCheckout();
                        }
                    },

                    true // indicates object equaility comparison
                );

            };

            $scope.renderValidation = false;
            initValidation();
        }]);;angular
    .module('ecs.ctrl.gc-recipients', [])
    .controller('gcRecipientsCtrl', [
        '$scope',
        '$http',
        '$window',
        '$timeout',
        'Common',
        'GCCheckoutService',
        '$location',
        function ($scope, $http, $window, $timeout, Common, GCCheckoutService, $location) {

            var self = this;

            var IsValid = function (name, email) {
                if (!name && !email)
                    return true;

                if (!!name && !!email)
                    return true;

                return false;
            };

            var goToBilling = function ($event) {
                if ($event)
                    $event.preventDefault();

                $timeout(function () {
                    $location.path('/gccheckout/billing/' + Common.getCurrentCheckoutUTSID());
                }, 100);

            };

            var gcCheckout = function () {
                var recipientsToAdd = [];
                var hasError = false;

                $scope.submitted = true;

                if ($scope["gcRecipientsForm"].$invalid) {
                    Common.showMessage('danger', '615');
                }
                else {
                    angular.forEach($scope.recipientsList, function (r) {
                        if (!IsValid(r.RecipientName, r.RecipientEmail)) {
                            Common.showMessage('danger', '615');
                            hasError = true;
                        }

                        else if (!!r.RecipientName && !!r.RecipientEmail) {
                            r.EditedRecipientName = r.RecipientName;
                            r.EditedRecipientEmail = r.RecipientEmail;
                            recipientsToAdd.push(r);
                        }
                    });

                    if (recipientsToAdd.length == 0 && !hasError) {
                        Common.showMessage('danger', '627');
                        hasError = true;
                    }

                    if (!hasError) {
                        var data = {
                            Amount: $scope.giftCertificate.Amount,
                            Name: $scope.giftCertificate.Name,
                            Email: $scope.giftCertificate.Email,
                            Recipients: recipientsToAdd,
                            Message: $scope.giftCertificate.Message
                        };

                        GCCheckoutService.setGCCheckoutInfo(data);
                        goToBilling();
                    }
                }
            };

            var addRecipients = function (numerOfRecipients) {
                for (i = 0; i < 5 - numerOfRecipients; i++) {
                    $scope.recipientsList.push({
                        RecipientName: '',
                        RecipientEmail: ''
                    });
                }
            };

            $scope.gcCheckout = gcCheckout;
            $scope.IsValid = IsValid;
            $scope.addRecipients = addRecipients;
            $scope.emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
            $scope.numberPattern = /^[1-9][0-9]*(\.[0-9]+)?|0+\.[0-9]*[1-9][0-9]*$/;

            (function () {
                $scope.giftCertificate = GCCheckoutService.gcCheckout || {};
                if (angular.equals($scope.giftCertificate, {})) {
                    $scope.giftCertificate = {
                        Amount: 25,
                        Name: $scope.user.Name,
                        Email: $scope.user.Email
                    };
                }
                $scope.recipientsList = $scope.giftCertificate.Recipients || [];

                addRecipients($scope.recipientsList.length);
            })();
        }]);


;angular
    .module('ecs.ctrl.gcBilling', [])
    .controller('gcBillingCtrl', [
        '$rootScope',
        '$scope',
        'Common',
        '$location',
        '$log',
        'GCCheckoutService',
        'Customers',
        'GiftCertificates',
        '$timeout',
        '$window',
        '$filter',
        '$sce',
        function ($rootScope, $scope, Common, $location, $log, GCCheckoutService, Customers, GiftCertificates, $timeout, $window, $filter, $sce) {

            var editBillingAddress = function ($event) {
                $event.preventDefault();

                var utsid = Common.getCurrentCheckoutUTSID();
                //$location.path('/checkout/billing/billing-address/' + Common.getCurrentCheckoutUTSID());
                $location.path('/MyAccount/UserInfo').search('md', 'gcbae').search('utsid', utsid);
            };

            var getBillingAddresses = function () {
                Customers.getCustomer($rootScope.user.CustomerId)
                .then(function (response) {
                    $scope.billingAddresses = response.data.BillingAddress;
                });
            };

            var goToRecipients = function ($event) {
                if ($event)
                    $event.preventDefault();

                $timeout(function () {
                    $location.path('/gccheckout/recipients/' + Common.getCurrentCheckoutUTSID());
                }, 100);

            };

            var editRecipient = function (recipient) {
                recipient.isInEditMode = !recipient.isInEditMode;
            };

            var saveRecipient = function (recipient) {
                recipient.isInEditMode = !recipient.isInEditMode;
                recipient.RecipientName = recipient.EditedRecipientName;
                recipient.RecipientEmail = recipient.EditedRecipientEmail;
            };

            var cancelRecipient = function (recipient) {
                recipient.isInEditMode = !recipient.isInEditMode;
                recipient.EditedRecipientName = recipient.RecipientName;
                recipient.EditedRecipientEmail = recipient.RecipientEmail;
            };

            var removeRecipient = function (recipient) {
                var index = $scope.gcInfo.Recipients.indexOf(recipient);
                $scope.gcInfo.Recipients.splice(index, 1);
            }

            var getEmptyCard = function () {
                var monthTmp = (new Date().getMonth() + 1).toString(),
                    month = (monthTmp > 9) ? month : '0' + monthTmp,
                    year = new Date().getFullYear().toString();

                return {
                    CustomerId: $scope.user.CustomerId,
                    CardType: null,
                    CardNumber: "",
                    ExpirationMonth: month,
                    ExpirationYear: year,
                    Name: "",
                    CVV: ""
                };
            };

            var checkCardExpDate = function () {
                var month = $scope.NewPaymentCard.ExpirationMonth,
                    year = $scope.NewPaymentCard.ExpirationYear,
                    expDate = new Date(year, month, 0),
                    dateValid = false;

                if (expDate.getTime() >= new Date().getTime()) {
                    dateValid = true;
                };

                return dateValid;
            };

            var getErrorMessage = function (errorObj) {
                var message = "*Please enter your credit card security code.";

                if (errorObj.minlength) {
                    message = "*CVV security code should be at least 3 digits.";
                }

                return message;
            };

            var useExistingCard = function (card) {
                $scope.NewPaymentCard = card;
                $scope.NewPaymentCard.Last4 = $scope.NewPaymentCard.CardNumber.substr(-4);
                $scope.showNewCardPortlet = false;
                $scope.showSelectedCreditCard = true;
                $scope.isReadyForCheckout = true;
            };

            var useDiffCard = function ($event) {
                if ($event)
                    $event.preventDefault();
                if ($scope.paymentCards.length === 0) {
                    $scope.showNewCardPortlet = true;
                } else {
                    $scope.showSelectedCreditCard = false;
                }
                $scope.isReadyForCheckout = false;
            };

            var addNewCard = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }
                $scope.NewPaymentCard = getEmptyCard();
                $scope.showNewCardPortlet = true;
                $scope.isReadyForCheckout = true;
            };

            var submitGCBilling = function (submittedForm) {
                var ccNumber = $scope.NewPaymentCard.CardNumber;
                var ccType = $scope.NewPaymentCard.CardType;

                if ($scope.showNewCardPortlet) {
                    $scope.isValidCard = Common.validateCreditCard(ccNumber, ccType);
                    $scope.isValidCCExpDate = checkCardExpDate();
                }

                $scope.gcBillingFormSubmitted = true;

                if (submittedForm.$valid && $scope.isValidCard && $scope.isValidCCExpDate) {
                    var orderItems = [];

                    angular.forEach($scope.gcInfo.Recipients, function (recipient) {
                        var orderItem = {
                            Amount: $scope.gcInfo.Amount,
                            FromName: $scope.gcInfo.Name,
                            FromEmail: $scope.gcInfo.Email,
                            ToName: recipient.RecipientName,
                            ToEmail: recipient.RecipientEmail,
                            Message: $scope.gcInfo.Message
                        };

                        orderItems.push(orderItem);
                    });

                    var data = {
                        SoldToCustomerId: $scope.user.CustomerId,
                        OrderDate: $scope.convertToJsonDateString(new Date()),
                        PaymentCard: {
                            CVV: $scope.NewPaymentCard.CVV,
                            CardNumber: $scope.NewPaymentCard.CardNumber,
                            CardType: $scope.NewPaymentCard.CardType,
                            CustomerId: $scope.user.CustomerId,
                            ExpirationMonth: $scope.NewPaymentCard.ExpirationMonth,
                            ExpirationYear: $scope.NewPaymentCard.ExpirationYear,
                            IsDefault: false,
                            Last4: $scope.NewPaymentCard.CardNumber.substr(-4),
                            Name: $scope.NewPaymentCard.Name,
                            doNotSave: true
                        },
                        BillingAddress: $scope.billingAddresses,
                        PaymentMethod: {
                            PayMethod: "Credit Card",
                            PaymentMethodCode: "YP-0001"
                        },
                        OrderItems: orderItems                       
                    };

                    if ($scope.NewPaymentCard.SaveThisCard) {
                        $scope.gcBillingFormSubmitted = false;
                        Customers.addPaymentCard($scope.user.CustomerId, $scope.NewPaymentCard)
                            .then(function (response) {
                                Common.showMessage('success', '682');
                            });
                    }

                    $scope.gcBillingFormSubmitted = false;

                    GiftCertificates.createGiftCertificateOrder(data, '100').then(
                        function (success) {
                            $scope.returnOrderItems = success.data.OrderItems;
                            $scope.isBillingCompleted = true;
                            GCCheckoutService.gcCheckout = undefined;
                            $scope.$scrollTop(0);

                            angular.forEach($scope.returnOrderItems, function (item) {
                                if (item.GiftCertificateNumber == "Error")
                                    $scope.errorInOrderItem = true;
                                else
                                    $scope.errorInAllItems = false;
                            });
                        },
                        function (error) {
                            console.log(error);
                        });
                }
                else {
                    if (!$scope.isValidCard)
                        Common.showMessage('danger', '620');

                    else if (!$scope.isValidCCExpDate)
                        Common.showMessage('danger', '618');

                    else
                        Common.showMessage('danger', '638');
                }
            };
            var submitGCBillingWithPONumber = function (submitForm) {

                var self = this;
                submitForm.$submitted = true;

                if (submitForm.$valid) {
                    var orderItems = [];

                    angular.forEach($scope.gcInfo.Recipients, function (recipient) {
                        var orderItem = {
                            Amount: $scope.gcInfo.Amount,
                            FromName: $scope.gcInfo.Name,
                            FromEmail: $scope.gcInfo.Email,
                            ToName: recipient.RecipientName,
                            ToEmail: recipient.RecipientEmail,
                            Message: $scope.gcInfo.Message
                        };

                        orderItems.push(orderItem);
                    });

                    var data = {
                        SoldToCustomerId: $scope.user.CustomerId,
                        OrderDate: $scope.convertToJsonDateString(new Date()),
                        BillingAddress: $scope.billingAddresses,
                        PaymentMethod: {
                            PayMethod: $scope.selectedPaymentMethod.payMethod,
                            PaymentMethodCode: $scope.selectedPaymentMethod.code,
                            PayerCustomerId: $scope.selectedPaymentMethod.payerCustomerId
                        },
                        OrderItems: orderItems,
                        PONumber: $scope.gcPayment.PONumber,
                        OrganizationInfo: $scope.organizationInfo
                    };

                    createGCOrder(data);


                }
                else {
                    Common.showMessage('danger', '638');
                }
            };
            var submitGCBillingWithMultiPartPONumber = function (submitForm) {

                var self = this;
                submitForm.$submitted = true;

                if (submitForm.$valid) {
                    var orderItems = [];

                    angular.forEach($scope.gcInfo.Recipients, function (recipient) {
                        var orderItem = {
                            Amount: $scope.gcInfo.Amount,
                            FromName: $scope.gcInfo.Name,
                            FromEmail: $scope.gcInfo.Email,
                            ToName: recipient.RecipientName,
                            ToEmail: recipient.RecipientEmail,
                            Message: $scope.gcInfo.Message
                        };

                        orderItems.push(orderItem);
                    });

                    var poParts = [];
                    var numOfInputs = $scope.selectedPaymentMethod.paymentConfig.InputFields.length;
                    for (var i = 0; i < numOfInputs; i++) {
                        poParts[i] = $scope.gcPayment.multipPartPO[i];
                    }
                    //Set the PO number 
                    $scope.gcPayment.PONumber = poParts.join($scope.selectedPaymentMethod.paymentConfig.FieldSeparator);


                    var data = {
                        SoldToCustomerId: $scope.user.CustomerId,
                        OrderDate: $scope.convertToJsonDateString(new Date()),
                        BillingAddress: $scope.billingAddresses,
                        PaymentMethod: {
                            PayMethod: $scope.selectedPaymentMethod.payMethod,
                            PaymentMethodCode: $scope.selectedPaymentMethod.code,
                            PayerCustomerId: $scope.selectedPaymentMethod.payerCustomerId
                        },
                        OrderItems: orderItems,
                        PONumber: $scope.gcPayment.PONumber,
                        OrganizationInfo: $scope.organizationInfo
                    };

                    createGCOrder(data);


                }
                else {
                    Common.showMessage('danger', '638');
                }
            };

            var submitGCBillingWithOrgInfo = function (submitForm) {

                var self = this;
                submitForm.$submitted = true;

                if (submitForm.$valid) {
                    var orderItems = [];

                    angular.forEach($scope.gcInfo.Recipients, function (recipient) {
                        var orderItem = {
                            Amount: $scope.gcInfo.Amount,
                            FromName: $scope.gcInfo.Name,
                            FromEmail: $scope.gcInfo.Email,
                            ToName: recipient.RecipientName,
                            ToEmail: recipient.RecipientEmail,
                            Message: $scope.gcInfo.Message
                        };

                        orderItems.push(orderItem);
                    });                 


                    var data = {
                        SoldToCustomerId: $scope.user.CustomerId,
                        OrderDate: $scope.convertToJsonDateString(new Date()),
                        BillingAddress: $scope.billingAddresses,
                        PaymentMethod: {
                            PayMethod: $scope.selectedPaymentMethod.payMethod,
                            PaymentMethodCode: $scope.selectedPaymentMethod.code,
                            PayerCustomerId: $scope.selectedPaymentMethod.payerCustomerId
                        },
                        OrderItems: orderItems,
                       // PONumber: $scope.gcPayment.PONumber,
                        OrganizationInfo: $scope.organizationInfo
                    };

                    createGCOrder(data);


                }
                else {
                    Common.showMessage('danger', '638');
                }
            };

            var submitGCBillingWithFSHGPDollars = function (submitForm) {

                var self = this;
                submitForm.$submitted = true;

                if (submitForm.$valid) {
                    var orderItems = [];

                    angular.forEach($scope.gcInfo.Recipients, function (recipient) {
                        var orderItem = {
                            Amount: $scope.gcInfo.Amount,
                            FromName: $scope.gcInfo.Name,
                            FromEmail: $scope.gcInfo.Email,
                            ToName: recipient.RecipientName,
                            ToEmail: recipient.RecipientEmail,
                            Message: $scope.gcInfo.Message
                        };

                        orderItems.push(orderItem);
                    });

                    var poParts = [];
                    
                    for (var i = 0; i < 4; i++) {
                        poParts[i] = $scope.gcPayment.multipPartPO[i];
                    }
                    //Set the PO number 
                    $scope.gcPayment.PONumber = poParts.join('.');


                    var data = {
                        SoldToCustomerId: $scope.user.CustomerId,
                        OrderDate: $scope.convertToJsonDateString(new Date()),
                        BillingAddress: $scope.billingAddresses,
                        PaymentMethod: {
                            PayMethod: $scope.selectedPaymentMethod.payMethod,
                            PaymentMethodCode: $scope.selectedPaymentMethod.code,
                            PayerCustomerId: $scope.selectedPaymentMethod.payerCustomerId
                        },
                        OrderItems: orderItems,
                        PONumber: $scope.gcPayment.PONumber,
                        OrganizationInfo: $scope.organizationInfo
                    };

                    createGCOrder(data);


                }
                else {
                    Common.showMessage('danger', '638');
                }
            };

            var createGCOrder = function (data) {

                GiftCertificates.createGiftCertificateOrder(data, '100').then(
                    function (success) {
                        $scope.returnOrderItems = success.data.OrderItems;
                        $scope.isBillingCompleted = true;
                        GCCheckoutService.gcCheckout = undefined;
                        $scope.$scrollTop(0);

                        angular.forEach($scope.returnOrderItems, function (item) {
                            if (item.GiftCertificateNumber == "Error")
                                $scope.errorInOrderItem = true;
                            else
                                $scope.errorInAllItems = false;
                        });
                    },
                    function (error) {
                        console.log(error);
                    });
            };
            var initBilling = function () {
                $scope.gcInfo = GCCheckoutService.gcCheckout;
                $scope.NewPaymentCard = getEmptyCard();
                $scope.billingAddresses = null;
                $scope.isReadyForCheckout = false;
                $scope.isValidCard = true;
                $scope.isValidCCExpDate = true;
                $scope.showCVVImage = false;
                $scope.paymentCards = [];
                $scope.isBillingCompleted = false;
                $scope.errorInOrderItem = false;
                $scope.errorInAllItems = true;
                $scope.selectedPaymentMethod = [];
                $scope.organizationInfo = null;  
                $scope.gcPayment = {};
                $scope.gcPayment.multipPartPO = [];

                if (!$scope.gcInfo)
                    $scope.$gcCheckout();

               // getBillingAddresses();
                $scope.months = Common.getMonths();
                $scope.years = Common.getYears();

                Customers.getPaymentCards($scope.user.CustomerId)
                    .then(function (res) {
                        $scope.paymentCards = res.data;
                        if ($scope.paymentCards.length === 0) {
                            $scope.showNewCardPortlet = true;
                            $scope.isReadyForCheckout = true;
                        }
                    });
                $scope.paymentMethods = getAvailablePaymentMethods($filter('orderBy')($scope.store.PaymentMethods,'DisplayOrder'));
                if ($scope.paymentMethods.length > 0) {
                    $scope.selectedPaymentMethod.code = $scope.paymentMethods[0].PaymentMethodCode //default to first Item in the list
                    $scope.selectedPaymentMethod.paymentConfig = JSON.parse($scope.paymentMethods[0].CaptureConfig); //default to first Item in the list                  
                    $scope.selectedPaymentMethod.payMethod = $scope.paymentMethods[0].PayMethod;
                    $scope.selectedPaymentMethod.payerCustomerId = $scope.paymentMethods[0].PayerCustomerId;                   

                    if (!!$scope.selectedPaymentMethod.paymentConfig.AlertMessage && !!$scope.selectedPaymentMethod.paymentConfig.AlertMessage)
                        $scope.selectedPaymentMethod.paymentConfig.AlertMessage = $sce.trustAsHtml($scope.selectedPaymentMethod.paymentConfig.AlertMessage);

                    getGiftCertificatePaymentMethodDetails($scope.selectedPaymentMethod.payerCustomerId, $scope.selectedPaymentMethod.code)

                    $scope.selectedPaymentMethod.canEditBilling = !$scope.selectedPaymentMethod.payerCustomerId && $scope.selectedPaymentMethod.code !== "DE-NT30"; 
                } 

               

                $scope.$scrollTop();
            };

            var getAvailablePaymentMethods = function (storePaymentMethods) {
                var availableMethods = [];
                angular.forEach(storePaymentMethods, function (method) {
                    if (method.CanPurchaseGiftCertificate && !method.RequiresApproval)
                        availableMethods.push(method);
                });

                return availableMethods;
            };

            var isValid = function (recipient) {
                if (recipient.EditedRecipientName && recipient.EditedRecipientEmail && $scope.emailPattern.test(recipient.EditedRecipientEmail))
                    return true;
                else
                    return false;
            };

               
            var setCardToken = function (token, cardType) {

                if (!!token && token !== '') {
                    $scope.NewPaymentCard.CardNumber = token;
                    $scope.NewPaymentCard.CardType = setCardTypeFromBrand(cardType) || setCardTypeFromToken(token);
                }
                else {
                    $scope.NewPaymentCard.CardNumber == null;
                    $scope.NewPaymentCard.CardType == null;
                }
                $scope.$apply();
            };

            var setCardTypeFromToken = function (token) {
                if (!!token && token !== '') {
                    var ccFirstDigit = token.substring(1, 2);
                    if (ccFirstDigit == '4')
                        return "VISA"
                    else if (ccFirstDigit == '5' || ccFirstDigit == '2')
                        return "MC"
                    else if (ccFirstDigit == '6')
                        return "DISC"
                    else if (ccFirstDigit == '3')
                        return "AMEX"
                    else
                        return null;
                }
                else {
                    return null;
                }
            };

            var setCardTypeFromBrand = function (name) {
                if (!name)
                    return null;
                else {
                    var upper = name.toUpperCase();
                    switch (upper) {
                        case "VISA":
                            return "VISA";
                        case "MC":
                        case "MASTERCARD":
                            return "MC";
                        case "DISC":
                        case "DISCOVER":
                            return "DISC";
                        case "AMEX":
                            return "AMEX";
                        default:
                            return null;
                    }
                }
            };

            var setCCHandler = function () {
                $window.addEventListener('message', function (e) {
                    Common.parseCreditCardTokenMessage(e, (token, cardType) => {
                        setCardToken(token, cardType);
                    });
                });
            };

            var updatePaymentMethod = function (method) {
                // Common.showLoader('124');
                $scope.selectedPaymentMethod.paymentConfig = JSON.parse(method.CaptureConfig);
                $scope.selectedPaymentMethod.payMethod = method.PayMethod;
                $scope.selectedPaymentMethod.payerCustomerId = method.PayerCustomerId;
                $scope.selectedPaymentMethod.code = method.PaymentMethodCode
                getGiftCertificatePaymentMethodDetails(method.PayerCustomerId, method.PaymentMethodCode)
                $scope.selectedPaymentMethod.canEditBilling = !$scope.selectedPaymentMethod.payerCustomerId && $scope.selectedPaymentMethod.code !== "DE-NT30"; 
            };

            var getGiftCertificatePaymentMethodDetails = function (payerCustomerId, paymentMethodCode) {
                GiftCertificates.getGiftCertificatePaymentMethodDetails(payerCustomerId, paymentMethodCode)
                    .then(function (response) {
                        $scope.billingAddresses = response.data.BillingAddress;
                        $scope.organizationInfo = response.data.OrganizationInfo;
                    });
            };

            setCCHandler();

            $scope.editBillingAddress = editBillingAddress;
            $scope.goToRecipients = goToRecipients;
            $scope.editRecipient = editRecipient;
            $scope.saveRecipient = saveRecipient;
            $scope.cancelRecipient = cancelRecipient;
            $scope.removeRecipient = removeRecipient;
            $scope.submitGCBilling = submitGCBilling;
            $scope.getErrorMessage = getErrorMessage;
            $scope.emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
            $scope.isValid = isValid;
            $scope.useExistingCard = useExistingCard;
            $scope.useDiffCard = useDiffCard;
            $scope.addNewCard = addNewCard;
            $scope.updatePaymentMethod = updatePaymentMethod;  
            $scope.submitGCBillingWithPONumber = submitGCBillingWithPONumber;
            $scope.submitGCBillingWithMultiPartPONumber = submitGCBillingWithMultiPartPONumber;
            $scope.submitGCBillingWithOrgInfo = submitGCBillingWithOrgInfo;
            $scope.submitGCBillingWithFSHGPDollars = submitGCBillingWithFSHGPDollars;
            initBilling();
        }]);;angular
    .module('ecs.ctrl.petvetcustomfield', [])
    .controller('petVetCustomFieldCtrl', [
        '$rootScope',
        '$scope',
        'PetVetService',
        '$uibModal',
        function ($rootScope, $scope, PetVetService, $uibModal) {

            var clinicSearchCache = null;
            $scope.PetVetService = PetVetService;

            openStartDatePicker = function ($event, elementOpened) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.startDateModel[elementOpened] = !$scope.startDateModel[elementOpened];
            };

            clearStartDatePicker = function ($event) {
                $event.preventDefault();
                $scope.programStartDate = null;
            };

            openEndDatePicker = function ($event, elementOpened) {
                $event.preventDefault();
                $event.stopPropagation();
                $scope.endDateModel[elementOpened] = !$scope.endDateModel[elementOpened];
            };

            clearEndDatePicker = function ($event) {
                $event.preventDefault();
                $scope.programEndDate = null;
            };

            onChangeEndDatePicker = function () {
                if ($scope.programEndDate) {
                    if ($scope.programStartDate != null && $scope.programStartDate > $scope.programEndDate) {
                        $scope.programEndDate = $scope.programStartDate;
                    }
                }
                $scope.programMaxStartDate = $scope.programEndDate;
                tryResolveErrors();
            };

            onChangeStartDatePicker = function () {
                if ($scope.programStartDate) {
                    if ($scope.programEndDate != null && $scope.programStartDate > $scope.programEndDate) {
                        $scope.programStartDate = $scope.programEndDate;
                    }
                }
                $scope.programMinEndDate = $scope.programStartDate;
                tryResolveErrors();
            };

            populateFields = function (data) {
                var optionArray;
                for (var i = 0; i < data.length; i++) {
                    switch (data[i].Category.toUpperCase()) {
                        case "OBJECTIVE":
                            optionArray = $scope.objectiveOptions;
                            break;
                        case "ACTIVITY":
                            optionArray = $scope.activityOptions;
                            break;
                        case "MEASUREMENT":
                            optionArray = $scope.measurementOptions;
                            break;
                        case "DISTRICT":
                            optionArray = $scope.districtOptions;
                            break;
                    }

                    optionArray.push({ Value: optionArray.length, Label: data[i].Value, Obj: data[i]});
                }
            };

            getLookupFieldInfo = function () {
                PetVetService.getActiveLookups()
                    .then(function (response) {
                        populateFields(response.data);
                    });
            };

            showClinicModal = function () {

                $scope.modalInstance = $uibModal.open({
                    templateUrl: 'ClincSearch.html',
                    controller: 'ClinicModalCtrl',
                    size: 'lg',
                    resolve: {
                        data: function () {
                            return { selectedClinic: $scope.selectedClinic, clinicData: clinicSearchCache };
                        }
                    }

                });

                $scope.modalInstance.result.then(function (result) {
                    //Modal is closed with a success result then this function runs.
                    clinicSearchCache = result.clinicData;
                    setSelectedClinic(result.selectedClinic);
                });

            };

            onClinicInputClick = function () {
                showClinicModal();
            };

            setClinicDisplay = function () {
                if ($scope.selectedClinic == null) {
                    $scope.selectedClinicDisplay = "";
                }
                else {
                    $scope.selectedClinicDisplay = $scope.selectedClinic.LocationNumber + " - " + $scope.selectedClinic.SiteName;
                }
            };

            onClinicInputTextChange = function() {
                setClinicDisplay();
            };

            fetchPVData = function () {
                checkErrors();
                var pvData = {};
                pvData.selectedActivity = $scope.activityOptions[$scope.selectedActivity];
                pvData.selectedObjective = $scope.objectiveOptions[$scope.selectedObjective];
                pvData.selectedMeasurement = $scope.measurementOptions[$scope.selectedMeasurement];
                pvData.selectedDistrict = $scope.districtOptions[$scope.selectedDistrict];
                pvData.programStartDate = $scope.programStartDate;
                pvData.programEndDate = $scope.programEndDate;
                pvData.selectedClinic = $scope.selectedClinic;
                pvData.errors = $scope.errors;
                PetVetService.setPVData(pvData);
            };

            setSelectedClinic = function (clinic) {
                $scope.selectedClinic = clinic;
                setClinicDisplay();
                tryResolveErrors();
            };

            onDropdownChange = function () {
                tryResolveErrors();
            };

            tryResolveErrors = function () {
                //If an error message is displaying, then check if it has been solved.
                if ($scope.errors.district !== ""
                    || $scope.errors.measurement !== ""
                    || $scope.errors.activity !== ""
                    || $scope.errors.objective !== ""
                    || $scope.errors.clinic !== "") {
                    checkErrors();
                }
            };

            checkErrors = function () {
                $scope.errors.district = "";
                $scope.errors.measurement = "";
                $scope.errors.activity = "";
                $scope.errors.objective = "";
                $scope.errors.clinic = "";
                if ($scope.selectedDistrict == null) {
                    $scope.errors.district = "This is a required field.";
                }
                if ($scope.selectedMeasurement == null) {
                    $scope.errors.measurement = "This is a required field.";
                }
                if ($scope.selectedActivity == null) {
                    $scope.errors.activity = "This is a required field.";
                }
                if ($scope.selectedObjective == null) {
                    $scope.errors.objective = "This is a required field.";
                }
                if ($scope.selectedClinic == null || $scope.selectedClinic.Id == null) {
                    $scope.errors.clinic = "This is a required field.";
                }
            };

            $scope.lookupFieldsFlag = $rootScope.store.StoreCode === 'PVT';

            $scope.modalInstance = null;

            $scope.petVet = {};
            $scope.selectedObjective = undefined;
            $scope.selectedClinic = undefined;
            $scope.selectedClinicDisplay = "";
            $scope.selectedActivity = undefined;
            $scope.selectedMeasurement = undefined;
            $scope.selectedDistrict = undefined;
            $scope.objectiveOptions = [];
            $scope.clinicOptions = [];
            $scope.activityOptions = [];
            $scope.measurementOptions = [];
            $scope.districtOptions = [];
            $scope.errors = { district: "", measurement: "", activity: "", objective: "", clinic: "" };

            $scope.programStartDate = new Date();
            $scope.programEndDate = new Date();
            $scope.programMinEndDate = new Date();
            $scope.programMaxStartDate = new Date();
            $scope.startDateModel = { datePickerOpened: false };
            $scope.endDateModel = { datePickerOpened: false };
            $scope.openStartDatePicker = openStartDatePicker;
            $scope.clearStartDatePicker = clearStartDatePicker;
            $scope.openEndDatePicker = openEndDatePicker;
            $scope.clearEndDatePicker = clearEndDatePicker;
            $scope.onChangeEndDatePicker = onChangeEndDatePicker;
            $scope.onChangeStartDatePicker = onChangeStartDatePicker;
            $scope.onClinicInputClick = onClinicInputClick;
            $scope.onClinicInputTextChange = onClinicInputTextChange;

            $scope.onDropdownChange = onDropdownChange;

            $scope.startDateOptions = {};
            $scope.endDateOptions = {};

            if ($scope.lookupFieldsFlag && ($scope.objectiveOptions == null || $scope.objectiveOptions.length <= 0)) {
                PetVetService.setPVFetchFunction(fetchPVData);
                getLookupFieldInfo();
            };

        }])
    .controller('ClinicModalCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'PetVetService',
        'data',
        function ($scope, Common, $uibModalInstance, PetVetService, data) {

            searchClinics = function ($event) {
                if ($event)
                    $event.preventDefault();

                var query = 'locationnumber=' + $scope.clinicSearchInfo.locationNumber +
                    ',sitename=' + $scope.clinicSearchInfo.siteName +
                    ',address=' + $scope.clinicSearchInfo.address +
                    ',city=' + $scope.clinicSearchInfo.city +
                    ',state=' + $scope.clinicSearchInfo.state +
                    ',postcode=' + $scope.clinicSearchInfo.postalCode;

                PetVetService.searchClinics({
                    'skip': 0,
                    'top': 1000,
                    'q': query
                }).then(function (response) {
                    setClinicResults(response.data);
                });

            };

            setClinicResults = function (clinicData) {
                $scope.clinicSearchResults = [];
                for (var i = 0; i < clinicData.length; i++) {
                    $scope.clinicSearchResults.push(clinicData[i]);
                }

                $scope.hideResultTable = false;
            };

            closeModal = function () {
                $uibModalInstance.dismiss('cancel');
            };

            onClinicRowPressed = function (clinic) {
                selectClinic(clinic);
            };

            getModalReturnObject = function (clinic) {
                return { selectedClinic: clinic, clinicData: $scope.clinicSearchResults }
            };

            selectClinic = function (clinic) {
                var returnObj = getModalReturnObject(clinic);
                $uibModalInstance.close(returnObj);
            };

            highlightClinic = function (clinic) {
                $scope.highlightClinicId = clinic.Id;
            };

            $scope.highlightClinicId = -1;;
            $scope.highlightClinic = highlightClinic;
            $scope.onClinicRowPressed = onClinicRowPressed;
            $scope.searchClinics = searchClinics;
            $scope.closeModal = closeModal;
            $scope.clinicSearchInfo = {};
            $scope.clinicSearchInfo.locationNumber = "";
            $scope.clinicSearchInfo.siteName = "";
            $scope.clinicSearchInfo.address = "";
            $scope.clinicSearchInfo.city = "";
            $scope.clinicSearchInfo.state = "";
            $scope.clinicSearchInfo.postalCode = "";
            $scope.clinicSearchResults = [];
            $scope.hideResultTable = true;

            if (data != null && data.clinicData != null) {
                setClinicResults(data.clinicData);
            };

            if (data != null && data.selectedClinic != null) {
                highlightClinic(data.selectedClinic);
            };

        }]);;angular
    .module('ecs.ctrl.favorites', [])
    .controller('favoritesCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'Common',
        'Customers',
        '$log',
        function ($scope, $location, EcsResource, CartService, Common, Customers, $log) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.

            var loadFavoriteProducts = function () {
                Customers.getWishList($scope.user.CustomerId)
                    .then(function (response) {
                    favProducts = response.data;
                    $scope.favProducts = favProducts;
                })

            },
            
            deleteFavoritesItem = function (model) {
                Customers
                    .removeWishListItem($scope.user.CustomerId, model)
                    .then(function (response) {
                        loadFavoriteProducts();
                        $log.log('wish List item removed');
                        Common.showMessage('success', '687');//success customer updated.
                    })
            };

            
            $scope.deleteFavoritesItem = deleteFavoritesItem;
            loadFavoriteProducts();
            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;


        }]);;angular
    .module('ecs.ctrl.shippingAddresses', [])
    .controller('shippingAddressesCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'AddressService',
        'Common',
        'Products',
        'Customers',
        '$log',
        '$rootScope',
        function ($scope, $location, EcsResource, CartService, AddressService, Common, Products, Customers, $log, $rootScope) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.

            var addNewAddress = false,
                editOrAdd = false,
                showMessage = false,
                existingBillingAddress,
                loadingShippingAddresses = true,

            showNewAddress = function () {
                $scope[$scope.activeForm].$setPristine();
                AddressService.setPostalAndCityValidity($scope, true);
                $scope.submitted = false;
                $scope.addNewAddress = true;
                $scope.editOrAdd = false;
                $scope.taxJurisdictions = [];
                existingBillingAddress = undefined;
                $scope.showMessage = false;
                $scope.customer = resetAddress({}, 'ShippingAddress');
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);
                
            },

            showEditAddress = function (address) {
                $scope[$scope.activeForm].$setPristine();
                $scope.submitted = false;
                $scope.addNewAddress = true;
                $scope.showMessage = true;
                $scope.editOrAdd = true;
                //Deep clone the address to edit
                $scope.customer['ShippingAddress'] = JSON.parse(JSON.stringify(address));
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);
            },

            cancelAddAddress = function () {
                $scope.$scrollTop();
                $scope.addNewAddress = false;
                $scope.showMessage = false;
                $scope[$scope.activeForm].$setPristine();
                AddressService.setPostalAndCityValidity($scope, true);
            },

            getAddresses = function () {

                Common.clearQueryStringValue('id');
                $scope.loadingShippingAddresses = true;
                Customers.getAddresses($scope.user.CustomerId,'shipping')
                .then(function (response) {
                    $scope.addresses = response.data;
                    $scope.loadingShippingAddresses = false;
                });

            },

            setDefaults = function () {
                var addressType = $scope.addressType = $scope.addressType || 'ShippingAddress'

                //Default it to none
                if (!$scope.customer) 
                    $scope.customer = resetAddress({}, addressType);
                $('#Name').keydown(e => {
                    var charCode = event.keyCode;

                    if ((charCode > 64 && charCode < 91) || (charCode > 96 && charCode < 123) || charCode == 8 || charCode == 32)

                        return true;
                    else
                        return false;
                });
                AddressService.getCountries($scope,'Shipping');
                                
            },

            resetAddress = function (customer, addressType) {

                customer[addressType] = {};
                customer[addressType].Country = 'US';
                $scope.postalCodeRequired = AddressService.isPostalCodeRequired(customer[addressType].Country);
                return customer;
            },

            updateTaxJurisdictions = function (reset, form) {

                if (!$scope[$scope.activeForm] && !!form)
                    $scope[$scope.activeForm] = form;

                AddressService.updateTaxJurisdictions($scope, reset);
            },

            onCountryChanged = function () {
                resetSelectedStateValue();
                AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);

            },

             resetSelectedStateValue = function () {
                 $scope.customer[$scope.addressType].State = "";
             },

            addOrEditShippingAddress = function () {

                var self = this;
                $scope.submitted = true;

                if ($scope[$scope.activeForm].City.$dirty || $scope[$scope.activeForm].PostalCode.$dirty) {

                    AddressService.updateTaxJurisdictions($scope, $scope.activeForm)
                    .then(function (response) {
                        self.addOrEditShippingAddress();
                    });

                } else {

                    if ($scope[$scope.activeForm].$valid) {
                        if ($scope.customer['ShippingAddress'].Name.trim().split(/\W+/).length >= 2) {
                            //Make sure the state is not set if the country doesn't have states
                            if ($scope.states.length === 0) {
                                $scope.customer['ShippingAddress'].State = "";
                            }

                            $scope.$scrollTop();

                            if (!$scope.editOrAdd) {

                                Customers.addAddress($scope.user.CustomerId, 'Shipping', $scope.customer['ShippingAddress'])
                                    .then(function (response) {

                                        getAddresses();
                                        $scope.submitted = false;
                                        $scope.addNewAddress = false;
                                        $scope.showMessage = false;
                                        $scope[$scope.activeForm].$setPristine();
                                        Common.showMessage('success', '683');//success new Shipping Address added.

                                    });

                            } else {

                                $scope.customer['ShippingAddress'].UpdateFlags = 1;
                                Customers.updateAddress($scope.user.CustomerId, $scope.customer['ShippingAddress'])
                                    .then(function (response) {

                                        getAddresses();
                                        $scope.submitted = false;
                                        $scope.addNewAddress = false;
                                        $scope.showMessage = false;
                                        $scope[$scope.activeForm].$setPristine();
                                        Common.showMessage('success', '684');//success Shipping Address updated.
                                        $rootScope.$broadcast('onMyAccountInfoChanged');

                                    });

                            }
                        } else {
                            Common.showMessage('danger', '643');
                        }
                    } else {
                        Common.showMessage('danger', '615');
                    }

                }

            },



            deleteShippingAddress = function (model) {
                Customers.removeAddress($scope.user.CustomerId, model)
                    .then(function (response) {
                        getAddresses();
                        $log.log('Shipping Address removed');
                        Common.showMessage('success', '689');//Remove Shipping address.
                    })
            };

            //$scope.hideEmailConfirm = true;
            $scope.activeForm = 'addressForm'
            $scope.addNewAddress = addNewAddress;
            $scope.showNewAddress = showNewAddress;
            $scope.loadingShippingAddresses = loadingShippingAddresses;
            $scope.addOrEditShippingAddress= addOrEditShippingAddress;
            $scope.cancelAddAddress = cancelAddAddress;
            $scope.deleteShippingAddress = deleteShippingAddress;
            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;
            $scope.editOrAdd = editOrAdd;
            $scope.showEditAddress = showEditAddress;
            $scope.currentCustomerId = $scope.user.CustomerId;
            $scope.savedAddress = undefined;
            $scope.showMessage = showMessage;

            $scope.$scrollTop();
            getAddresses();
            setDefaults();


            

        }]);;angular
    .module('ecs.ctrl.orderHistory', [])
    .controller('orderHistoryCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'ShoppingCarts',
        'Products',
        'Customers',
        'Orders',
        'Common',
        'ChiliService',
        '$log',
        '$filter',
        function ($scope, $location, EcsResource, CartService, ShoppingCarts,
            Products, Customers, Orders, Common, ChiliService, $log, $filter) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.
          
            var showIfNoData = false,
                showValidationDates = false,
                showDateNotProper = false,
                pendingApprovalDataLoaded = false,
                showPendingApprovalTab = true,
                allStoreOrderHistoryDataLoaded = false,
                //showPendingApprovalTab = true,

                searchByOrderNumber = function ($event) {
                    if ($event)
                        $event.preventDefault();


                    var query = 'ordernumber=' + $scope.search.orderNumberToSearch;
                    Customers.searchOrders({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    }).then(function (response) {
                        setOrders(response.data);
                    })


                },

                searchOrderByDateRange = function ($event, filter) {
                    if ($event)
                        $event.preventDefault();

                    //if it's passed in, update the variables
                    if (filter) {
                        $scope.selectedFilter = filter;
                    }
                    var query = 'orderdate:' + $scope.selectedFilter.query;
                    Customers.searchOrders({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    }).then(function (response) {
                        setOrders(response.data);
                    })
                },

                searchCartByDateRange = function ($event, filter) {
                    if ($event)
                        $event.preventDefault();

                    //if it's passed in, update the variables
                    if (filter) {
                        $scope.selectedFilter = filter;
                    }
                    var query = 'pendate:' + $scope.selectedFilter.query;
                    Customers.searchCustomerApprovalCarts({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    }).then(function (response) {
                        setApprovalCarts(response.data);
                    })
                },

                searchByQuoteNumber = function ($event) {
                    if ($event)
                        $event.preventDefault();

                    var query = 'quote=' + $scope.search.cartQuoteToSearch.replaceAll('#', '').trim();
                    Customers.searchCustomerApprovalCarts({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    }).then(function (response) {
                        setApprovalCarts(response.data);
                    })

                },

                loadOrders = function () {

                    var query = 'orderdate:' + $scope.selectedFilter.query;
                    Customers.searchOrders({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    })
                        .then(function (response) {
                            setOrders(response.data);
                        })

                },

                selectAllSearchBy = function ($event) {
                    if ($scope.searchBy.value != "") {
                        $scope.searchBy.label = $scope.searchByOptions.find(op => { return $scope.searchBy.value == op.value }).label
                    }
                },

                allSearch = function () {
                    if ($scope.searchBy.value != "") {
                        switch ($scope.searchBy.value) {
                            case 'searchByOrder':
                                $scope.search.orderNumberToSearch = $scope.search.searchValue;
                                searchAllStoreOrdersByOrderNumber();
                                break;
                            case 'searchBySubmittedBy':
                                $scope.search.submittedByToSearch = $scope.search.searchValue;
                                searchAllStoreOrdersByBySubmittedBy();

                                break;
                            case 'searchByQuote':
                                $scope.search.quoteNumberToSearch = $scope.search.searchValue;
                                searchAllStoreOrdersQuoteNumber();
                                break;
                        }
                    }
                },



                searchAllStoreOrdersByOrderNumber = function () {
                    //$scope.showNoResults = true;
                    //$scope.searchCompleted = false;
                    //$scope.pendingOrders = new Array();
                    //$scope.currentOrder = null;
                    //$scope.approvalComments = "";
                    //$scope.poNumber = "";

                    $scope.hideCustomerDetailPane();

                    var query = "createdate:" + $scope.selectedFilter.query + "," + 'ordernumber=' + $scope.search.orderNumberToSearch;
                    searchShoppingCarts(query);
                   
                    //statusMsg = Messenger.createStatusMessage('Searching For ' + $scope.selectedStatusFilter.label + ' Orders', 'Please wait', true);


                },

                searchAllStoreOrdersByBySubmittedBy = function () {
                    $scope.hideCustomerDetailPane();

                    var query = "createdate:" + $scope.selectedFilter.query + "," + "soldto=" + $scope.search.submittedByToSearch;
                    searchShoppingCarts(query);
                },

                searchAllStoreOrdersQuoteNumber = function () {
                    $scope.hideCustomerDetailPane();

                    var query = "createdate:" + $scope.selectedFilter.query + "," + "quote=" + $scope.search.quoteNumberToSearch;
                    searchShoppingCarts(query);
                },

                searchAllStoreOrdersByDateRange = function ($event, filter) {
                    $scope.hideCustomerDetailPane();

                    if ($event)
                        $event.preventDefault();

                    if (filter) {
                        $scope.selectedFilter = filter;
                    }

                    var query = "createdate:" + $scope.selectedFilter.query;
                    searchShoppingCarts(query);
                },

                searchShoppingCarts = function (query) {
                    $scope.showIfNoData = true;
                    $scope.allStoreOrderHistoryDataLoaded = false;
                    ShoppingCarts.searchShoppingCarts({
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    }).then(function (response) {
                        //Messenger.removeStatusMessage(statusMsg);
                        $scope.allStoreOrderHistories = response.data;
                        $scope.showIfNoData = typeof $scope.allStoreOrderHistories === 'undefined' || $scope.allStoreOrderHistories.length == 0;
                        $scope.allStoreOrderHistoryDataLoaded = true;
                        for (var i = 0; i < $scope.allStoreOrderHistories.length; i++) {
                            if (typeof $scope.allStoreOrderHistories[i].CartApprovalRequestDate === 'undefined') {
                                $scope.allStoreOrderHistories[i].CartApprovalRequestDate = "N/A";
                            } else {
                                var parsedDate = new Date(parseInt($scope.allStoreOrderHistories[i].CartApprovalRequestDate.substr(6)));
                                $scope.allStoreOrderHistories[i].CartApprovalRequestDate = $filter('date')(parsedDate, 'MM/dd/yyyy');
                            }

                            $scope.allStoreOrderHistories[i].Discount = $scope.allStoreOrderHistories[i].Discount * -1;

                            //$scope.allStoreOrderHistories[i].CustomField = JSON.parse($scope.allStoreOrderHistories[i]?.AdditionalInfo);
                            //if (!$scope.allStoreOrderHistories[i].CustomField.Clinic) {
                            //    $scope.allStoreOrderHistories[i].CustomField = null;
                            //}

                            //if (!!$scope.allStoreOrderHistories[i].CustomField) {
                            //    //If there's custom field data, format some properties
                            //    $scope.allStoreOrderHistories[i].CustomField.ProgramStart = new Date($scope.allStoreOrderHistories[i].CustomField.ProgramStart).toLocaleDateString("en-US");
                            //    $scope.allStoreOrderHistories[i].CustomField.ProgramEnd = new Date($scope.allStoreOrderHistories[i].CustomField.ProgramEnd).toLocaleDateString("en-US");
                            //}

                            if (!!$scope.allStoreOrderHistories[i].AdditionalInfo && $scope.allStoreOrderHistories[i].CartId > 0) {
                                //Parse the additional info as it should be JSON. We'll store the parsed object from here on.
                                $scope.allStoreOrderHistories[i].AdditionalInfo = JSON.parse($scope.allStoreOrderHistories[i].AdditionalInfo);
                            } else if ($scope.allStoreOrderHistories[i].AdditionalInfo && $scope.allStoreOrderHistories[i].CartId == 0) {
                                $scope.allStoreOrderHistories[i].AdditionalInfo = {
                                    OrderNumber: $scope.allStoreOrderHistories[i].AdditionalInfo
                                }
                            }

                            angular.forEach($scope.statusFilters, function (s) {
                                if (s.value == $scope.allStoreOrderHistories[i].Status)
                                    $scope.allStoreOrderHistories[i].PrintStatus = s.label;
                            });
                        }
                    }, function (e) {
                        Messenger.removeStatusMessage(statusMsg);
                        $scope.showNoResults = true;
                        $scope.allStoreOrderHistoryDataLoaded = true;
                    });
                },


            setOrders = function (data) {
                searchOrders = data;
                $scope.showIfNoData = true;
                for (var i = 0; i < searchOrders.length; i++) {
                    if (searchOrders[i].NeedByInventory > searchOrders[i].OrderDate) {
                        searchOrders[i].NeedByInventory = Common.convertJsonDateString(searchOrders[i].NeedByInventory);
                    } else {
                        searchOrders[i].NeedByInventory = null;
                    }
                    searchOrders[i].OrderDate = Common.convertJsonDateString(searchOrders[i].OrderDate);                    
                    
                    $scope.showIfNoData = false;
                }

                $scope.searchOrders = searchOrders;

            }

            getOrders = function () {
                if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                    $scope.selectedFilter = $scope.dateFilters[0];
                    loadOrders();
                }
            }

            goToOrderDetails = function (order) {
                if (order.OrderType.toUpperCase() === "GIFT CERTIFICATE")
                    $location.path('/MyAccount/GCOrderDetails/' + order.OrderNumber);
                else
                    $location.path('/MyAccount/OrderDetails/' + order.OrderNumber);
            };

            goToCartDetails = function (pendingApproval) {
                $location.path('/MyAccount/CartDetails/' + pendingApproval.CartGuid);
            };

            getApprovalCarts = function () {
                if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                    $scope.selectedFilter = $scope.dateFilters[0];
                    loadApprovalCarts();
                }
            };

            getAllStoreOrderHistory = function () {
                $scope.hideCustomerDetailPane();
                if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                    $scope.selectedFilter = $scope.dateFilters[0];
                    var query = "createdate:" + $scope.selectedFilter.query;
                    searchShoppingCarts(query);
                }
            };

            setApprovalCarts = function (data) {
                approvalCarts = data;
                $scope.showIfNoData = true;
                for (var i = 0; i < approvalCarts.length; i++) {
                    if (approvalCarts[i].CartApprovalRequestDate !== undefined && approvalCarts[i].CartApprovalRequestDate !== null) {
                        approvalCarts[i].CartApprovalRequestDate = Common.convertJsonDateString(approvalCarts[i].CartApprovalRequestDate);
                        $scope.showIfNoData = false;
                    }
                }

                $scope.approvalCarts = approvalCarts;

            };

            loadApprovalCarts = function () {
                if (pendingApprovalDataLoaded === false) {
                    var query = 'pendate:' + $scope.selectedFilter.query;
                    Customers.searchCustomerApprovalCarts({
                        ':customerId': $scope.user.CustomerId,
                        'skip': 0,
                        'top': 1000,
                        'q': query
                    })
                        .then(function (response) {
                            setApprovalCarts(response.data);
                            pendingApprovalDataLoaded = true;
                        })
                }

            };

            getRenderPDF = function (guid) {
                ChiliService.getRenderPDF(guid);
            },


            $scope.onOrderHistoryTab = function () {
                getAllStoreOrderHistory();
            };

            $scope.onPendingApprovalTab = function () {
                getApprovalCarts();
            };

            $scope.onAllStoreOrderHistoryTab = function () {
                getAllStoreOrderHistory();
            };

            $scope.showCustomerDetailPane = function (order) {
                $scope.currentOrder = order;

                if ($scope.currentOrder.captureConfig) {
                    $scope.currentOrder.captureConfig = JSON.parse($scope.currentOrder.PaymentMethod.CaptureConfig);
                    $scope.captureApprovalConfig = JSON.parse($scope.currentOrder.PaymentMethod.CaptureApprovalConfig);


                    if ($scope.captureApprovalConfig !== undefined && $scope.captureApprovalConfig !== null) {
                        $scope.costCenterAltLabel = $scope.captureApprovalConfig.CostCenterLabel;
                    }

                    if ($scope.costCenterAltLabel === undefined || $scope.costCenterAltLabel === null) {
                        var captureConfig = JSON.parse($scope.currentOrder.PaymentMethod.CaptureConfig);

                        if (captureConfig.AltCostCenterField !== undefined && captureConfig.AltCostCenterField !== null) {
                            $scope.costCenterAltLabel = captureConfig.AltCostCenterField.Label;
                        }
                    }
                }

                $scope.currentOrder.HasSellAndDisplayPriceProducts = $scope.currentOrder.Items.some(i => i.DisplayPrice != null);

                $("#fluxpanel-wrapper").removeClass("right-hidden");
            };

            $scope.hideCustomerDetailPane = function () {
                $("#fluxpanel-wrapper").addClass("right-hidden");
            };

            $scope.statusFilters = [
                {
                    value: 3,
                    label: "Pending Approval"
                },
                {
                    value: 4,
                    label: "Approved"
                },
                {
                    value: 5,
                    label: "Rejected"
                },
                {
                    value: 6,
                    label: "Ordered"
                }
            ];

            $scope.searchByOptions = [
                {
                    value: "searchByOrder",
                    label: "Search By Order #"
                },
                {
                    value: "searchBySubmittedBy",
                    label: "Search By Submitted By"
                },
                {
                    value: "searchByQuote",
                    label: "Search By Quote #"
                },
            ];

            $scope.searchBy = {
                value: $scope.searchByOptions[0].value,
                label: $scope.searchByOptions[0].label
            };
            
            $scope.searchByOrderNumber = searchByOrderNumber;
            $scope.searchByQuoteNumber = searchByQuoteNumber;
            $scope.showIfNoData = showIfNoData;
            $scope.allSearch = allSearch;
            $scope.selectAllSearchBy = selectAllSearchBy;
            $scope.searchOrderByDateRange = searchOrderByDateRange;
            $scope.searchCartByDateRange = searchCartByDateRange;
            $scope.searchAllStoreOrdersByDateRange = searchAllStoreOrdersByDateRange;
            $scope.searchAllStoreOrdersByOrderNumber = searchAllStoreOrdersByOrderNumber;
            $scope.searchAllStoreOrdersByBySubmittedBy = searchAllStoreOrdersByBySubmittedBy;
            $scope.dateFilters = (($scope.user && $scope.user.IsEmployee) ? Common.getFYStandardDateRangeFilter() : Common.getStandardDateRangeFilter());
            $scope.goToOrderDetails = goToOrderDetails;
            $scope.goToCartDetails = goToCartDetails;
            $scope.showPendingApprovalTab = showPendingApprovalTab;
            $scope.pendingApprovalDataLoaded = pendingApprovalDataLoaded;
            $scope.allStoreOrderHistoryDataLoaded = allStoreOrderHistoryDataLoaded;
            $scope.getRenderPDF = getRenderPDF
            $scope.search = {};
            getOrders();

            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;


        }]);


  ;angular
    .module('ecs.ctrl.pointHistory', [])
    .controller('pointHistoryCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'Products',
        'Customers',
        'BudgetsService',
        'Common',
        '$log',
        function ($scope, $location, EcsResource, CartService, Products, Customers, BudgetsService, Common, $log) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.
          
            var showIfNoData = false,
            showLoadedBalance = false,
            

            calculateBalanceTotals = function (data) {
                groupedHistoryEntriesArray = $scope.groupedHistoryEntriesArray;

                //calculate the balances of other months
                var currentMonthArray;
                var pastMonthArray;
                for (var i = 0; i < groupedHistoryEntriesArray.length; i++) {
                    for (var j = 0; j < groupedHistoryEntriesArray[i].length; j++) {
                        currentMonthArray = groupedHistoryEntriesArray[i][j];
                        pastMonthArray = null;
                        if (groupedHistoryEntriesArray[i][j + 1] !== undefined) {
                            pastMonthArray = groupedHistoryEntriesArray[i][j + 1];
                        }
                        groupedHistoryEntriesArray[i][j].InitialBalance = calculateBalanceByMonth(currentMonthArray, pastMonthArray);
                    }
                }
                //The last month within the data range displayed must be set from server data.
                if (groupedHistoryEntriesArray.length > 0) {
                    if (groupedHistoryEntriesArray[groupedHistoryEntriesArray.length - 1].length > 0) {
                        var indexY = groupedHistoryEntriesArray.length - 1;
                        var indexM = groupedHistoryEntriesArray[indexY].length - 1;
                        groupedHistoryEntriesArray[indexY][indexM].InitialBalance = data.Balance;
                    }
                }
                $scope.showLoadedBalance = true;
            }

            calculateBalanceByMonth = function (currentMonth, pastMonth) {

                if (pastMonth === null) {
                    return currentMonth[currentMonth.length - 1].Balance - currentMonth[currentMonth.length - 1].Amount;
                }
                else {
                    return pastMonth[0].Balance;
                }
            }

            loadBalanceByMonth = function (date, budgetGroupId) {
                var monthValue = date.getMonth() + 1; //+1 because months start on 0.
                var yearValue = date.getFullYear();
                $scope.showLoadedBalance = false;

                Customers.getStartingBalance({
                    ':customerId': $scope.user.CustomerId,
                    'groupid': budgetGroupId,
                    'm': monthValue,
                    'y': yearValue
                })
                    .then(function (response) {
                        calculateBalanceTotals(response.data);
                    })
            },

            groupHistoryEntries = function (data) {
                //format: groupedHistoryEntries[year][month][entry]
                var groupedHistoryEntries = new Map();
                var month;
                var monthName;
                var year;
                var nextIndex;

                for (var i = 0; i < data.length; i++) {
                    month = data[i].DateObj.getMonth();

                    year = data[i].DateObj.getFullYear();

                    if (groupedHistoryEntries[year] === undefined) {
                        groupedHistoryEntries[year] = new Map();
                    }

                    if (groupedHistoryEntries[year][month] === undefined) {
                        groupedHistoryEntries[year][month] = [];

                        monthName = data[i].DateObj.toLocaleString('default', { month: 'long' });

                        groupedHistoryEntries[year][month].MonthName = monthName;
                        groupedHistoryEntries[year][month].Year = year;
                    }

                    nextIndex = groupedHistoryEntries[year][month].length;
                    groupedHistoryEntries[year][month][nextIndex] = data[i];
                }

                //converting to array for better webpage compatability.
                groupedHistoryEntriesArray = [];
                var indexY;
                var indexM;
                for (var y in groupedHistoryEntries) {
                    indexY = groupedHistoryEntriesArray.length;
                    groupedHistoryEntriesArray[indexY] = [];
                    for (var m in groupedHistoryEntries[y]) {
                        indexM = groupedHistoryEntriesArray[indexY].length;
                        groupedHistoryEntriesArray[indexY][indexM] = groupedHistoryEntries[y][m];
                        //sort by date.
                        groupedHistoryEntriesArray[indexY][indexM].sort(function (a, b) {
                            return b.DateObj - a.DateObj;
                        });
                    }
                    groupedHistoryEntriesArray[indexY].reverse(); //reverse by month
                }
                groupedHistoryEntriesArray.reverse(); //reverse by year.

                $scope.groupedHistoryEntriesArray = groupedHistoryEntriesArray;

                indexY = groupedHistoryEntriesArray.length - 1;
                indexM = groupedHistoryEntriesArray[indexY].length - 1;
                nextIndex = groupedHistoryEntriesArray[indexY][indexM].length - 1;
                var lastEntry = groupedHistoryEntriesArray[indexY][indexM][nextIndex];

                loadBalanceByMonth(lastEntry.DateObj, lastEntry.BudgetAmount.BudgetGroupId);
            },

            //Converts json date format to JS date object. Requires timezome data / field 2 in json.
            convertJsonDateToDateObj = function(json) {
                var dateNumber = json.replace(/\/Date\((.*?)\)\//gi, "$1");
                return new Date(Number(dateNumber.split("-")[0]));
            },

            setPointHistory = function (data) {
                searchBudgetHistories = data;
                $scope.showIfNoData = true;
                for (var i = 0; i < searchBudgetHistories.length; i++) {
                    searchBudgetHistories[i].DateObj = convertJsonDateToDateObj(searchBudgetHistories[i].Date);
                    searchBudgetHistories[i].DisplayAmount = searchBudgetHistories[i].Amount;
                    searchBudgetHistories[i].DateDisplay = searchBudgetHistories[i].DateObj;
                    if (searchBudgetHistories[i].Amount > 0) {
                        searchBudgetHistories[i].DisplayAmount = "+" + searchBudgetHistories[i].DisplayAmount;
                    }
                    else if (searchBudgetHistories[i].amount < 0) {
                        searchBudgetHistories[i].DisplayAmount = "-" + searchBudgetHistories[i].DisplayAmount;
                    }
                    $scope.showIfNoData = false;
                }

                $scope.searchBudgetHistories = searchBudgetHistories;

                if (data.length > 0) {
                    groupHistoryEntries(data);
                }
            },

            searchByOrderNumber = function ($event) {
                if ($event)
                    $event.preventDefault();

                var query = 'ordernumber=' + $scope.orderNumberToSearch;
                Customers.searchBudgetHistories({
                    ':customerId': $scope.user.CustomerId,
                    'skip': 0,
                    'top': 1000,
                    'q': query
                }).then(function (response) {
                    setPointHistory(response.data);
                })
                
            },

            searchByDateRange = function ($event, filter) {
                if ($event)
                    $event.preventDefault();

                //if it's passed in, update the variables
                if (filter) {
                    $scope.selectedFilter = filter;
                }
                var query = 'historydate:' + $scope.selectedFilter.query;
                Customers.searchBudgetHistories({
                    ':customerId': $scope.user.CustomerId,
                    'skip': 0,
                    'top': 1000,
                    'q': query
                }).then(function (response) {
                    setPointHistory(response.data);
                })
            },

            loadPointHistory = function () {

                var query = 'historydate:' + $scope.selectedFilter.query;
                Customers.searchBudgetHistories({
                    ':customerId': $scope.user.CustomerId,
                    'skip': 0,
                    'top': 1000,
                    'q': query
                })
                    .then(function (response) {
                        setPointHistory(response.data);
                    })

            },

            getPointHistory = function () {
                if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                    $scope.selectedFilter = $scope.dateFilters[0];
                    loadPointHistory();
                }
            },

            formatNumber = function(currencyCode, amount) {
                return new Intl.NumberFormat('en-US', { style: 'currency', currency: currencyCode, currencyDisplay: 'narrowSymbol' }).format(amount)
            },

            goToOrderDetails = function (budgetHistoryEntry) {
                $location.path('/MyAccount/OrderDetails/' + budgetHistoryEntry.OrderNumber);
            };

            $scope.searchByOrderNumber = searchByOrderNumber;
            $scope.showIfNoData = showIfNoData;
            $scope.showLoadedBalance = showLoadedBalance;
            $scope.searchByDateRange = searchByDateRange;
            $scope.orderNumberToSearch = '';
            $scope.dateFilters = (($scope.user && $scope.user.IsEmployee) ? Common.getFYStandardDateRangeFilter() : Common.getStandardDateRangeFilter());
            $scope.goToOrderDetails = goToOrderDetails;
            getPointHistory();

            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;

        }]);;angular
    .module('ecs.ctrl.purchaseBalance', [])
    .controller('purchaseBalanceCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'Products',
        'Customers',
        'Employees',
        'Common',
        '$log',
        function ($scope, $location, EcsResource, CartService, Products, Customers, Employees, Common, $log) {

            

            var loadPurchaseBalance = function () {
                Employees.SearchPurchaseTransactionHistory({
                    ':employeeid': $scope.user.CustomerId,
                    'skip': 0,
                    'top': 25,
                    'q': 'orderNumber=12345,orderDay<05/01/2014'
                })
                    .then(function (response) {
                        purchaseBalance = response.data;
                        for (var i = 0; i < purchaseBalance.length; i++) {
                            purchaseBalance[i].OrderDate = Common.convertJsonDateString(purchaseBalance[i].OrderDate);
                            $scope.purchaseBalance = purchaseBalance;
                        }
                    })

            };

            loadPurchaseBalance();
            $scope.$scrollTop();



        }]);;angular
    .module('ecs.ctrl.giftCertificates', [])
    .controller('giftCertificatesCtrl', [
        '$scope',
        'Products',
        'Common',
        'Customers',
        '$location',
        function ($scope, Products, Common, Customers, $location) {

            var loadGiftCertificateInfo = function () {

                    Customers.getGiftCertificates({
                        ':customerId': $scope.user.CustomerId,
                        'show': 'showAll'
                    })
                    .then(function (response) {
                        var giftCertificateInfo = response.data,
                            balanceInfo = { balance: 0 };

                        for (var i = 0; i < giftCertificateInfo.length; i++) {
                            var certInfo = giftCertificateInfo[i];

                            balanceInfo.balance += certInfo.RemainingAmount;

                            if (!balanceInfo.BaseCurrency) {
                                balanceInfo.BaseCurrency = certInfo.BaseCurrency;
                                balanceInfo.CurrencyExchangeRates = certInfo.CurrencyExchangeRates;
                            }
                        
                        }

                        if (balanceInfo.balance == null) {
                            balanceInfo.balance == 0;
                        } 

                        $scope.balanceInfo = balanceInfo;
                    });

            },

            submitForm = function (form) {
                $scope.submitted = true;
                if (form.$valid) {
                    Customers.activateGiftCertificate($scope.user.CustomerId, $scope.giftActivation)
                        .then(function (response) {
                            $scope.submitted = false;
                            $scope.giftActivation = {};
                            loadGiftCertificateInfo();
                            Common.showMessage('success', '688');//Gift card activated successfully.
                        });


                } else {
                    Common.showMessage('danger', '615');
                }
            },         
            
            giftActivation = {
                GiftCertificateNumber: '',
                AuthorizationCode: ''
            };

            $scope.$scrollTop();
            $scope.giftActivation = giftActivation;
            $scope.submitForm = submitForm;
            $scope.showNullBalance = false;

            loadGiftCertificateInfo();


        }]);;angular
    .module('ecs.ctrl.userInfo', [])
    .controller('userInfoCtrl', [
        '$scope',
        '$location',
        'AddressService',
        'EcsResource',
        'Constants',
        'Common',
        'Objects',
        'Customers',
        '$log',
        '$window',
        '$rootScope',

        function ($scope, $location, AddressService, EcsResource, Constants, Common, Objects, Customers, $log, $window, $rootScope) {

            $scope.emailReadOnly = false;

            var loadCustomer = function () {
                console.log("loadCustomer");
                Customers.getCustomer($scope.user.CustomerId)
                    .then(function (response) {

                        setDefaults(response.data);
                    });
                $('#Name').keydown(e => {
                    var charCode = event.keyCode;

                    if ((charCode > 64 && charCode < 91) || (charCode > 96 && charCode < 123) || charCode == 8 || charCode == 32)

                        return true;
                    else
                        return false;
                });
            },

                setMode = function () {

                    $scope.checkoutMode = false;
                    var qs = $location.search();
                    if (!!qs.md && qs.md.toLowerCase() === 'gcbae') {
                        $scope.checkoutMode = true;
                        $scope.checkoutReturnPath = 'gccheckout/billing/' + qs.utsid;
                    }

                },


                setDefaults = function (customer) {

                    if (!!customer.DataConsentDate)
                        customer.formattedDataConsentDate = Common.convertJsonDateString(customer.DataConsentDate);


                    $scope.customer = customer;
                    $scope.addressType = 'BillingAddress';
                    $scope.activeForm = 'myAccountBillingForm';

                    AddressService.getCountries($scope, 'Billing');
                    AddressService.getStateOrRegions($scope, customer[$scope.addressType].Country);

                },


                resetAddress = function (customer, addressType) {

                    customer[addressType] = {};
                    customer[addressType].Country = 'US';
                    $scope.postalCodeRequired = AddressService.isPostalCodeRequired(customer[addressType].Country);
                    return customer;
                },


                updateTaxJurisdictions = function (reset, form) {
                    if (!$scope[$scope.activeForm] && !!form)
                        $scope[$scope.activeForm] = form;

                    AddressService.updateTaxJurisdictions($scope, reset);
                },


                onCountryChanged = function () {
                    AddressService.getStateOrRegions($scope, $scope.customer[$scope.addressType].Country);

                },


                getNotificationSettings = function () {

                    $scope.customer.NotificationSettings = $scope.customer.NotificationSettings || {};

                    var notifications = [],
                        newsletterEmails = { Type: 'Newsletters', Enabled: $scope.customer.NotificationSettings.NewsletterEmails },
                        marketingEmails = { Type: 'Emails', Enabled: $scope.customer.NotificationSettings.MarketingEmails };

                    if (newsletterEmails) {
                        notifications.push(newsletterEmails);
                    }

                    if (marketingEmails) {
                        notifications.push(marketingEmails);
                    }

                    return notifications;

                },

                cancelChangeAddress = function () {
                    if ($scope.checkoutMode)
                        $location.path($scope.checkoutReturnPath);

                },

                submitForm = function () {

                    var self = this;
                    $scope.submitted = true;

                    if ($scope.customer['BillingAddress'].Country === 'US' && ($scope[$scope.activeForm].City.$dirty || $scope[$scope.activeForm].PostalCode.$dirty)) {

                        AddressService.updateTaxJurisdictions($scope, $scope.activeForm)
                            .then(function (response) {
                                self.submitForm();
                            });

                    } else {

                        if ($scope[$scope.activeForm].$valid) {
                            if ($scope.customer[$scope.addressType].Name.trim().split(/\W+/).length >= 2) {

                                $scope.$scrollTop();

                                // _addressForm hides the Name field if FullName already present on the form. 
                                // $scope.customer['BillingAddress'].Name = $scope.customer.FullName;
                                $scope.customer.FullName = $scope.customer['BillingAddress'].Name;

                                //copy the values from the billing over to customer
                                $scope.customer.CompanyName = $scope.customer['BillingAddress'].CompanyName;
                                $scope.customer.Phone = $scope.customer['BillingAddress'].Phone;
                                $scope.customer.Extension = $scope.customer['BillingAddress'].Extension;
                                $scope.customer.Email = $scope.customer['BillingAddress'].Email;
                                $scope.customer.EmailConfirm = $scope.customer['BillingAddress'].EmailConfirm;
                                //   $scope.customer.NotificationSettings = getNotificationSettings();
                                $scope.customer.UpdateFlags = 1;

                                //Make sure the state is not set if the country doesn't have states
                                if ($scope.states.length === 0) {
                                    $scope.customer['BillingAddress'].State = "";
                                }

                                Customers.updateCustomer($scope.user.CustomerId, $scope.customer)
                                    .then(function (response) {
                                        $scope.submitted = false;
                                        $scope[$scope.activeForm].$setPristine();
                                        $scope.submitted = false; 
                                        $rootScope.$broadcast('onUserNameChanged');
                                        $rootScope.$broadcast('onMyAccountInfoChanged');

                                        if ($scope.checkoutMode) {
                                            Common.showMessage('success', '680');//success customer updated.
                                            $location.path($scope.checkoutReturnPath);
                                        }
                                        else {
                                            Common.showMessage('success', '685');//success customer updated.
                                        }
                                    });

                            } else {
                                Common.showMessage('danger', '643');
                            }
                        } else {
                            Common.showMessage('danger', '615');
                        }

                    }


                };


            $scope.$scrollTop();
            loadCustomer();
            setMode();

            $scope.inUsOnly = $scope.store.Functionality.InUSOnly;
            $scope.restrictBillingNameEdits = $scope.store.Functionality.RestrictBillingNameEdits;
            $scope.onCountryChanged = onCountryChanged;
            $scope.updateTaxJurisdictions = updateTaxJurisdictions;
            $scope.submitForm = submitForm;
            $scope.showMarketingEmails = $scope.store.Functionality.MarketingEmails;
            $scope.showNewsletterEmails = $scope.store.Functionality.NewsletterEmails;
            $scope.cancelChangeAddress = cancelChangeAddress;

        }]);

;angular
    .module('ecs.ctrl.digitalLocker', [])
    .controller('digitalLockerCtrl', [
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'Products',
        'Customers',
        'Notifications',
        'Common',
        'ElectronicPurchases',
        '$log',
        '$window',
        '$uibModal',
        'Config',
        function ($scope, $location, EcsResource, CartService, Products, Customers, Notifications, Common, ElectronicPurchases, $log, $window, $uibModal, Config) {

            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.


            var showDetails = false,
                hideDetails = false,
                showIfNoData = false,

            downloadDetails = function ($event, $index) {
                $event.preventDefault();
                purchaseDetails($index);
                $scope.showDetails = true;
            },

            openResendNotification = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'ResendNotification.html',
                    controller: 'ResendNotificationCtrl',
                    resolve: {
                        orderId: function () {
                            return $scope.downloadPurchaseDetails.ElectronicPurchaseGuid;
                        },
                        email: function () {
                            return $scope.downloadPurchaseDetails.RecipientEmail;
                        },
                        self: function () {
                            return $scope;
                        }

                    }
                });

            },


            searchByOrderNumber = function ($event) {
                if ($event)
                    $event.preventDefault();

                $scope.orderNumberToSearch = $scope.orderNumberToSearch.replace(/~+$/, '');
                if ($scope.orderNumberToSearch !== '') {

                    var query = 'ordernumber=' + $scope.orderNumberToSearch;
                    Customers.searchElectronicPurchases({
                        ':customerId': $scope.user.CustomerId,
                        'top': 1000,
                        'skip': 0,
                        'q': query
                    }).then(function (response) {
                        setDigitalLocker(response.data);
                    })
                }
            },

            searchByDateRange = function ($event, filter) {
                if ($event)
                    $event.preventDefault();

                //if it's passed in, update the variable
                if (filter) {
                    $scope.selectedFilter = filter;
                }

                var query = 'date:' + $scope.selectedFilter.query;
                Customers.searchElectronicPurchases({
                    ':customerId': $scope.user.CustomerId,
                    'top': 1000,
                    'skip': 0,
                    'q': query
                }).then(function (response) {
                    setDigitalLocker(response.data);
                })
            },


            purchaseDetails = function (index) {
                downloadPurchaseDetails = $scope.searchElectronicPurchases[index];
                $scope.downloadPurchaseDetails = downloadPurchaseDetails;
                if ($scope.downloadPurchaseDetails.NotificationId != null) {
                    Notifications.getNotification({
                        ':notificationId': $scope.downloadPurchaseDetails.NotificationId
                    })
                    .then(function (response) {
                        notification = response.data;
                        notification.SentDate = Common.convertJsonDateString(notification.SentDate);
                        $scope.notification = notification;


                    })
                }

                links = $scope.downloadPurchaseDetails.Links;
                if (links.length == 0) {
                    $scope.hideDetails = true;
                }
                else {
                    for (var i = 0; i < links.length; i++) {
                        links[i].LinkExpiration = Common.convertJsonDateString(links[i].LinkExpiration);
                    }
                    $scope.links = links;
                }
            },

            refreshLink = function () {
                ElectronicPurchases.refreshElectronicPurchaseLinks({
                    ':purchaseid': $scope.downloadPurchaseDetails.ElectronicPurchaseGuid
                })
                    .then(function (response) {
                        linkRefresh = response.data;
                        $scope.linkRefresh = linkRefresh;
                        $log.log('Links are refreshed');
                        Common.showMessage('success', '690');//Links have been refreshed.

                    })
            },

            editInProgress = { $el: undefined, active: false },

            toggleEditSaveMemo = function ($event, electronicPurchase) {

                var event = $event || {};
                if (electronicPurchase.MemoEditMode) {
                    //save memo here - add to api and post/update it.
                    electronicPurchase.Memo = electronicPurchase.NewMemoText;
                    updateMemo(electronicPurchase);
                    electronicPurchase.MemoEditMode = false; // after saving turn editing off
                    editInProgress.active = false;
                    editInProgress.el = undefined;
                } else {
                    if (!editInProgress.active) {
                        // change to edit mode
                        electronicPurchase.MemoEditMode = true;
                        editInProgress.active = true;
                        editInProgress.$el = $(event.currentTarget);
                    } else {
                        Common.showMessage('warning', '699');
                        //$scope.$scrollTop(editInProgress.$el.position().top);
                    }
                }


            },

            cancelEdit = function (electronicPurchase) {
                electronicPurchase.MemoEditMode = false;
                editInProgress.active = false;
                editInProgress.$el = undefined;
            },

            updateMemo = function (electronicPurchase) {
                var ep = angular.copy(electronicPurchase);
                ep.PurchaseDate = Common.convertToJsonDateString(ep.PurchaseDate);
                ElectronicPurchases.updateMemo(ep)
                    .then(function (response) {
                        $log.log('Electronic purchase memo updated.');
                        Common.showMessage('success', '698');//Links have been refreshed.
                        loadDigitalLocker();
                    })
            },

            loadDigitalLocker = function (query) {
                var query = 'date:' + $scope.selectedFilter.query;
                Customers.searchElectronicPurchases({
                    ':customerId': $scope.user.CustomerId,
                    'skip': 0,
                    'top': 1000,
                    'q': query
                })
                .then(function (response) {
                    setDigitalLocker(response.data);
                });
            },

            setDigitalLocker = function (data) {
                searchElectronicPurchases = data;
                $scope.showIfNoData = true;
                for (var i = 0; i < searchElectronicPurchases.length; i++) {
                    searchElectronicPurchases[i].PurchaseDate = Common.convertJsonDateString(searchElectronicPurchases[i].PurchaseDate);
                    $scope.showIfNoData = false;
                }

                $scope.searchElectronicPurchases = searchElectronicPurchases;


            },

            getQRCodeUrl = function (token) {
                var url = Config.Webhooks.host + Config.Webhooks.path + 'getqrcode.ashx?id={0}';
                return url.replace('{0}', token);
            },

            getDigitalLockerItems = function () {
                if ($scope.dateFilters && $scope.dateFilters.length > 0) {
                    $scope.selectedFilter = $scope.dateFilters[0];
                    loadDigitalLocker();
                }
            };

            $scope.$scrollTop();

            $scope.cancelEdit = cancelEdit;
            $scope.getQRCodeUrl = getQRCodeUrl;
            
            $scope.dateFilters = (($scope.user && $scope.user.IsEmployee) ? Common.getFYStandardDateRangeFilter() : Common.getStandardDateRangeFilter());
            $scope.showIfNoData = showIfNoData;
            $scope.orderNumberToSearch = '';
            $scope.openResendNotification = openResendNotification;
            $scope.searchByOrderNumber = searchByOrderNumber;
            $scope.toggleEditSaveMemo = toggleEditSaveMemo;
            $scope.searchByDateRange = searchByDateRange;
            $scope.showDetails = showDetails;
            $scope.downloadDetails = downloadDetails;
            $scope.refreshLink = refreshLink;
            $scope.hideDetails = hideDetails;
            //$scope.newRecipientEmail = "";

            $scope.changeFocus = Common.changeFocus;

            $scope.downloadPurchase = function ($event, link) {
                $window.location.href = link;
            };

            getDigitalLockerItems();

        }])
        .controller('ResendNotificationCtrl', [
        '$scope',
        'ElectronicPurchases',
        'Common',
        '$uibModalInstance',
        'orderId',
        'email',
        'self',
        function ($scope, ElectronicPurchases, Common, $uibModalInstance, orderId, email, self) {

            $scope.orderId = orderId;
            $scope.email = email;

            $scope.send = function (email) {
                ElectronicPurchases.resendElectronicPurchase({
                    ':purchaseid': $scope.orderId,
                    'EmailAddress': email
                }).then(function (response) {
                    self.downloadPurchaseDetails.RecipientEmail = email;
                    self.downloadPurchaseDetails.NotificationId = null;
                    self.notification.SentDate = null;
                    Common.showMessage('success', '696');
                    //$scope.newRecipientEmail = email;
                });
                $uibModalInstance.close();
            };

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);;angular
	.module('ecs.ctrl.orderDetails', [])
	.controller('orderDetailsCtrl', [
		'$rootScope',
		'$scope',
		'$location',
		'EcsResource',
		'CartService',
		'ChiliService',
		'Products',
		'Customers',
		'Orders',
		'Common',
		'$log',
		'ProductUrlService',
		'PetVetService',
		'$uibModal',
		function ($rootScope, $scope, $location, EcsResource, CartService, ChiliService, Products, Customers, Orders, Common, $log, ProductUrlService, PetVetService, $uibModal) {
			//need to have the CartService accessible by the cshtml so we can utilize the VisibleFee helpers
			$scope.CartService = CartService;
			//On page load, if there's an id at the end of the url then treat it as 
			//an id and load the product.
			var loadItems = function () {
				for (var i = 0; i < $scope.order.Items.length; i++) {
					var item = $scope.order.Items[i];

					item.DeliveryStatus = deliveryStatus($scope.order.Items[i].DeliveryStatus);
					item.ImageUrl = ProductUrlService.getImageUrl(item.Image.FileName, item.Image.Extension, 'T');
				}
			},
				setUpOrder = function (orderData) {
					$scope.order = orderData;
					$scope.order.HasSellAndDisplayPriceProducts = orderData.Items.some(i => i.DisplayPrice != null);
					$scope.order.PaymentMethod = JSON.parse(orderData.PaymentMethod.CaptureConfig);

					if ($rootScope.store.StoreCode === 'PVT') {
						PetVetService.getCustomFieldByOrder({
							':orderId': $scope.order.OrderNumber
						}).then(function (response) {
							if (response.data.Clinic != null) {
								response.data.Clinic = PetVetService.setClinicDisplayValues(response.data.Clinic);
							}
							if (response.data.ProgramEnd != null) {
								response.data.ProgramEnd = Common.convertJsonDateString(response.data.ProgramEnd);
							}
							if (response.data.ProgramStart != null) {
								response.data.ProgramStart = Common.convertJsonDateString(response.data.ProgramStart);
							}
							$scope.pvtInfo = response.data;
						})
					}

					if (!!$scope.order && !!$scope.order.ShippingAddress && $scope.order.ShippingAddress.Country == 'FR') {
						Orders.getCopyrightLevyFeeByOrder($scope.order.OrderNumber)
							.then(function (response) {
								$scope.order.CopyrightLevy = response.data;
							});
					}

					loadItems();
				},
				getOrder = function () {
					return ECSStores.Order;
				},

				isMsDcProduct = function (productNumber) {
					return Common.isMsDcProduct(productNumber);
				},

				getRenderPDF = function (guid) {
					ChiliService.getRenderPDF(guid);
				},

				fetchOrder = function (orderId) {

					Orders.getOrder({ ':orderid': orderId })
						.then(function (response) {
							setUpOrder(response.data);
						});

				},
				loadOrder = function () {
					var order = getOrder();

					//check to see if we have current product data, and if that product data
					//is still valid. Anything over 2 seconds old is cached on the page.
					if (order && !ECSStores.Meta.IsExpiredInSeconds(2)) {
						$log.log('Order loaded from page cache');

						setUpOrder(order);
					} else {
						$log.log('Order fetch from API');

						fetchOrder(order.OrderNumber);
					}
				},
				showCancel = false,
				hideCancel = false,

				deliveryStatus = function (status) {
					switch (status) {
						case 0:
							return 'Available to Ship';
							break;
						case 1:
							return 'Deleted';
							break;
						case 2:
							return 'Shipped';
							break;
						case 3:
							return 'Return credit';
							break;
						case 4:
							return 'In Process';
							break;
						case 5:
							return 'On Back Order';
							break;
						case 6:
							return 'On Hold';
							break;
						case 7:
							return 'Partially Shipped';
							break;
						case 8:
							return 'On-Demand';
							break;
						case 9:
							return 'Pre-Order';
							break;
					}
				},

				cancelOrderItem = function (orderId, itemId, $event) {

					$event.preventDefault();
					$scope.$scrollTop();
					Common.showLoader('108');

					Orders.cancelOrderItem({
						':orderId': orderId,
						':itemid': itemId
					})
						.then(function (response) {
							$log.log('Order cancelled');
							Common.showMessage('success', '691');
							$rootScope.$broadcast('onOrderItemCancel');
							$scope.order = response.data;
							loadItems();
						})
				},

				openResendOrderConfirmation = function () {
					var modalInstance = $uibModal.open({
						templateUrl: 'ResendOrderConfirmation.html',
						controller: 'ResendOrderConfirmationCtrl',
						resolve: {
							orderId: function () {
								return $scope.order ? $scope.order.OrderNumber : undefined;
							},
							email: function () {
								return $scope.order ? $scope.order.SoldToCustomerEmail : undefined;
							}
						}
					});

				};

			$scope.cancelOrderItem = cancelOrderItem;
			$scope.isMsDcProduct = isMsDcProduct;
			$scope.getGrandTotal = Common.getGrandTotal;
			$scope.openResendOrderConfirmation = openResendOrderConfirmation;
			$scope.getRenderPDF = getRenderPDF;

			loadOrder();
			$scope.$scrollTop();
			$scope.changeFocus = Common.changeFocus;
		}])
	.controller('ResendOrderConfirmationCtrl', [
		'$scope',
		'Common',
		'$uibModalInstance',
		'Orders',
		'orderId',
		'email',
		function ($scope, Common, $uibModalInstance, Orders, orderId, email) {

			$scope.orderId = orderId;
			$scope.email = email;

			$scope.send = function (email) {
				Orders.confirmationEmail({
					':orderId': $scope.orderId,
					'EmailAddress': email
				}).then(function (response) {
					Common.showMessage('success', '695');
				});
				$uibModalInstance.close();
			};

			$scope.close = function () {
				$uibModalInstance.dismiss('cancel');
			};

		}]);;angular
    .module('ecs.ctrl.cartDetails', [])
    .controller('cartDetailsCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        'EcsResource',
        'CartService',
        'ChiliService',
        'ShoppingCarts',
        'Products',
        'Customers',
        'Orders',
        'Common',
        '$log',
        'ProductUrlService',
        'PetVetService',
        '$uibModal',
        function ($rootScope, $scope, $location, EcsResource, CartService, ChiliService, ShoppingCarts, Products, Customers, Orders, Common, $log, ProductUrlService, PetVetService, $uibModal) {
            //need to have the CartService accessible by the cshtml so we can utilize the VisibleFee helpers
            $scope.CartService = CartService;
            //On page load, if there's an id at the end of the url then treat it as 
            //an id and load the product.
            var loadItems = function () {
               
                for (var i = 0; i < $scope.cart.Items.length; i++) {
                    var item = $scope.cart.Items[i];
                    item.ImageUrl = ProductUrlService.getImageUrl(item.Image.FileName, item.Image.Extension, 'T');
                }
            };

            setUpCart = function (cartData) {
                $scope.cart = cartData;
                $scope.cart.PaymentMethod = JSON.parse(cartData.PaymentMethod.CaptureConfig);
                $scope.cart.HasSellAndDisplayPriceProducts = cartData.Items.some(i => i.DisplayPrice != null);

                loadItems();
            };

            getRenderPDF = function (guid) {
                ChiliService.getRenderPDF(guid);
            },

            getCart = function () {
                return ECSStores.Cart;
            };

            isMsDcProduct = function (productNumber) {
                return Common.isMsDcProduct(productNumber);
            };

            fetchCart = function (cartGuid) {

                ShoppingCarts.getCartDetailsByGuid(cartGuid)
                    .then(function (response) {
                        setUpCart(response.data);
                    });
            };

            loadCart = function () {
                var cart = getCart();

                //check to see if we have current product data, and if that product data
                //is still valid. Anything over 2 seconds old is cached on the page.
                if (cart && !ECSStores.Meta.IsExpiredInSeconds(2)) {
                    $log.log('Cart loaded from page cache');

                    setUpCart(cart);
                } else {
                    $log.log('Cart fetched from API');

                    fetchCart(cart.CartGuid);
                }

                if ($rootScope.store.StoreCode === 'PVT') {
                    PetVetService.getCustomFieldByCart({
                        ':cartid': cart.CartId
                    }).then(function (response) {
                        if (response.data.Clinic != null) {
                            response.data.Clinic = PetVetService.setClinicDisplayValues(response.data.Clinic);
                        }
                        if (response.data.ProgramEnd != null) {
                            response.data.ProgramEnd = Common.convertJsonDateString(response.data.ProgramEnd);
                        }
                        if (response.data.ProgramStart != null) {
                            response.data.ProgramStart = Common.convertJsonDateString(response.data.ProgramStart);
                        }
                        $scope.pvtInfo = response.data;
                    })
                }
            };

            showCancel = false;
            hideCancel = false;

            statusText = function (status) {
                switch (status) {
                    case 1:
                        return 'Active';
                        break;
                    case 3:
                        return 'Pending Approval';
                        break;
                    case 4:
                        return 'Approved';
                        break;
                    case 5:
                        return 'Rejected';
                        break;
                }
            };

            cancelOrderItem = function (orderId, itemId, $event) {

                $event.preventDefault();
                $scope.$scrollTop();
                Common.showLoader('108');

                Orders.cancelOrderItem({
                    ':orderId': orderId,
                    ':itemid': itemId
                })
                    .then(function (response) {
                        $log.log('Order cancelled');
                        Common.showMessage('success', '691');
                        $rootScope.$broadcast('onOrderItemCancel');
                        $scope.order = response.data;
                        loadItems();
                    })
            };

            openResendOrderConfirmation = function () {
                var modalInstance = $uibModal.open({
                    templateUrl: 'ResendOrderConfirmation.html',
                    controller: 'ResendOrderConfirmationCtrl',
                    resolve: {
                        orderId: function () {
                            return $scope.order ? $scope.order.OrderNumber : undefined;
                        },
                        email: function () {
                            return $scope.order ? $scope.order.SoldToCustomerEmail : undefined;
                        }
                    }
                });
            };

            $scope.getRenderPDF = getRenderPDF;
            $scope.cancelOrderItem = cancelOrderItem;
            $scope.isMsDcProduct = isMsDcProduct;
            $scope.getGrandTotal = Common.getGrandTotal;
            $scope.openResendOrderConfirmation = openResendOrderConfirmation;

            loadCart();
            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;
        }]);;angular
    .module('ecs.ctrl.paymentCards', [])
    .controller('paymentCardsCtrl', [
        '$rootScope',
        '$scope',
        'Common',
        '$location',
        'Customers',
        '$log',
        '$window',
        function ($rootScope, $scope, Common, $location, Customers, $log, $window) {

            var getPaymentCards = function ($event) {

                if ($event)
                    $event.preventDefault();

                Customers.getPaymentCards($scope.user.CustomerId)
                    .then(function (response) {
                        $scope.paymentCards = response.data;
                        $scope.showNoDataMsg = $scope.paymentCards.length <= 0;
                    });
            },

            addPaymentCard = function ($event) {
                if ($event)
                    $event.preventDefault();

                $scope.$scrollTop();

                Customers.addPaymentCard($scope.user.CustomerId, $scope.newPaymentCard)
                    .then(function (response) {
                        Common.showMessage('success', '692');
                        getPaymentCards();
                    });
            },

            removePaymentCard = function (paymentCardToRemove) {
                $scope.$scrollTop();
                Customers.removePaymentCard($scope.user.CustomerId, paymentCardToRemove)
                    .then(function (response) {
                        Common.showMessage('success', '693');
                        getPaymentCards();
                    });
            },

                updatePaymentCard = function ($event) {
                 
                if ($event)
                    $event.preventDefault();

                $scope.$scrollTop();

                Customers.updatePaymentCard($scope.user.CustomerId, $scope.existingPaymentCard)
                    .then(function (response) {
                        Common.showMessage('success', '694');
                        getPaymentCards();
                    });
            }

            getPayCardName = function () {
                Customers.getCustomer($scope.user.CustomerId)
                    .then(function (response) {
                        $scope.newPaymentCard.Name = response.data.FullName;
                    });
            },

            addNewCard = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }
                $scope.newPaymentCard = getEmtpyCard();

                if ($scope.restrictBillingNameEdits) {
                    getPayCardName();
                }

                $scope.showNewPaymentCardForm = true;
            },

           cancelNewCard = function ($event) {
                if ($event) {
                    $event.preventDefault();
                }
                $scope.showNewPaymentCardForm = false;
                $scope.showSelectedPaymentCard = false;             
            },

           showSelectedCard = function (card) {
                $scope.existingPaymentCard = JSON.parse(JSON.stringify(card));
                $scope.showSelectedPaymentCard = true;
            },

            deleteSelectedCard = function (card) {
                removePaymentCard(card);
            },

            getEmtpyCard = function () {

                var monthTmp = (new Date().getMonth() + 1).toString(),
                    month = (monthTmp > 9) ? month : '0' + monthTmp,
                    year = new Date().getFullYear().toString();

                return {

                    CustomerId: $scope.user.CustomerId,
                    CardType: null,
                    CardNumber: "",
                    Last4: "",
                    ExpirationMonth: "01",
                    ExpirationYear: year,
                    Name: "",
                    CVV: "",
                    IsDefault: false
                };
            },

            checkNewCardExpDate = function () {

                var month = $scope.newPaymentCard.ExpirationMonth,
                    year = $scope.newPaymentCard.ExpirationYear,
                    expDate = new Date(year, month, 0),
                    dateValid = false;

                if (expDate.getTime() >= new Date().getTime()) {
                    dateValid = true;
                };

                return dateValid;
            },

            checkExistingCardExpDate = function () {

                var month = $scope.existingPaymentCard.ExpirationMonth,
                    year = $scope.existingPaymentCard.ExpirationYear,
                    expDate = new Date(year, month, 0),
                    dateValid = false;

                if (expDate.getTime() >= new Date().getTime()) {
                    dateValid = true;
                };

                return dateValid;
            },

            submitNewCreditCard = function (submitForm) {

                var self = this;

                $scope.isValidCard = Common.validateCreditCard($scope.newPaymentCard.CardNumber, $scope.newPaymentCard.CardType);
                //$scope.isValidCard = true;
                $scope.newPCExpDateValid = checkNewCardExpDate();
                $scope.newCCFormSubmitted = true;

                if (submitForm.$valid && $scope.newPCExpDateValid && $scope.isValidCard) {
                    $scope.newCCFormSubmitted = false;
                    addPaymentCard();
                    $scope.showNewPaymentCardForm = false;
                }
                else {
                    if (!$scope.isValidCard)
                        Common.showMessage('danger', '620');

                    else if (!$scope.newPCExpDateValid)
                        Common.showMessage('danger', '618');

                    else
                        Common.showMessage('danger', '615');
                }
            },

            submitUpdatedCreditCard = function (submitForm) {
                var self = this;
                $scope.newPCExpDateValid = checkExistingCardExpDate();
                $scope.selectedCCFormSubmitted = true;

                if (submitForm.$valid && $scope.newPCExpDateValid) {
                    $scope.selectedCCFormSubmitted = false;
                    updatePaymentCard();
                    $scope.showSelectedPaymentCard = false;
                }
                else {
                    if (!$scope.newPCExpDateValid)
                        Common.showMessage('danger', '618');

                    else
                        Common.showMessage('danger', '615');
                }
            },

            setDefaults = function () {
                $scope.paymentCards = getPaymentCards();
                $scope.showNewPaymentCardForm = false;
                $scope.showSelectedPaymentCard = false;
                $scope.showCVVInfoImage = false;
                $scope.newPCExpDateValid = true;
            },

            setCardToken = function (token, cardType) {

                if (!!token && token !== '') {
                    $scope.newPaymentCard.CardNumber = token;
                    $scope.newPaymentCard.CardType = setCardTypeFromBrand(cardType) || setCardTypeFromToken(token);
                }
                else {
                    $scope.newPaymentCard.CardNumber == null;
                    $scope.newPaymentCard.CardType == null;
                }
                $scope.$apply();
            },

            setCardTypeFromToken = function (token) {
                if (!!token && token !== '') {
                    var ccFirstDigit = token.substring(1, 2);
                    if (ccFirstDigit == '4')
                        return "VISA"
                    else if (ccFirstDigit == '5' || ccFirstDigit == '2')
                        return "MC"
                    else if (ccFirstDigit == '6')
                        return "DISC"
                    else if (ccFirstDigit == '3')
                        return "AMEX"
                    else
                        return null;
                }
                else {
                    return null;
                }
            },
            setCardTypeFromBrand = function (name) {
                if (!name)
                    return null;
                else {
                    var upper = name.toUpperCase();
                    switch (upper) {
                        case "VISA":
                            return "VISA";
                        case "MC":
                        case "MASTERCARD":
                            return "MC";
                        case "DISC":
                        case "DISCOVER":
                            return "DISC";
                        case "AMEX":
                            return "AMEX";
                        default:
                            return null;
                    }
                }
            },

            setCCHandler = function () {
                var self = this;

                $window.addEventListener('message', function (e) {
                    Common.parseCreditCardTokenMessage(e, (token, cardType) => {
                        self.setCardToken(token, cardType);
                    });
                });
            };

            setCCHandler();
            setDefaults();
            $scope.$scrollTop();
            $scope.addNewCard = addNewCard;
            $scope.cancelNewCard = cancelNewCard;
            $scope.showSelectedCard = showSelectedCard;
            $scope.deleteSelectedCard = deleteSelectedCard;
            $scope.submitNewCreditCard = submitNewCreditCard;
            $scope.submitUpdatedCreditCard = submitUpdatedCreditCard;
            $scope.restrictBillingNameEdits = $scope.store.Functionality.RestrictBillingNameEdits;

            $scope.years = Common.getYears();
            $scope.months = Common.getMonths();

        }]);;(function () {
    angular
    .module('ecs.ctrl.storePass', [])
    .controller('storePassListCtrl', [
        '$scope',
        '$rootScope',
        'Customers',
        'StorePasses',
        '$log',
        '$uibModal',
        '$location',
        'Common',
        'StorePassesStateManager',
        function ($scope, $rootScope, Customers, StorePasses, $log, $uibModal, $location, Common, StorePassesStateManager) {
            

            var getDateRangeFilter = function () {
                var today = new Date(),
                    upcoming = new Date(),
                    last30 = new Date(),
                    last6 = new Date(),
                    last12 = new Date();

                today.setDate(today.getDate());
                upcoming.setDate(upcoming.getDate() + 365);
                last30.setDate(last30.getDate() - 30);
                last6.setMonth(last6.getMonth() - 6);
                last12.setMonth(last12.getMonth() - 12);

                var todayString = [Common.padNumber(today.getMonth() + 1), Common.padNumber(today.getDate()), today.getFullYear()].join('/'),
                    upcomingString = [Common.padNumber(upcoming.getMonth() + 1), Common.padNumber(upcoming.getDate()), upcoming.getFullYear()].join('/'),
                    last30String = [Common.padNumber(last30.getMonth() + 1), Common.padNumber(last30.getDate()), last30.getFullYear()].join('/'),
                    last6String = [Common.padNumber(last6.getMonth() + 1), Common.padNumber(last6.getDate()), last6.getFullYear()].join('/'),
                    last12String = [Common.padNumber(last12.getMonth() + 1), Common.padNumber(last12.getDate()), last12.getFullYear()].join('/');


                var filters = [{ query: todayString + '||' + upcomingString, label: 'Upcoming Events' }
                                   , { query: last30String + '||' + todayString, label: 'Events in Last 30 Days' }
                                   , { query: last6String + '||' + todayString, label: 'Events in Last 6 Months' }
                                   , { query: last12String + '||' + todayString, label: 'Events in Last 12 Months' }];

                return filters;
            };

            var setupStorePassEventData = function (events) {
                for (var i = 0; i < events.length; i++) {
                    events[i].EventDate = Common.convertJsonDateString(events[i].EventDate);
                    events[i].PrintedDate = Common.convertJsonDateString(events[i].PrintedDate);
                }

                return events;
            };


            

            $scope.isDateInFuture = function (jsonDate) {
                return eval(jsonDate.replace(/\/Date\((.*?)\)\//gi, "new Date($1)")) > new Date() ? true : false;
            };

            $scope.getFAFPasses = function () {

                StorePassesStateManager.saveState('FAF', null);
                

                if ($scope.storePasses == null) {
                    if (!StorePassesStateManager.customerFAFPasses) {
                        Customers.getCustomerStorePasses($rootScope.user.CustomerId, 'FAF')
                                  .then(function (response) {
                                      $scope.storePasses = response.data;
                                      $scope.remainingPasses = 15 - response.data.length;
                                      StorePassesStateManager.customerFAFPasses = $scope.storePasses;
                                  });
                    }
                    else {
                        $scope.storePasses = StorePassesStateManager.customerFAFPasses;
                        $scope.remainingPasses = (15 - StorePassesStateManager.customerFAFPasses.length);
                    }
                }

            };

            $scope.showEditPassesDialog = function (storePass) {
                var modalInstance = $uibModal.open({
                    templateUrl: 'EditStorePass.html',
                    controller: 'editStorePassCtrl',
                    size: 'lg',
                    resolve: {
                        model: function () {
                            return $scope.storePasses;
                        },
                        storepass: function () {
                            return storePass;
                        },

                    }
                });
                modalInstance.result.then(function (model) {
                    $scope.storePasses = angular.copy(model);
                    StorePassesStateManager.customerFAFPasses = $scope.storePasses;
                })
            };

            $scope.showStorePassDeleteConfirmationDialog = function (storePass) {

                var modalInstance = $uibModal.open({
                    templateUrl: 'RemoveStorePass.html',
                    controller: 'deleteStorePassCtrl',
                    resolve: {
                        storePass: function () {
                            return storePass;
                        },
                        model: function () {
                            return $scope.storePasses;
                        }
                    }
                });
                modalInstance.result.then(function (model) {
                    $scope.storePasses = angular.copy(model);
                    StorePassesStateManager.customerFAFPasses = $scope.storePasses;
                })
            };

            $scope.showStorePassReactivateConfirmationDialog = function (storePass) {

                var modalInstance = $uibModal.open({
                    templateUrl: 'ReactivateStorePass.html',
                    controller: 'reactivateStorePassCtrl',
                    resolve: {
                        storepass: function () {
                            return storePass;
                        },
                        model: function () {
                            return $scope.storePasses;
                        }
                    }
                });
                modalInstance.result.then(function (model) {
                    $scope.storePasses = angular.copy(model);
                    StorePassesStateManager.customerFAFPasses = $scope.storePasses;
                })
            };

            $scope.getVIPPassEvents = function ($event) {

                if ($scope.vipStorePassEvents == null) {

                    if ($scope.vipSearch.searchType === 'Date')
                        $scope.searchVIPPassEvents($event, null);
                    else
                        $scope.searchVIPPassEventsByName($event);
                }
                else
                    StorePassesStateManager.saveState('VIP', $scope.vipSearch);
            };

            $scope.searchVIPPassEvents = function ($event, filter) {
                if ($event)
                    $event.preventDefault();

                //if it's passed in, update the variables
                if (filter) {
                    $scope.vipSearch.dateFilter = filter;
                }

                //Reset the name search
                $scope.vipSearch.searchFieldName = "Event Name";
                $scope.vipSearch.searchField = "eventname";
                $scope.vipSearch.searchValue = '';
                $scope.vipSearch.searchType = 'Date';

                StorePassesStateManager.saveState('VIP', $scope.vipSearch);

                var query = 'EventDate:' + $scope.vipSearch.dateFilter.query;
                StorePasses.searchStorePassEvents({
                    'skip': 0,
                    'top': 1000,
                    'q': query
                })
                         .then(function (response) {
                             $scope.vipStorePassEvents = setupStorePassEventData(response.data);
                         });
            };

            $scope.searchVIPPassEventsByName = function ($event) {

                if ($event)
                    $event.preventDefault();

                if ($scope.vipSearch.searchValue == '') {
                    return;
                }
                var searchField = $scope.vipSearch.searchField;
                var searchValue = $scope.vipSearch.searchValue;
                var query = searchField + '*=' + searchValue;

                $scope.vipSearch.searchType = 'Name';
                StorePassesStateManager.saveState('VIP', $scope.vipSearch);

                StorePasses.searchStorePassEvents({
                    'skip': 0,
                    'top': 1000,
                    'q': query
                })
                    .then(function (response) {
                        $scope.vipStorePassEvents = setupStorePassEventData(response.data);
                    });
            };

            $scope.setVIPSearchField = function ($event, field) {
                if ($event)
                    $event.preventDefault();

                $scope.vipSearch.searchField = field;

                if (field == 'eventname')
                    $scope.vipSearch.searchFieldName = 'Event Name';

                if (field == 'sponsor')
                    $scope.vipSearch.searchFieldName = 'Sponsor';

            };

            $scope.changeFocus = Common.changeFocus;
            $scope.dateFilters = getDateRangeFilter();
            $scope.storePasses = null;
            $scope.vipStorePassEvents = null;
            $scope.vipSearch = {};
            if (!!StorePassesStateManager.vipTabSearchOptions) {
                $scope.vipSearch = StorePassesStateManager.vipTabSearchOptions;
            }
            else {
                $scope.vipSearch.searchType = 'Date';
                $scope.vipSearch.searchValue = '';
                $scope.vipSearch.searchFieldName = "Event Name";
                $scope.vipSearch.searchField = "eventname";
                $scope.vipSearch.dateFilter = $scope.dateFilters[0];
            }

            $scope.tabState = {};
            if (!!StorePassesStateManager.currentTab) {
                if (StorePassesStateManager.currentTab === 'VIP')
                    $scope.tabState.vipActive = true;
            }
            (function () {
                
            })();
        }])

     .controller('editStorePassCtrl', [
            '$scope',
            '$uibModalInstance',
            'StorePasses',
            'Common',
            'model',
            'storepass',
            '$filter',
            'AddressService',
            function ($scope, $uibModalInstance, StorePasses, Common, model, storepass, $filter, AddressService) {

                $scope.isSubmitting = false;
                $scope.storePasses = model;
                $scope.emailFormatPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
                AddressService.getCountries($scope, 'FAF');

                $scope.formStorePass = {};

                $scope.editStorePass = function () {
                    $scope.isSubmitting = true;

                    var storePass = {};
                    storePass.FirstName = $scope.formStorePass.firstName;
                    storePass.LastName = $scope.formStorePass.lastName;
                    storePass.EmailAddress = $scope.formStorePass.fafEmail;
                    storePass.Country = $scope.formStorePass.Country;
                    

                    StorePasses.updateStorePass(storepass.StorePassNumber, storePass)
                     .then(function (response) {
                         $scope.isSubmitting = false;
                         Common.showMessage('success', 'Store pass successfully updated.');

                         storepass.FirstName = $scope.formStorePass.firstName;
                         storepass.LastName = $scope.formStorePass.lastName;
                         storepass.EmailAddress = $scope.formStorePass.fafEmail;
                         storepass.Country = $scope.formStorePass.Country;

                         //Update the info in the list of passes on the FAF Pass list
                         var updatedStorePass = storepass;

                         var originalStorePass = $filter('filter')(model, { StorePassNumber: updatedStorePass.StorePassNumber }, true);

                         if (!!originalStorePass) {
                             var index = model.indexOf(originalStorePass[0]);
                             if (index != -1)
                                 model[index] = updatedStorePass;
                         }

                         $uibModalInstance.close(model);
                     },
                        function (message) {
                            $scope.isSubmitting = false;
                        });
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss('cancel');
                };

                (function () {
                    $scope.formStorePass.firstName = storepass.FirstName;
                    $scope.formStorePass.lastName = storepass.LastName;;
                    $scope.formStorePass.fafEmail = storepass.EmailAddress;;
                    $scope.formStorePass.Country = storepass.Country;;
                })();
            }])

      .controller('deleteStorePassCtrl', [
          '$scope',
          'Common',
          '$uibModalInstance',
          'storePass',
          'StorePasses',
          'model',
          '$filter',
          function ($scope, Common, $uibModalInstance, storePass, StorePasses, model, $filter) {
              $scope.fullName = storePass.PassholderName;

              $scope.cancel = function () {
                  $uibModalInstance.dismiss('cancel');
              };

              $scope.removeStorePass = function () {
                  StorePasses.deleteStorePass(storePass.StorePassNumber)
                  .then(function (response) {
                      var deletedStorePass = $filter('filter')(model, { StorePassNumber: storePass.StorePassNumber }, true);
                      if (!!deletedStorePass) {
                          var index = model.indexOf(deletedStorePass[0]);
                          if (index != -1)
                              model.splice(index, 1);
                      }

                      Common.showMessage('success', 'Store Pass successfully deleted.');
                      $uibModalInstance.close(model);
                  },
                  function (message) {
                      $uibModalInstance.dismiss('cancel');
                  })
              };
          }])

    .controller('reactivateStorePassCtrl', [
         '$scope',
         'Common',
         '$uibModalInstance',
         'StorePasses',
         'storepass',
         'model',
         '$filter',
         function ($scope, Common, $uibModalInstance, StorePasses, storepass, model, $filter) {

             $scope.fullName = storepass.PassholderName;
             $scope.cancel = function () {
                 $uibModalInstance.dismiss('cancel');
             };

             $scope.reactivateStorePass = function () {
                 $scope.storePass = storepass;
                 var storePasses = [];

                 var storePass = {};
                 storePass.FirstName = storepass.FirstName;
                 storePass.LastName = storepass.LastName;
                 storePass.EmailAddress = storepass.EmailAddress;
                 storePass.PassType = 'FAF';
                 storePass.Company = 'Microsoft';
                 storePass.Country = storepass.Country;

                 storePasses.push(storePass);

                 StorePasses.createStorePass(storePasses)
                 .then(function (response) {
                     if (response.data.length > 0) {
                         var returnedStorePass = response.data[0];

                         var reactivatedStorePass = $filter('filter')(model, { StorePassNumber: returnedStorePass.StorePassNumber }, true);

                         if (!!reactivatedStorePass) {
                             var index = model.indexOf(reactivatedStorePass[0]);
                             if (index != -1)
                                 model[index] = returnedStorePass;
                         }

                         Common.showMessage('success', 'Store Pass successfully reactivated.');
                         $uibModalInstance.close(model);
                     }
                     else {
                         Common.showMessage('error', 'Failed to reactivate store pass.');
                         $uibModalInstance.dismiss('cancel');
                     }
                 },
                 function (message) {
                     Common.showMessage('error', 'Failed to reactivate store pass.');
                     $uibModalInstance.dismiss('cancel');
                 })
             };

         }]);

})();
;angular
    .module('ecs.ctrl.storePassEventDetails', [])
    .controller('storePassEventDetailsCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        '$routeParams',
        'StorePasses',
        'Common',
        '$log',
        '$uibModal',
        function ($rootScope, $scope, $location, $routeParams, StorePasses, Common, $log, $uibModal) {

            
            loadEvent = function () {

                var spEvent = undefined;
                try {
                    if (ECSStores !== undefined && !!ECSStores.EventToApprove) {
                        spEvent = ECSStores.EventToApprove;
                        //spEvent.EventDate = Common.convertJsonDateString(spEvent.EventDate);
                        //spEvent.PrintedDate = Common.convertJsonDateString(spEvent.PrintedDate);

                        $scope.storePassEvent = spEvent;
                    }
                } catch (e) {
                    //Do nothing
                }

                if (spEvent === undefined) {
                    //Event Id is in the route, load it and make sure we
                    StorePasses.getStorePassEvent($routeParams.id)
                        .then(function (response) {
                            var spEvent = response.data;
                            spEvent.EventDate = Common.convertJsonDateString(spEvent.EventDate);
                            spEvent.PrintedDate = Common.convertJsonDateString(spEvent.PrintedDate);

                            $scope.storePassEvent = spEvent;
                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/MyAccount/storepasses/');
                            } else {
                                var errCode = reason.data ? reason.data.errorCode : undefined;
                                var messageInData = reason.data ? reason.data.message : undefined;
                                var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                                Common.showMessage('danger', message, { errorCode: errCode });
                            }
                        });
                }
            },
            
            resendApproval = function ($event) {
                if ($event)
                    $event.preventDefault();

                StorePasses.resendStorePassEventApproval($scope.storePassEvent.StorePassEventId)
                    .then(function (response) {
                        Common.showMessage('danger', '632');
                        });

            },
            
            approveEvent = function ($event, isApproved) {
                if ($event)
                    $event.preventDefault();

                if (!isApproved && (!$scope.storePassApproval.Comments || $scope.storePassApproval.Comments === '')) {
                    Common.showMessage('danger', '631');
                    return;
                }

                var approvalModel = {};
                approvalModel.Approved = isApproved
                approvalModel.Comments = !!$scope.storePassApproval.Comments ? $scope.storePassApproval.Comments : null; 

                Common.showLoader('110');
                StorePasses.approveStorePassEvent($scope.storePassEvent.StorePassEventId, approvalModel)
                    .then(function (response) {
                        $scope.storePassEvent.ApprovalStatus = isApproved ? 1 : -1;
                    });

            };

            $scope.storePassEvent = null;
            $scope.storePassApproval = {};
            $scope.resendApproval = resendApproval;
            $scope.approveEvent = approveEvent;

            loadEvent();
            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;
        }]);;angular
    .module('ecs.ctrl.vipStorePassesCreate', [])
    .controller('vipStorePassesCreateCtrl', [
        '$rootScope',
        '$scope',
        '$location',
        '$routeParams',
        'StorePasses',
        'FileUploader',
        'Common',
        '$log',
        '$uibModal',
        function ($rootScope, $scope, $location, $routeParams, StorePasses, FileUploader, Common, $log, $uibModal) {

            
            init = function () {

                $scope.passType = $routeParams.id;

                //Prepopulate the StorePassEvent info 
                var newEvent = {};
                newEvent.EventName = '';
                newEvent.EventDate = '';
                newEvent.Sponsor = '';
                newEvent.MSContact = $scope.user.Name;
                newEvent.CreatedBy = $scope.user.Name;
                newEvent.CreatedByEmail = $scope.user.Email;
                newEvent.Comments = '';
                $scope.storePassEvent = newEvent;

                var today = new Date();
                var priorDate = new Date().setDate(today.getDate() - 30);
                $scope.eventDateOptions = {
                    minDate: priorDate, // set this to whatever date you want to set
                }


                var passApprover = {};
                passApprover.sponsorEmailAlias = '';

                $scope.storePassApprover = passApprover;

                $scope.newPass = {};
            },

            createStorePassEvent = function ($event) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                var model = $scope.storePassEvent;
                if (!model.CreatedByEmail || model.CreatedByEmail === '') {
                    Common.showMessage('danger', '630');
                    return;
                }

                //Do any validation above this. Once we convert this date, we won't be able to convert it again
                model.EventDate = Common.convertToJsonDateString(model.eventDateSelected);
                model.Approver = $scope.storePassApprover;
                model.GuestList = $scope.guestList;
                
                //This is testing to make sure it's always Andy
                //model.Approver.ApproverEmail = 'arogers@ecompanystore.com';


                Common.showLoader('129');
                StorePasses.createStorePassEvent(model)
                    .then(function (response) {
                        setStep(null, 4);
                    });

            },


            lookupSponsorByAlias = function ($event) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                var searchTerm = $scope.storePassApprover.sponsorEmailAlias;

                if (!searchTerm || searchTerm === '')
                    return;

                StorePasses.searchStorePassApprovers($scope.passType, searchTerm)
                    .then(function (response) {
                        if (response.data.length > 0) {
                            var passApprover = response.data[0];
                            passApprover.sponsorEmailAlias = searchTerm;

                            $scope.storePassApprover = passApprover;
                            $scope.storePassEvent.Sponsor = passApprover.ApproverName;
                        } else {
                            //If this were to happen, then just say they are not eligble
                            Common.showMessage('danger', '481');
                        }
                    });

            },

            clearSponsor = function ($event) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                $scope.storePassApprover.ApproverName = null;
                $scope.storePassApprover.ApproverEmail = null;
                $scope.storePassEvent.Sponsor = '';
            },

            toggleEntryMode = function ($event, mode) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                $scope.guestEntryMode = mode;

            },

            setStep = function ($event, step, form) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                //If we were given the form, make sure it's valid
                if (!!form && !form.$valid)
                {
                    Common.showMessage('danger', '615');
                    return;
                }

                $scope.wizardStep = step;
                $scope.datePickerOpened = false;

            },

            addGuest = function ($event, form) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                if (!!form && !form.$valid) {
                    Common.showMessage('danger', '615');
                    return;
                }


                var customer = new Object();
                customer.FirstName = $scope.newPass.FirstName;
                customer.LastName = $scope.newPass.LastName;
                customer.Company = $scope.newPass.Company;
                $scope.guestList.push(customer);

                form.$setPristine();
                $scope.newPass = {};

            },
            
            setDatePickerVisibility = function ($event, visibility) {
                if ($event) {
                    $event.preventDefault();
                    $event.stopPropagation();
                }

                $scope.datePickerOpened = visibility;

            };

            $scope.wizardStep = 1;
            $scope.passType = null;
            $scope.storePassEvent = null;
            $scope.storePassApprover = null;
            $scope.guestList = new Array();
            $scope.setDatePickerVisibility = setDatePickerVisibility;
            $scope.toggleEntryMode = toggleEntryMode;
            $scope.setStep = setStep;
            $scope.lookupSponsorByAlias = lookupSponsorByAlias;
            $scope.clearSponsor = clearSponsor;
            $scope.addGuest = addGuest;
            $scope.createStorePassEvent = createStorePassEvent;
            $scope.datePickerOpened = false;
            $scope.guestEntryMode = 'upload';
            $scope.emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;

            $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/ParseStorePassSpreadSheet", autoUpload: true }),
            $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
                console.log(status);
            };


            $scope.uploader.onCompleteItem = function (item, response, status, headers) {
                if (response.Error) {
                    $scope.uploadError = true;
                    $scope.uploadErrorList = response.ErrorMessages;
                } else {
                    $scope.uploadError = false;
                    for (var i = 0; i < response.Customers.length; i++) {
                        var customer = new Object();
                        customer.FirstName = response.Customers[i].FirstName;
                        customer.LastName = response.Customers[i].LastName;
                        customer.Company = response.Customers[i].Company;
                        if (customer.FirstName != "" && customer.LastName != "" && customer.Company != "") {
                            $scope.guestList.push(customer);
                        }
                    }
                    $scope.guestEntryMode = 'none';
                }
                $scope.$apply();
            };
           
            init();
            $scope.$scrollTop();
            $scope.changeFocus = Common.changeFocus;
        }]);;    angular
    .module('ecs.ctrl.fafStorePassCreate', [])
    .controller('fafStorePassCreateCtrl', [
            '$rootScope',
            '$scope',
            '$location',
            'Customers',
            'StorePasses',
            'Common',
            '$log',
            '$uibModal',
            'StorePassesStateManager',
            'AddressService',
            function ($rootScope, $scope, $location, Customers, StorePasses, Common, $log, $uibModal, StorePassesStateManager, AddressService) {

            
                init = function () {

                    getStorePasses();

                    $scope.formStorePass.firstName = '';
                    $scope.formStorePass.lastName = '';
                    $scope.formStorePass.fafEmail = '';
                    $scope.formStorePass.country = 'US';

                    AddressService.getCountries($scope, 'FAF');

                },

                getStorePasses = function () {
                    if (!StorePassesStateManager.customerFAFPasses) {
                        Customers.getCustomerStorePasses($rootScope.user.CustomerId, 'FAF')
                                  .then(function (response) {
                                      $scope.storePasses = response.data;
                                      $scope.canAddPasses = (response.data.length < 15);
                                      StorePassesStateManager.customerFAFPasses = $scope.storePasses;
                                  });
                    }
                    else {
                        $scope.storePasses = StorePassesStateManager.customerFAFPasses;
                        $scope.canAddPasses = (StorePassesStateManager.customerFAFPasses.length < 15);
                    }
                },

                setAcknowledgement = function () {
                    $scope.isAcknowledged = true;                  
                },

                createStorePasses = function () {
                    $scope.isSubmitting = true;
                    var storePasses = [];

                    var storePass = {};
                    storePass.FirstName = $scope.formStorePass.firstName;
                    storePass.LastName = $scope.formStorePass.lastName;
                    storePass.EmailAddress = $scope.formStorePass.fafEmail;
                    storePass.PassType = 'FAF';
                    storePass.Company = 'Microsoft';
                    storePass.Country = $scope.formStorePass.country; //$scope[$scope.formStorePass].Country.$dirty;//$scope.formStorePass.Country;

                    storePasses.push(storePass);

                    StorePasses.createStorePass(storePasses)
                        .then(function (response) {
                            $scope.isSubmitting = false;
                            if (response.data.length > 0) {
                                Common.showMessage('success', 'Friends and Family pass successfully created.');
                                angular.forEach(response.data, function (addedStorePass) {
                                    StorePassesStateManager.customerFAFPasses.push(addedStorePass);
                                });
                                $location.path('/MyAccount/storepasses/');
                            }
                        },
                        function (message) {
                            $scope.isSubmitting = false;
                        });
                };
                
                $scope.isAcknowledged = false;
                $scope.isSubmitting = false;
                $scope.canAddPasses = false;
                $scope.emailFormatPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;

                $scope.formStorePass = {};

                $scope.setAcknowledgement = setAcknowledgement;
                $scope.createStorePasses = createStorePasses;

                init();
                $scope.$scrollTop();
                $scope.changeFocus = Common.changeFocus;
            }]);

            ;angular
    .module('ecs.ctrl.storePassGuestList', [])
    .controller('storePassGuestListCtrl', [
    '$scope',
    '$rootScope',
    '$timeout',
    '$window',
    '$location',
    '$route',
    '$log',
    'Common',
    function ($scope, $rootScope, $timeout, $window, $location, $route, $log, Common) {
        var init = function () {
            var self = $scope;
        };

        $scope.guestIndex = $scope.$parent.$index;
        $scope.guestList = $scope.$parent.$parent.guestList;
        $scope.guestLink = $scope.guestList[$scope.guestIndex];

        $scope.newGuestFirstName = $scope.guestLink.FirstName;
        $scope.newGuestLasttName = $scope.guestLink.LastName;
        $scope.newGuestCompany = $scope.guestLink.Company;

        $scope.editing = false;
        $scope.deleted = false;

        $scope.editRow = function () {
            $scope.editing = true;
        };

        $scope.saveRow = function () {
            if (!$scope.newGuestFirstName || !$scope.newGuestLasttName || !$scope.newGuestCompany) {
                Common.showMessage('error', 'All fields are required before saving Guest.');
            } else {
                $scope.editing = false;
                $scope.guestLink.FirstName = $scope.newGuestFirstName;
                $scope.guestLink.LastName = $scope.newGuestLasttName;
                $scope.guestLink.Company = $scope.newGuestCompany;
            }

        };

        $scope.cancelEdit = function () {
            $scope.editing = false;
            $scope.newGuestFirstName = $scope.guestLink.FirstName;
            $scope.newGuestLasttName = $scope.guestLink.LastName;
            $scope.newGuestCompany = $scope.guestLink.Company;
        };

        $scope.deleteRow = function () {
            for (var i = 0; i < $scope.guestList.length; i++) {
                if ($scope.guestList[i] == $scope.guestLink) {
                    $scope.guestList.splice(i, 1);
                    $scope.deleted = true;
                    break;
                }
            }
        };

        init();
    }]);;angular
    .module('ecs.ctrl.gcOrderDetails', [])
    .controller('gcOrderDetailsCtrl', [
        '$rootScope',
        '$scope',
        '$log',
        'Common',
        'GiftCertificates',
        '$uibModal',
        '$location',
        function ($rootScope, $scope, $log, Common, GiftCertificates, $uibModal, $location) {

            var setGcOrderStatus = function (order) {
                if ((order.PaymentCards === null || angular.equals(order.PaymentCards, {}) || order.PaymentCards.length === 0) && order.PaymentMethod.IsTerms === false)
                    order.PrintStatus = 'Pending Payment';
                else if (!order.ToCustomerNumber)
                    order.PrintStatus = 'Pending Activation';
                else
                    order.PrintStatus = 'Activated';
            };

            var setUpGcOrder = function (order) {
                order.EffectiveDate = $scope.locale.convertDate(Common.convertJsonDateString(order.EffectiveDate));
                setGcOrderStatus(order);
                $scope.order = order;
            };

            var loadGcOrder = function () {
                var giftCertificateId = Common.getCurrentCheckoutUTSID();

                GiftCertificates.getGiftCertificate(giftCertificateId).then(
                    function (success) {
                        setUpGcOrder(success.data);
                    },
                    function (error) {
                        $log.warn("Gift Certificate load error :: ", error);
                        if (error.data.errorCode)
                            $location.path('/MyAccount/OrderHistory');
                    });
            };

            var resendGiftCertificate = function ($event) {
                if ($event)
                    $event.preventDefault();

                var modalInstance = $uibModal.open({
                    templateUrl: 'ResendGiftCertificateModalContent',
                    controller: 'resendGiftCertificateModalCtrl',
                    resolve: {
                        order: function () {
                            return $scope.order;
                        }
                    }
                });

                modalInstance.result.then(
                    function (data) {
                        $scope.order.ToName = $scope.order.ResendName;
                        $scope.order.ToEmail = $scope.order.ResendEmail
                    });
            };

            $scope.resendGiftCertificate = resendGiftCertificate;
            $scope.changeFocus = Common.changeFocus;


            loadGcOrder();
        }])

.controller('resendGiftCertificateModalCtrl', [
            '$scope',
            '$uibModalInstance',
            'order',
            'GiftCertificates',
            'Common',
            function ($scope, $uibModalInstance, order, GiftCertificates, Common) {

                order.ResendName = order.ToName;
                order.ResendEmail = order.ToEmail;
                $scope.order = order;

                $scope.send = function () {
                    Common.showLoader('126');

                    var newRecipient = {
                        Name: order.ResendName,
                        EmailAddress: order.ResendEmail
                    };

                    GiftCertificates.updateGiftCertificateEmail(order.GiftCertificateNumber, newRecipient).then(
                        function (success) {
                            Common.showMessage('success', '679');
                            $uibModalInstance.close();
                        },
                        function (error) {
                            console.log('Update gift certificate email error', error);
                        });
                };

                $scope.cancel = function () {
                    $uibModalInstance.dismiss('cancel');
                };

                $scope.emailPattern = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,10}$/i;
            }]);;angular
    .module('ecs.ctrl.removeAccount', [])
    .controller('removeAccountCtrl', [
        '$scope',
        '$location',
        '$http',
        '$window',
        '$timeout',
        'Common',
        'Customers',
        function ($scope, $location, $http, $window, $timeout, Common, Customers) {

            var self = this,
                updateConsent = function () {
                    if ($scope.requestData.dataConsent) {

                        var dataConsentPref = {};
                        dataConsentPref.Enabled = true;
                        dataConsentPref.Type = 'Data Consent';
                        Customers.updateNotificationPreferences($scope.userProfile.CustomerId, dataConsentPref)
                            .then(function (response) {
                                $scope.userProfile.updatedDataConsent = true; //This just shows a update message
                            });
                    }
                    else
                        Common.showMessage('danger', '635');

                },

                submit = function () {
                    postData($scope.requestData);
                },

                postData = function (data) {

                    var removeAccount = App.Configuration.RootPath + 'User/DataConsentRequest',
                        profile = $scope.userProfile,
                        request;

                    data.CustomerId = profile.CustomerId;
                    data.Name = profile.FullName;
                    data.Address1 = profile.BillingAddress.Address1;
                    data.Address2 = profile.BillingAddress.Address2;
                    data.City = profile.BillingAddress.City;
                    data.State = profile.BillingAddress.State;
                    data.PostalCode = profile.BillingAddress.PostalCode;
                    data.Country = profile.BillingAddress.Country;
                    data.Email = profile.Email;
                    data.Phone = profile.Phone;

                    if (data) {
                        request = $http({
                            method: "post",
                            url: removeAccount,
                            data: JSON.stringify(data)
                        });

                        request.success(function (response) {
                            var status = 'success',
                                errorMessageNum = '624';
                            if (response && !response.SendSuccess) {

                                Common.showMessage('danger', errorMessageNum);

                            }

                            $scope.submittedSuccessfully = true;

                        });

                        request.error(function (response) {
                            $scope.submittedSuccessfully = false;
                            Common.showMessage('danger', '624');
                        });
                    }


                },
                clickBackButton = function () {
                    $location.path('/MyAccount/UserInfo');
                },

                getProfile = function () {


                    var user = $scope.user;

                    if (user && user.CustomerId && user.CustomerId !== '') {
                        Customers.getCustomer(user.CustomerId)
                            .then(function (response) {
                                $scope.userProfile = response.data;
                                if (!!$scope.userProfile.DataConsentDate)
                                    $scope.userProfile.DataConsentDate = Common.convertJsonDateString($scope.userProfile.DataConsentDate);

                                //this is to handle if the user type is FAF but the data user.IsEmployee is also set to true
                                if ($scope.userProfile.Roles.length > 0) {
                                    angular.forEach($scope.userProfile.Roles, function (roles) {
                                        if (roles == 'FAF Pass Holder' || roles == 'Friends and Family Pass') {
                                            $scope.isEmployee = false;
                                            $scope.isFAF = true; 
                                        }
                                    })
                                }
                            });
                    } else { //not authorized
                        Common.goHome();
                    }
                };


            $scope.submittedSuccessfully = false;
            $scope.submit = submit;
            $scope.updateConsent = updateConsent;
            $scope.requestData = {};
            $scope.requestData.RequestType = 'Data Consent Access Request';
            $scope.requestData.todaysDate = new Date();
            $scope.requestData.dataConsent = false;
            $scope.userProfile = null;
            $scope.isEmployee = $scope.user.IsEmployee;
            $scope.isFAF = false;
            $scope.clickBackButton = clickBackButton;

            getProfile();

        }]);
        

;angular
    .module('ecs.ctrl.giftCode', [])
    .controller('giftCodeCtrl', [
        '$scope',
        '$uibModal',
        'EcsResource',
        'CartService',
        'ProductUrlService',
        'Customers',
        'Common',
        'Rewards',
        'EcsLocale',
        '$log',
        '$sce',
        'RewardService',
        function ($scope, $uibModal, EcsResource, CartService, ProductUrlService, Customers, Common, Rewards, EcsLocale, $log, $sce, RewardService) {

            var giftCodeCtrl = this,

                currentReward = RewardService.giftCodeReward ? RewardService.giftCodeReward : null,
                trophyPack = null,
                swagPack = null,

                mobileRewardLinks = undefined,

                showRedeemCodeLandingPage = function () {
                    giftCodeCtrl.isRedeemCodeLandingPageVisible = !RewardService.isGiftCodeValidated;
                },

                showRedeemCodeShopPage = function () {
                    giftCodeCtrl.isRedeemCodeLandingPageVisible = false;
                },

                validateGiftCode = function (giftCode) {
                    RewardService.validateGiftCode(giftCode).then(() => {
                        initializeRewards(RewardService.giftCodeReward);
                        showRedeemCodeShopPage();
                    }, function (err) {
                        Common.showMessageNew('fail', 'Validate Gift Code', err.data.errorCode, null);
                    });

                }

            initializeRewards = function (reward) {
                var unclaimedRewards = [],
                    historicalRewards = {},
                    historicalRewardTypes = [];

                var type = (!!reward.RewardCategory) ? reward.RewardCategory : "Other Rewards";


                reward.expirationDateObj = Common.convertJsonDateObject(reward.ExpirationDate);
                reward.htmlDescription = $sce.trustAsHtml(reward.Description)


                var redeemedProductNames = [...new Set(reward.RedeemedProducts.map(rp => rp.ProductName))];

                var redeemedAs = "";
                angular.forEach(reward.RedeemedProducts, function (rp) {
                    reward.redeemedOn = EcsLocale.convertDate(Common.convertJsonDateObject(rp.RedeemedDate));
                    reward.OrderNumber = rp.OrderNumber;
                });

                angular.forEach(redeemedProductNames, function (rpn) {
                    redeemedAs = redeemedAs + ", " + rpn;
                });

                reward.RedeemedAs = redeemedAs.substring(2);

                if (reward.Status === 1) { // should be 1 if this is a true rewards
                    reward.redirectText = 'OK, I want to see my options...';
                    //If it's Just Award or Just SWAG and we don't have any points, check if there is only one product available
                    //If there really is only 1 product, the button should just be "Confirm My Info".
                    if ((reward.CampaignComponentType === 1 || reward.CampaignComponentType === 2) && reward.Points <= 0) {
                        var packProducts = getPackProducts(reward.Packs[0]);
                        if (packProducts != undefined && packProducts.length == 1) {
                            reward.redirectText = 'Confirm My Info';
                        }
                    }
                    unclaimedRewards.push(setUnclaimedRewardOptions(reward));
                } else if (reward.Status === 2) {

                    if ($.inArray(type, historicalRewardTypes) === -1) {
                        historicalRewardTypes.push(type);
                        historicalRewards[type] = [];
                    }

                    historicalRewards[type].push(setRewardImagePaths(reward));
                }

                for (var i = 0, len = historicalRewardTypes.length; i < len; i += 1) {
                    historicalRewards[historicalRewardTypes[i]] = sortyByExpirationDate(historicalRewards[historicalRewardTypes[i]]);
                }

                giftCodeCtrl.unclaimedRewards = sortyByExpirationDate(unclaimedRewards);
                giftCodeCtrl.historicalRewards = historicalRewards;
                giftCodeCtrl.historicalRewardTypes = historicalRewardTypes;

                setCurrentReward();

            },

                toggleMobileRewardSelector = function () {
                    giftCodeCtrl.showMobileRewardSelector = !giftCodeCtrl.showMobileRewardSelector;
                    if (!mobileRewardLinks) {
                        mobileRewardLinks = $('#mobileRewardSelector a').not('.accordion-toggle');
                        mobileRewardLinks.click(toggleMobileRewardSelector);
                    }

                },

                setCurrentReward = function (reward) {


                    if (!reward) {
                        //Not passed in, then just grap first uncalaimed if we have one.
                        giftCodeCtrl.currentReward = null;
                        if (giftCodeCtrl.unclaimedRewards.length > 0) {
                            giftCodeCtrl.currentReward = giftCodeCtrl.unclaimedRewards[0];
                        }
                    }
                    else {
                        giftCodeCtrl.currentReward = reward;
                        if (!!giftCodeCtrl.unclaimedSelector)
                            giftCodeCtrl.unclaimedSelector.open = false;
                    }
                },

                sortyByExpirationDate = function (rewards) {
                    return rewards.sort(function (a, b) {
                        if (a.expirationDateObj < b.expirationDateObj) {
                            return -1;
                        } else if (b.expirationDateObj < a.expirationDateObj) {
                            return 1;
                        } else {
                            return 0;
                        }
                    });

                },

                setRewardImagePaths = function (reward) {
                    var redeemedProducts = reward.RedeemedProducts;

                    for (var i = 0, len = redeemedProducts.length; i < len; i++) {
                        var product = redeemedProducts[i],
                            imageUrls = {};

                        if (!!product.Image) {
                            imageUrls.lg = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, 'L');
                            imageUrls.md = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension);
                        }
                        else {
                            product.Image = {};
                            imageUrls.lg = '';
                            imageUrls.md = '';
                        }

                        $.extend(product.Image, imageUrls);
                    }

                    return reward;
                },

                setUnclaimedRewardOptions = function (reward) {
                    var trophyPack,
                        swagPack;

                    for (var i = 0; i < reward.Packs.length; i++) {
                        if (!trophyPack && reward.Packs[i].IsDefault) {
                            trophyPack = reward.Packs[i];
                        }

                        if (!swagPack && !reward.Packs[i].IsDefault) {
                            swagPack = reward.Packs[i];
                        }

                        if (!!trophyPack && !!swagPack) {
                            break;
                        }

                    };

                    if (!!trophyPack) {
                        setImageUrls(trophyPack);
                    }

                    if (!!swagPack) {
                        setImageUrls(swagPack);
                    }



                    reward.trophyPack = trophyPack;
                    reward.swagPack = swagPack;

                    return reward;
                },

                setImageUrls = function (pack) {
                    var urls = {};

                    urls.lg = getMainImageUrl(pack, 'l');
                    urls.md = getMainImageUrl(pack);
                    urls.sm = getMainImageUrl(pack, 'tt');

                    pack.imageUrls = urls;
                },

                setPageReady = function () {
                    giftCodeCtrl.pageReady = true;
                },

                getMainImageUrl = function (pack, size) {
                    var imageUrl,
                        product = getProduct(pack);

                    if (product) {
                        imageUrl = ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                    } else {
                        imageUrl = ProductUrlService.getNoImageUrl(size);
                    }

                    return imageUrl;
                },


                linkTo = function (path) {
                    Common.linkTo(path);
                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },

                showMyOptions = function () {

                    giftCodeCtrl.landing = false;

                },

                // Phase 1, packs only have 1 group with 1 product
                getProduct = function (pack) {
                    if (!!pack.Groups && !!pack.Groups[0] && !!pack.Groups[0].Products && !!pack.Groups[0].Products[0])
                        return pack.Groups[0].Products[0];
                    return null;
                },

                //redirect to pages based on award offerings

                redirectTo = function () {
                    var reward = giftCodeCtrl.currentReward;

                    //Is this a campaign based 
                    //Is this a gift code campaign? 
                    if (reward.CampaignComponentType == 5 || reward.CampaignComponentType == 6) {
                        giftCodeCtrl.linkTo('/select-catalog-award/' + reward.RewardId);
                        return;
                    }

                    if (!reward.Packs)
                        return;

                    //Do we have more than 1 pack or do we have points, go to select-pack to choose the options
                    if (reward.Packs.length > 1 || reward.Points > 0) {
                        giftCodeCtrl.linkTo('/redeemcode/select-pack/' + reward.RewardId);
                        return;
                    }

                    //Bad data - No Group in Pack
                    if (!reward.Packs[0].Groups)
                        return;

                    //We've got a single pack, but with more than 1 group, go to select-group to choose
                    if (reward.Packs[0].Groups.length > 1) {
                        giftCodeCtrl.linkTo('/redeemcode/select-group/' + reward.RewardId + '/' + reward.Packs[0].RewardPackId);
                        return;
                    }

                    //Otherwise it's based on the number of products in the pack, if only one go straight to Review Order page
                    var products = getPackProducts(reward.Packs[0]);
                    if (products.length > 1) {
                        giftCodeCtrl.linkTo('/select-award/' + reward.RewardId + '/' + reward.Packs[0].RewardPackId);
                        return;
                    }
                    else {
                        giftCodeCtrl.linkTo("/review-order/" + reward.RewardId + "/" + reward.Packs[0].RewardPackId + "/" + "[" + reward.Packs[0].Groups[0].Products[0].RewardProductId + "]");
                        return;
                    }

                    return;
                },

                showHistoricalReward = function (reward) {

                    var modalInstance = $uibModal.open({
                        templateUrl: 'historicalRewardTemplate',
                        controller: 'HistoricalRewardModalCtrl',
                        resolve: {
                            reward: function () {
                                return reward;
                            }

                        }
                    });

                },

                getPackProducts = function (pack) {
                    var packProducts = [];

                    for (var i = 0; i < pack.Groups.length; i++) {
                        var group = pack.Groups[i];
                        if (!!group.Products) {
                            packProducts = $.extend(packProducts, group.Products);
                        }
                    }

                    return packProducts;
                };


            giftCodeCtrl.showHistoricalReward = showHistoricalReward;
            giftCodeCtrl.currentReward = currentReward;
            giftCodeCtrl.trophyPack = trophyPack;
            giftCodeCtrl.swagPack = swagPack;

            giftCodeCtrl.linkTo = linkTo;
            giftCodeCtrl.convertDate = convertDate;
            giftCodeCtrl.getProduct = getProduct;
            giftCodeCtrl.showMyOptions = showMyOptions;
            giftCodeCtrl.landing = true;

            giftCodeCtrl.redirectTo = redirectTo;
            giftCodeCtrl.setCurrentReward = setCurrentReward;
            giftCodeCtrl.toggleMobileRewardSelector = toggleMobileRewardSelector;
            giftCodeCtrl.validateGiftCode = validateGiftCode;

            showRedeemCodeLandingPage();



        }])
    .controller('HistoricalRewardModalCtrl', [
        '$scope',
        '$uibModalInstance',
        'reward',
        function ($scope, $uibModalInstance, reward) {

            $scope.reward = reward;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);
;angular
    .module('ecs.ctrl.selectGiftCodeCatalogAward', [])
	.controller('selectGiftCodeCatalogAwardCtrl', [
        '$scope',
        '$location',
        '$routeParams',
        'EcsResource',
        'Products',
        'Common',
        'Catalogs',
        'Rewards',
        'RewardService',
        'ProductUrlService',
        '$log',
        '$uibModal',
        '$sce',
        '$window',
        function ($scope, $location, $routeParams, EcsResource, Products, Common, Catalogs, Rewards, RewardService, ProductUrlService, $log, $uibModal, $sce, $window) {


            var selectedCatalog = null,

                getPack = function (packs) {

                    var pack = null;

                    //Catalog rewards have 1 pack, with the catalogs defined as groups under the pack
                    if (packs.length > 1) {
                        $location.path('/awards/error/');
                    }

                    return packs[0];
                },

                getProductImage = function (product, size) {
                    if (!product)
                        return ProductUrlService.getNoImageurl(size);

                    return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                },

                getProductImages = function (product) {
                    product.Image.urls = {};

                    product.Image.urls.lg = getProductImage(product, 'l');
                    product.Image.urls.md = getProductImage(product, '');
                },


                getCatalogs = function (reward) {
                    var catalogs = [];

                    var pack = getPack(reward.Packs);

                    if (!!pack) {
                        for (var i = 0; i < pack.Groups.length; i++) {
                            var catalogValues = pack.Groups[i].Name.split('|');
                            var catalog = {};
                            catalog.name = catalogValues[0];
                            catalog.slug = catalogValues[1];
                            catalog.displayOrder = pack.Groups[i].DisplayOrder;
                            catalogs.push(catalog);
                        }
                    }

                    return catalogs;
                },

                getProducts = function () {
                    var products = null;

                    var catalogSlug = $scope.selectedCatalog.slug;

                    var params = {
                        ':catalogId': $scope.selectedCatalog.slug,
                        'order': 'NEWEST'
                    };
                    Common.showLoader('121');
                    Catalogs.getCatalogProducts(params)
                        .then(function (response) {
                            $scope.products = response.data.Products;
                            for (var i = 0; i < $scope.products.length; i++) {
                                getProductImages($scope.products[i]);
                            }
                        });

                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },

                redirectToOrderReview = function (rewardId, remainingRedemptions) {
                    RewardService.setSelectedProducts(remainingRedemptions, $scope.selectedProducts);
                    Common.linkTo("/review-catalog-order/" + rewardId);
                },

                showProductDetails = function (product, selectedIndex) {

                    Common.showLoader('137');

                    Products.getProduct({ ':sku': product.ProductSlug }).then((res) => {
                        Common.hideLoader();

                        var p = res.data;
                        var modalInstance = $uibModal.open({
                            templateUrl: 'GiftCodeRewardCatalogProductDetails.html',
                            controller: 'showGiftCodeRewardCatalogProductDetailsCtrl',
                            size: 'lg',
                            resolve: {
                                product: function () {
                                    return p
                                }

                            }

                        });

                        //If confirmed, delete the recipient and refresh the list
                        modalInstance.result.then(function (chooseProduct) {
                            if (chooseProduct)
                                $scope.redirectToOrderReview($scope.rewardId, product.ProductSlug);
                        });
                    });
                },

                addToSelectedProduct = function (product) {
                    var remainingRedemptions = $scope.remainingRedemptions - product.Quantity;
                    if (remainingRedemptions >= 0) {
                        product = Object.assign({}, product, { Quantity: product.Quantity });
                        $scope.remainingRedemptions = remainingRedemptions;
                        $scope.selectedProducts = [...$scope.selectedProducts, product];
                        RewardService.addToSelectedProduct($scope.selectedProducts);
                        Common.showMessage('success', `You have successfully added ${product.Name}. If you wish to check all of the added Products, proceed to the Checkout page.`);
                    } else {
                        Common.showMessage('error', 'Unable to redeem. The Quantity should not be greater than the Total Redemptions Remaining.');
                    }
                },

                getReward = function () {
                    Rewards.getReward($scope.rewardId)
                        .then(function (reward) {
                            if (reward.data.Status != 1) {
                                Common.goHome();
                                return;
                            }

                            $scope.reward = reward.data;
                            $scope.rewardCatalogs = getCatalogs($scope.reward);
                            $scope.selectedCatalog = $scope.rewardCatalogs[0];
                            $scope.showCatalogSel = ($scope.rewardCatalogs.length > 1);
                            var remainingRedemptions = $scope.reward.TotalUnitsRedeemable;
                            if (reward.data.RedeemedProducts && reward.data.RedeemedProducts.length > 0) {
                                angular.forEach(reward.data.RedeemedProducts, function (rp) {
                                    remainingRedemptions -= rp.Quantity;
                                });
                            }
                            $scope.remainingRedemptions = remainingRedemptions;
                            //Get the products in the catalog
                            getProducts();

                            $window.sessionStorage.clear(); //if the user clicks the back button, remove any stored selected products in session storage
                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/awards/error/');
                            } else {
                                var errCode = reason.data ? reason.data.errorCode : undefined;
                                var messageInData = reason.data ? reason.data.message : undefined;
                                var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                                Common.showMessage('danger', message, { errorCode: errCode });
                            }
                        });
                };



            $scope.linkTo = function (path) {
                return Common.linkTo(path);
            };


            $scope.reward = null;
            $scope.products = [];
            $scope.rewardCatalogs = [];
            $scope.selectedProducts = [];

            $scope.rewardId = $routeParams.id;
            $scope.selectedCatalog = selectedCatalog;
            $scope.getProducts = getProducts;
            $scope.convertDate = convertDate;
            $scope.showProductDetails = showProductDetails;
            $scope.redirectToOrderReview = redirectToOrderReview;
            $scope.addToSelectedProduct = addToSelectedProduct;

            getReward();
            $scope.changeFocus = Common.changeFocus;
        }])

    .controller('showGiftCodeRewardCatalogProductDetailsCtrl', [
        '$scope',
        'Common',
        'ProductUrlService',
        '$uibModalInstance',
        '$sce',
        'product',
        'RewardService',
        function ($scope, Common, ProductUrlService, $uibModalInstance, $sce, product, RewardService) {
            $scope.product = product || {};
            $scope.product.DescriptionHTML = $sce.trustAsHtml(product.Description);

            $scope.close = function (chooseProduct) {
                $uibModalInstance.close(chooseProduct);
            };

            (function initialiseZoomOptions() {
                RewardService.renderZoomableMultiImage($scope.product);
            })();
        }]);
;'use strict';

/* 
    1. Code to display existing shipping address with 
    selection option will be moved to a directive.
*/

angular
    .module('ecs.ctrl.review-gift-code-catalog-order', [])
    .controller('reviewGiftCodeCatalogOrderCtrl', [
        '$scope',
        '$rootScope',
        '$routeParams',
        'Common',
        'Rewards',
        'RewardService',
        'ProductUIService',
        '$window',
        function ($scope, $rootScope, $routeParams, Common, Rewards, RewardService, ProductUIService, $window) {
            var 

                redirectBackToSelect = function () {
                    $scope.rewardService.linkTo('/select-catalog-award/' + $scope.rewardId);
                    $window.sessionStorage.clear();
                },

                redeemReward = function () {
                    // Check if gift code is still valid.
                    // This is needed in case the user redeemed the code in another instance of a browser.
                    // https://cic.my.workfront.com/task/view?ID=61ae36d2000f7666968c51a2072d77cc
                    Rewards.validateRewardGiftCode($scope.rewardService.reward.PromoCode).then(
                        () => {
                            $scope.rewardService.redeemReward();
                        },
                        (error) => {
                            Common.showMessageNew('fail', 'Validate Gift Code', error.data.errorCode, null);
                        }
                    );
                },

                showAddressForm = function () {
                    // Check if gift code is still valid.
                    Rewards.validateRewardGiftCode($scope.rewardService.reward.PromoCode).then(
                        () => {
                            $scope.rewardService.showAddressForm(true);
                        },
                        (error) => {
                            Common.showMessageNew('fail', 'Validate Gift Code', error.data.errorCode, null);
                        }
                    );
                };

            $scope.productUI = ProductUIService;
            $scope.rewardService = RewardService;
            $scope.rewardId = $routeParams.id;
            $scope.redeemReward = redeemReward;
            $scope.redirectBackToSelect = redirectBackToSelect;
            $scope.showAddressForm = showAddressForm;
            $scope.rewardService.setScope($scope);
            $scope.rewardService.setStoreCode($rootScope.store.StoreCode);
            $scope.rewardService.getReward($scope.rewardId);
            $scope.rewardService.getProducts();
        }]);


;angular
    .module('ecs.ctrl.selectGiftCodeAward', [])
    .controller('selectGiftCodeAwardCtrl', [
		'$scope',
		'$location',
		'$routeParams',
		'EcsResource',
		'Products',
		'Common',
		'Customers',
        'Rewards',
        'RewardService',
		'ProductUrlService',
        '$log',
        '$window',
        function ($scope, $location, $routeParams, EcsResource, Products, Common, Customers, Rewards, RewardService, ProductUrlService, $log, $window) {
		   

		    var trophyPack = null,

		    rewardProductId = null,

		    getPack = function (packs) {

		        var pack = null;

		        $.each(packs, function (index) {
		            if (this.RewardPackId == $scope.packId) {
		                pack = this;
		            }
		        });

		        if (pack == null) {
		            $location.path('/awards/error/');
		        }

		        for (var i = 0; i < packs.length; i++) {
		            if (!trophyPack && packs[i].Type === 1) {
		                trophyPack = packs[i];
		                $scope.trophyPackId = trophyPack.RewardPackId;
		            }
		            if (!!trophyPack)
		                break;
		        };

		        // Trophy packs only have 1 group and 1 product - for now.
		        if (!!trophyPack && !!trophyPack.Groups && !!trophyPack.Groups[0] && !!trophyPack.Groups[0].Products && !!trophyPack.Groups[0].Products[0])
		            rewardProductId = trophyPack.Groups[0].Products[0].RewardProductId;

		        $scope.rewardProductId = rewardProductId;

		        return pack;
		    },



		   

		    getNoImageurl = function (size) {
		        return ProductUrlService.getNoImageurl(size);
		    },

		    getProductImage = function (product, size) {
		        if (!product)
		            return getNoImageurl(size);

		        return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
		    },

            getProductImages = function (product) {
                product.Image.urls = {};

                product.Image.urls.lg = getProductImage(product, 'l');
                product.Image.urls.md = getProductImage(product, '');
                product.Image.urls.sm = getProductImage(product, 't');
                product.Image.urls.xs = getProductImage(product, 'tt');
            },

            getProducts = function (reward) {
                var products = null;

                var pack = getPack(reward.Packs);

                // Phase 1, packs on ly have 1 group
                if (!!pack.Groups[0]) {
                    products = pack.Groups[0].Products;
                }

                if (!!products) {
                    for (var i = 0; i < products.length; i++) {
                        getProductImages(products[i]);
                    }
                }

                return products;
            },



		    convertDate = function (date) {
		        return Common.convertJsonDateString(date);
		    },



                customRewardsRedirectToOrderReview = function (rewardId, packId, productId) {

		        Common.linkTo("/review-order/" + rewardId + "/" + packId + "/" + JSON.stringify(productId));
                },

                redirectToOrderReview = function (rewardId, packId, remainingRedemptions) {
                    RewardService.setSelectedProducts(remainingRedemptions, $scope.selectedProducts);
                    Common.linkTo("/review-order/" + rewardId + "/" + packId);
                },

             showProductDetails = function (products, selectedIndex) {
                 if (products[selectedIndex].showDetails) {
                     products[selectedIndex].showDetails = false;
                 } else {
                     for (var i = 0, len = products.length; i < len; i += 1) {
                         products[i].showDetails = false;
                     }
                     products[selectedIndex].showDetails = true;
                 }

                },

                addToSelectedProduct = function (product) {
                    var remainingRedemptions = $scope.remainingRedemptions - product.Quantity;
                    if (remainingRedemptions >= 0) {
                        product = Object.assign({}, product, { Quantity: product.Quantity });
                        $scope.remainingRedemptions = remainingRedemptions;

                        // check if product is already added
                        var pid = $scope.selectedProducts.find((p) => p.RewardProductId === product.RewardProductId);
                        if (pid && !pid.IsConfigurable) { //IsConfigurable is used for getting childProducts
                            $scope.selectedProducts = $scope.selectedProducts.map(p => {
                                if (p.RewardProductId === product.RewardProductId) {
                                    return { ...p, Quantity: p.Quantity + product.Quantity }
                                } else {
                                    return { ...p }
                                }

                            });
                        } else {
                            $scope.selectedProducts = [...$scope.selectedProducts, product];
                        }
                        RewardService.addToSelectedProduct($scope.selectedProducts);
                        Common.showMessage('success', `You have successfully added ${product.Name}. If you wish to check all of the added Products, proceed to the Checkout page.`);
                    } else {
                        Common.showMessage('error', 'Unable to redeem. The Quantity should not be greater than the Total Redemptions Remaining.');
                    }
                },

            getReward = function () {
                Rewards.getReward($scope.rewardId)
				    .then(function (reward) {
				        if (reward.data.Status != 1) {
				            Common.goHome();
				            return;
				        }

                        $scope.reward = reward.data;
                        var remainingRedemptions = $scope.reward.TotalUnitsRedeemable;
                        if (reward.data.RedeemedProducts && reward.data.RedeemedProducts.length > 0) {
                            angular.forEach(reward.data.RedeemedProducts, function (rp) {
                                remainingRedemptions -= rp.Quantity;
                            });
                        }
                        $scope.remainingRedemptions = remainingRedemptions;
                        $scope.products = getProducts($scope.reward);

                        $window.sessionStorage.clear(); //if the user clicks the back button, remove any stored selected products in session storage
				    }, function (reason) {
				        if (reason.status == '400' || reason.status == '401') {
				            $location.path('/awards/error/');
				        } else {
				            var errCode = reason.data ? reason.data.errorCode : undefined;
				            var messageInData = reason.data ? reason.data.message : undefined;
				            var message = errCode ? errCode : messageInData || (reason.statusText || '200');
				            Common.showMessage('danger', message, { errorCode: errCode });
				        }
				    });
            };

		    $scope.linkTo = function (path) {
		        return Common.linkTo(path);
		    };

		    
		    $scope.reward = null;
            $scope.products = [];
            $scope.selectedProducts = [];

		    $scope.rewardId = $routeParams.id;
		    $scope.packId = $routeParams.packId;
		    $scope.rewardProductId = rewardProductId;
		    $scope.convertDate = convertDate;
		    $scope.showProductDetails = showProductDetails;
            $scope.redirectToOrderReview = redirectToOrderReview;
            $scope.customRewardsRedirectToOrderReview = customRewardsRedirectToOrderReview;
            $scope.addToSelectedProduct = addToSelectedProduct;

		    

            getReward();
		}]);;'use strict';

/* 
    1. Code to display existing shipping address with 
    selection option will be moved to a directive.
*/

angular
    .module('ecs.ctrl.review-gift-code-order', [])
    .controller('reviewGiftCodeOrderCtrl', [
        '$scope',
        '$rootScope',
        '$location',
        '$routeParams',
        'EcsResource',
        'Products',
        'Common',
        'Rewards',
        'ProductUrlService',
        '$log',
        '$uibModal',
        '$sce',
        'Campaign',
        'RewardService',
        'ProductUIService',
        '$window',
        function ($scope, $rootScope, $location, $routeParams, EcsResource, Products, Common, Rewards, ProductUrlService, $log, $uibModal, $sce, Campaign, RewardService, ProductUIService, $window) {
            var currentUser = ECSStores.CurrentUser,
                redeemed = false,

                // PHX-61
                // TODO: We need to merge this logic to reward service 
                updateRemainingRedemptions = (product) => {
                    if (!product.Quantity) product.Quantity = 1;

                    const remainingQty = $scope.reward.NumberOfRemainingProductsToRedeem;
                    const totalQty = $scope.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                    if (totalQty <= remainingQty) {
                        RewardService.remainingRedemptions = remainingQty - totalQty;

                    } else {
                        const excessQty = totalQty - remainingQty;
                        product.Quantity = product.Quantity - excessQty;
                        RewardService.remainingRedemptions = 0;
                        Common.showMessage('danger', 'The quantity you entered exceeded your total remaining redemptions, the quantity was set to your total remaining redemptions');
                    }
                    $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(RewardService.remainingRedemptions));
                    $window.sessionStorage.setItem("products", JSON.stringify($scope.products));
                },

                // PHX-61
                // TODO: We need to merge this logic to reward service 
                removeSelectedProduct = (product) => {
                    const idx = $scope.products.indexOf(product);
                    $scope.products.splice(idx, 1);
                    const remainingQty = $scope.reward.NumberOfRemainingProductsToRedeem;
                    const totalQty = $scope.products.reduce((a, b) => a + (b['Quantity'] || 0), 0);
                    RewardService.remainingRedemptions = remainingQty - totalQty;
                    $window.sessionStorage.setItem("remainingRedemptions", JSON.stringify(RewardService.remainingRedemptions));
                    $window.sessionStorage.setItem("products", JSON.stringify($scope.products));

                    if ($scope.products.length == 0) {
                        $window.sessionStorage.clear();
                        $scope.redirectToSelectAward();
                    }
                },

                getPack = function (packId, reward) {
                    var pack = null;

                    if (!reward || !reward.Packs)
                        return pack;

                    $.each(reward.Packs, function (index) {
                        if (this.RewardPackId == $scope.packId) {
                            pack = this;
                        }
                    });

                    if (pack == null) {
                        $location.path('/awards/error/');
                    }

                    return pack;
                },

                getProduct = function (productId, pack) {
                    var product = null;

                    if (!pack || !pack.Groups)
                        return product;

                    $.each(pack.Groups, function (index) {
                        if (!!this.Products) {
                            $.each(this.Products, function (index) {
                                var p = this;
                                if (p.RewardProductId == productId) {
                                    product = p;
                                }
                            });
                        }
                    });

                    if (product == null) {
                        $location.path('/awards/error/');
                    }

                    return product;
                },

                //required for displaying shipping address in 2 columns
                //can be moved to a different service when tested
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },



                loadChildProducts = function (product) {
                    if (!product || !product.IsConfigurable) {
                        product.selectedConfiguration = null;
                        product.childProducts = null;
                        return;
                    }

                    product.selectedConfiguration = null;
                    product.childProducts = null;

                    //haven't fully tested this yet with Multi Gifts
                    Products.getBackendChildProducts(product.ProductNumber).then(
                        function (response) {
                            product.childProducts = response.data;
                        },
                        function (message) {
                            $log.log('Error getting child products', message);
                        });
                },

                getNoImageurl = function (size) {
                    return ProductUrlService.getNoImageurl(size);
                },

                getProductImage = function (product, size) {
                    if (!product)
                        return getNoImageurl(size);

                    return ProductUrlService.getImageUrl(product.Image.FileName, product.Image.Extension, size);
                },

                getProductImages = function (product) {
                    product.Image.urls = {};

                    product.Image.urls.lg = getProductImage(product, 'l');
                    product.Image.urls.md = getProductImage(product, '');
                    product.Image.urls.sm = getProductImage(product, 't');
                    product.Image.urls.xs = getProductImage(product, 'tt');
                },

                loadSelectedProductByIds = function (productIds, pack) {
                    var productArray = [];

                    if (!Array.isArray(productIds)) {
                        productArray.push(productIds)
                    } else {
                        productArray = productIds;
                    }

                    $.each(productArray, function (index) {
                        var product = getProduct(this, pack);
                        getProductImages(product);
                        $scope.products.push(product);
                        loadChildProducts(product);
                    });
                },

                loadSelectedProducts = function (selectedProducts) {
                    if (!selectedProducts) {
                        //to handle when page is hard reload/refresh
                        RewardService.products = JSON.parse($window.sessionStorage.getItem("products"));
                        selectedProducts = RewardService.products;
                        RewardService.remainingRedemptions = JSON.parse($window.sessionStorage.getItem("remainingRedemptions"));
                    }
                    $scope.products = selectedProducts;
                    angular.forEach($scope.products, function (p) {
                        loadChildProducts(p);
                    });
                },

                getReward = function (rewardid) {

                    Rewards.getReward(rewardid).
                        then(function (reward) {

                            if (reward.data.Status != 1) {
                                Common.goHome();
                                return;
                            }

                            $scope.reward = reward.data;
                            $scope.shipToAddress = $scope.reward.DefaultShippingAddress;
                            $scope.pack = getPack($scope.packId, $scope.reward);
                            if (!!$scope.productId) {
                                loadSelectedProductByIds($scope.productId, $scope.pack);
                            } else {
                                loadSelectedProducts(RewardService.selectedProducts);
                            }
                            $scope.reward.awardConfigJSON = JSON.parse(reward.data.AwardConfigJSON);

                            $scope.reward.PersonalizedName = $scope.reward.RecipientName;
                            $scope.paymentRequired = $scope.reward.PaymentRequired;

                        }, function (reason) {
                            if (reason.status == '400' || reason.status == '401') {
                                $location.path('/awards/error/');
                            } else {
                                var errCode = reason.data ? reason.data.errorCode : undefined;
                                var messageInData = reason.data ? reason.data.message : undefined
                                var message = errCode ? errCode : messageInData || (reason.statusText || '200');
                                Common.showMessage('danger', message, { errorCode: errCode });
                            }
                        });
                },

                getNoImageurl = function (size) {
                    return ProductUrlService.getNoImageurl(size);
                },

                //====End Private functions



                toggleEdit = function () {
                    $scope.editName = !$scope.editName;
                },


                cancelNameEdit = function () {
                    $scope.reward.PersonalizedName = $scope.savedRecipientName;
                    $scope.toggleEdit();
                },

                prepareForNameEdit = function () {
                    $scope.savedRecipientName = $scope.reward.PersonalizedName;
                    $scope.toggleEdit();
                },

                canRedeem = function () {
                    var isReadyToRedeem = false;

                    if ($scope.products != null && $scope.products.length == 1) {
                        var product = $scope.products[0];
                        isReadyToRedeem = !!product &&
                            (!product.IsConfigurable || !!product.selectedConfiguration);
                    }
                    else {
                        if (!!$scope.products) {
                            isReadyToRedeem = true;
                            $.each($scope.products, function (index) {
                                var product = this;
                                if (!!product.childProducts && !product.selectedConfiguration) {
                                    isReadyToRedeem = false;
                                }
                            });
                        }

                        isReadyToRedeem = isReadyToRedeem;
                    }

                    return isReadyToRedeem;
                },

                redirectTo = function () {
                    $scope.linkTo('/awards/select-pack/' + $scope.rewardId);
                },
                redirectToSelectAward = function () {
                    $scope.linkTo('/select-award/' + $routeParams.id + '/' + $routeParams.packId);
                },

                redeemReward = function () {

                    if (!$scope.rewardService.shippingChecks()) {
                        return;
                    }

                    Common.showLoader('119');

                    var selectedProduct = [];

                    $.each($scope.products, function (index) {
                        var product = {};
                        product.ProductNumber = this.IsConfigurable ? (!!this.selectedConfiguration.PurchaseProductNumber ? this.selectedConfiguration.PurchaseProductNumber : this.selectedConfiguration.ProductNumber) : this.ProductNumber;
                        product.ProductName = this.Name;
                        product.Quantity = this.Quantity ? this.Quantity : 1;
                        product.RedeemedAs = this.Name;

                        if (this.IsConfigurable) {
                            product.RedeemedAs = product.RedeemedAs + ' with Option ' + this.selectedConfiguration.OptionType + ':' + this.selectedConfiguration.Name
                        }

                        selectedProduct.push(product);
                    });

                    var rewardRedemptionDTO = {
                        'RewardId': $scope.reward.RewardId,
                        'Type': 1, //Redeem Pack
                        'RedeemedAs': $scope.pack.Name,
                        'PersonalizedName': $scope.reward.PersonalizedName,
                        'ShippingAddress': $scope.shipToAddress, //Don't need to provide the shipping address anymore in the redemption. Is already been set in the DB
                        'RedeemedPack': {
                            'RewardPackId': $scope.packId,
                            'RedeemedProducts': selectedProduct
                        },
                        'IsExpired': false,
                        'IncludesBase': Boolean($scope.reward.needsBase)
                    };

                    if ($scope.shipToAddress.Country !== 'US') {
                        rewardRedemptionDTO.ContactPhone = $scope.reward.ContactPhone;
                        rewardRedemptionDTO.ContactPhoneExtension = $scope.reward.ContactPhoneExtension;
                    }


                    $scope.redeeming = true;

                    Rewards.redeemRewards($scope.reward.RewardId, rewardRedemptionDTO, '100')
                        .then(function (response) {
                            $log.log(response);
                            $scope.reward.OrderNumber = !!response.data.RedeemedPack.RedeemedProducts && response.data.RedeemedPack.RedeemedProducts.length > 0 ? response.data.RedeemedPack.RedeemedProducts[0].OrderNumber : null;
                            redeemed = true;
                            $scope.redeeming = false;
                            RewardService.isGiftCodeValidated = false;
                            $scope.$scrollTop(0);
                        },
                            function (message) {
                                $scope.redeeming = false;
                                Common.showMessage('error', 'Error redeeming the reward.');
                                $log.log('Error redeeming product', message);
                            });
                },

                isRedeemed = function () {
                    // There is no OrderNumber created for trophies yet, so we need to also track via
                    // the redeemed variable.
                    return !!$scope.reward && (!!$scope.reward.OrderNumber || $scope.reward.Status != 1 || redeemed);
                },

                isTrophy = function () {
                    return !!$scope.pack && !$scope.pack.GenerateSAPOrder;
                },

                getNote = function (pack, paymentRequired) {
                    var paymentRequiredMsg = 'A request for final processing information has been sent to your nominating supervisor. Once this information is received, your order will ship within 2-3 weeks.',
                        isTrophyMsg = 'Please allow 8 - 10 weeks for delivery',
                        notTrophyMsg = 'Merchandise orders generally ship next business day',
                        note = notTrophyMsg;

                    if (paymentRequired) {
                        note = paymentRequiredMsg;
                    } else if (!!pack && !pack.GenerateSAPOrder) {
                        note = isTrophyMsg;
                    }

                    return note;
                },

                convertDate = function (date) {
                    return Common.convertJsonDateString(date);
                },



                swapProductImage = function (product) {
                    if (!!product.selectedConfiguration) {
                        product.Image.urls.lg = getProductImage(product.selectedConfiguration, 'l');
                        product.Image.urls.md = getProductImage(product.selectedConfiguration, '');
                        product.Image.urls.sm = getProductImage(product.selectedConfiguration, 't');
                        product.Image.urls.xs = getProductImage(product.selectedConfiguration, 'tt');
                    }
                },

                rewardProductDiscontinuedFilter = function (child) {

                    if (child.IsDiscontinued && child.QtyAvailable <= 0) {
                        return false;
                    } else {
                        return true;
                    }

                },

                showAddressForm = function () {

                    var reward = $scope.reward,
                        modalInstance = $uibModal.open({
                            templateUrl: 'AddEditRewardShippingAddress.html',
                            controller: 'rewardShippingAddressCtrl as ctrl', //different controller
                            size: 'lg',
                            resolve: {
                                campaign: function () {
                                    return Campaign;
                                },
                                storeCode: function () {
                                    return $rootScope.store.StoreCode;
                                },
                                reward: function () {
                                    return {
                                        OverrideAddress: reward.OverrideAddress,
                                        EmailReplyToAddress: reward.EmailReplyToAddress,
                                        Name: reward.Name,
                                        ShipToAddress: $scope.shipToAddress,
                                        CustomerId: reward.CustomerId,
                                        RewardId: reward.RewardId
                                    };

                                },
                                scope: function () {
                                    return $scope;
                                }
                            }

                        }).result.then(function (shipToAddress) {
                            Common.showMessage('success', 'Address has been updated.');
                            $scope.shipToAddress = shipToAddress;
                        });
                };

            $scope.removeSelectedProduct = removeSelectedProduct;
            $scope.updateRemainingRedemptions = updateRemainingRedemptions;

            $scope.productUI = ProductUIService;
            $scope.rewardService = RewardService;
            $scope.reward = null;
            $scope.editName = false;

            $scope.products = [];

            $scope.rewardId = $routeParams.id;
            $scope.packId = $routeParams.packId;
            $scope.productId = !!$routeParams.productId ? JSON.parse($routeParams.productId) : null;

            $scope.pack = {};

            $scope.redeeming = false;


            $scope.linkTo = function (path) {
                return Common.linkTo(path);
            };

            $scope.swapProductImage = swapProductImage;
            $scope.convertDate = convertDate;
            $scope.isTrophy = isTrophy;
            $scope.getNote = getNote;
            $scope.redeemed = isRedeemed;
            $scope.redeemReward = redeemReward;
            $scope.redirectTo = redirectTo;
            $scope.redirectToSelectAward = redirectToSelectAward;
            $scope.canRedeem = canRedeem;

            $scope.showAddressForm = showAddressForm;


            $scope.toggleEdit = toggleEdit;
            $scope.cancelNameEdit = cancelNameEdit;
            $scope.prepareForNameEdit = prepareForNameEdit;

            $scope.productUI = ProductUIService;
            $scope.rewardProductDiscontinuedFilter = rewardProductDiscontinuedFilter;

            getReward($scope.rewardId);
            $scope.rewardService.getReward($scope.rewardId);
        }])

    .controller('rewardShippingAddressCtrl', [
        'Rewards',
        'Common',
        'Stores',
        'Objects',
        '$uibModalInstance',
        '$scope',
        'campaign',
        'storeCode',
        'reward',
        'scope',
        function (Rewards, Common, Stores, Objects, $uibModalInstance, $scope, campaign, storeCode, reward, scope) {

            var ctrl = this,

                init = function () {

                    //Do we actually have an address (just look at Address 1 to determine that)
                    if (!!reward.ShipToAddress && !!reward.ShipToAddress.Address1)
                        newAddress = angular.copy(reward.ShipToAddress);

                    exposeSelf();

                },


                newAddress = {
                    Name: '',
                    FirstName: '',
                    LastName: '',
                    Address1: '',
                    Address2: '',
                    City: '',
                    State: '',
                    PostalCode: '',
                    County: '',
                    CompanyName: '',
                    Country: 'US',
                    Email: '',
                    PhoneNumber: '',
                    PhoneExtension: ''
                },

                apiStoreCode = storeCode,


                exposeSelf = function () {

                    ctrl.newAddress = newAddress;

                    ctrl.reward = reward || {};

                    ctrl.saveAndUseAddress = saveAndUseAddress;

                    ctrl.cancelChanges = closeModal;

                    ctrl.countries = [];
                    ctrl.countriesLoading = true;
                    ctrl.showAdditionalShipToAddressFields = true;
                    Objects.getCountries({ type: 'Shipping' })
                        .then(function (response) {
                            ctrl.countriesLoading = false;
                            ctrl.countries = !!$scope.store.StoreCode && Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                        });

                    ctrl.states = [];
                    ctrl.originalCountry = ctrl.newAddress.Country;
                    Objects.getStateOrRegions({ country: ctrl.originalCountry })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    ctrl.onCountryChanged = onCountryChanged;
                    ctrl.selectOffice = selectOffice;



                    ctrl.close = closeModal;
                    ctrl.scope = scope;
                    ctrl.updateInProgress = false; //I'm doing this because $waiting isn't the best solution for this form.

                    //AR - Leaving in case we ever need to support the address lookup again.
                    ctrl.offices = [];
                    ctrl.officesLoading = false;
                    ctrl.officesPageNum = 1;
                    ctrl.officesTotalNum = 0;
                    ctrl.officesItemsPerPage = 6;
                },

                hideForm = function () {
                    closeModal();
                    ctrl.newAddress = newAddress;
                },

                onCountryChanged = function () {

                    //AR - 78050: All user to enter any address, not just US. I will leave this original code here in case this is something we need to add back in.
                    ctrl.newAddress.State = '';
                    Objects.getStateOrRegions({ country: ctrl.newAddress.Country })
                        .then(function (response) {
                            ctrl.states = response.data;
                        });

                    //AR - Leaving code that toggles between Address Entery form and Address Lookup. In case we ever need to support this again.
                    //if (ctrl.newAddress.Country != 'US') {
                    //    ctrl.officesLoading = true;
                    //    ctrl.officesPageNum = 1;
                    //    ctrl.officesTotalNum = 0;
                    //    Stores.searchAddresses(apiStoreCode, 'Office', "Country=" + ctrl.newAddress.Country)
                    //    .then(function (response) {
                    //        ctrl.officesLoading = false;
                    //        ctrl.officesTotalNum = response.data.length;
                    //        ctrl.offices = segmentize(response.data, ctrl.officesItemsPerPage);
                    //    });
                    //}
                    //else {
                    //    if (ctrl.originalCountry !== 'US')
                    //    {
                    //        //If the original address that we loaded was not US, then clear out the address fields
                    //        ctrl.newAddress = {
                    //            Address1: '',
                    //            Address2: '',
                    //            City: '',
                    //            State: '',
                    //            PostalCode: '',
                    //            County: '',
                    //            CompanyName: '',
                    //            Country: 'US',
                    //            Email: '',
                    //            PhoneNumber: '',
                    //            PhoneExtension: ''
                    //        }

                    //    }
                    //}

                },

                //AR - Leaving in case we ever need to support the address lookup again.
                segmentize = function (data, columns) {
                    var newData = [];

                    for (var i = 0; i < data.length; i = i + columns) {
                        newData.push(data.slice(i, i + columns));
                    }

                    return newData;
                },


                closeModal = function () {
                    $uibModalInstance.dismiss('cancel');
                },

                //AR - Leaving in case we ever need to support the address lookup again.
                selectOffice = function (selectedAddress) {

                    ctrl.updateInProgress = true;
                    var model = angular.copy(selectedAddress);
                    //Specify that it is a shipping address and use the existing ShipToName put the Name of the office as the CompanyName of the shipping address
                    model.AddressType = 'Shipping';
                    model.CompanyName = model.Name;
                    model.Name = reward.ShipToAddress.Name;
                    updateRewardAddress(reward, model);

                },

                saveAndUseAddress = function (form, newAddress) {

                    ctrl.updateInProgress = true;
                    campaign.getTaxJurisdiction(newAddress, form)
                        .then(function () {
                            if (form.$valid) {

                                var model = {
                                    'AddressType': 'Shipping',
                                    'Name': newAddress.FirstName + ' ' + newAddress.LastName, //newAddress.Name,
                                    'FirstName': newAddress.FirstName,
                                    'LastName': newAddress.LastName,
                                    'Address1': newAddress.Address1,
                                    'Address2': newAddress.Address2,
                                    'Country': newAddress.Country,
                                    'City': newAddress.City,
                                    'State': newAddress.State,
                                    'PostalCode': newAddress.PostalCode,
                                    'Email': newAddress.Email,
                                    'Phone': newAddress.Phone
                                };

                                updateRewardAddress(reward, model);

                            } else {
                                Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                                ctrl.updateInProgress = false;
                                //Common.hideLoader();
                            }
                        }, function () {
                            Common.showMessage('fail', 'Could not save shipping address. Please correct errors and try again.');
                            ctrl.updateInProgress = false;
                            //Common.hideLoader();
                        });

                },


                updateRewardAddress = function (reward, address) {
                    Rewards.updateRewardShippingAddress(reward.RewardId, address)
                        .then(function (response) {
                            $uibModalInstance.close(address);
                        },
                            function (message) {
                                ctrl.updateInProgress = false;
                                Common.showMessage('error', 'Error saving address.');
                            });

                };




            init();



        }])

    .controller('showRewardProductAdditionalInfoCtrl', [
        '$scope',
        'Common',
        '$uibModalInstance',
        'product',
        function ($scope, Common, $uibModalInstance, product) {

            var removeRecipient = function (recipient) {
                Campaign.removeRecipient(recipient);
                $uibModalInstance.close();
            };

            $scope.product = product;

            $scope.close = function () {
                $uibModalInstance.dismiss('cancel');
            };

        }]);


;(function () {
    'use strict';
    angular.module('ecs.reward-campaigns', []);
})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignWizardTabsCtrl', campaignWizardTabsCtrl);

    campaignWizardTabsCtrl.$inject = ['$scope', '$location', '$log', 'CampaignWizard', 'Common'];

    function campaignWizardTabsCtrl($scope, $location, $log, CampaignWizard, Common) {

        var init = function () {
            $scope.tabCampaign = CampaignWizard.currentCampaign;
            $scope.tabCampaignStatus = CampaignWizard.currentCampaignStatus;
            $scope.tabs = [{ step: 1, label: 'General', isSummary: false, title: 'Set up your ' + App.Session.RewardCampaignNamingConvention + ' Pack', goTo: $scope.goToGeneral },
                { step: 2, label: 'Owners', isSummary: false, title: 'Add other people that can edit, view, or upload recipients for this ' + App.Session.RewardCampaignNamingConvention + ' Pack.', goTo: $scope.goToOwners },
                { step: 3, label: 'Components', isSummary: false, title: 'Configure the components of your ' + App.Session.RewardCampaignNamingConvention + ' Pack.', goTo: $scope.goToComponents },
                { step: 4, label: 'Recipients', isSummary: false, title: 'Add recipients to your ' + App.Session.RewardCampaignNamingConvention + ' Pack.', goTo: $scope.goToRecipients },
                { step: 5, label: 'Communication', isSummary: false, title: 'Configure the communication settings of your ' + App.Session.RewardCampaignNamingConvention + ' Pack.', goTo: $scope.goToCommunication },
                            { step: 6, label: 'Summary', isSummary: true, title: 'Go to the summary page.', goTo: $scope.goToSummary }];


            var pathParts = $location.path().split("/");
            if (pathParts.length === 0)
                $scope.tabCampaignStep = undefined;

            var stepName = CampaignWizard.getCampaignWizardStep().toLowerCase();
            if (stepName === "general" || stepName === "owners" || stepName === "components" || stepName === "recipients" || stepName === "communication" || stepName === "summary")
                $scope.tabCampaignStep = stepName.charAt(0).toUpperCase() + stepName.slice(1);
        }

        var onCampaignWizardLoadStatus = function () {
            $scope.tabCampaign = CampaignWizard.currentCampaign;
            $scope.tabCampaignStatus = CampaignWizard.currentCampaignStatus;
        }

        $scope.goToCampaignListPage = function ($event) {
            if ($event)
                $event.preventDefault();

            CampaignWizard.goToCampaignList();
        }
        $scope.goToGeneral = function () {
            CampaignWizard.goToGeneral();
        }
        $scope.goToOwners = function () {
            CampaignWizard.goToOwners();
        }
        $scope.goToComponents = function () {
            CampaignWizard.goToComponents();
        }
        $scope.goToRecipients = function () {
            CampaignWizard.goToRecipients();
        }
        $scope.goToSummary = function () {
            CampaignWizard.goToSummary();
        }
        $scope.goToCommunication = function () {
            CampaignWizard.goToCommunication();
        }

        $scope.$on('onCampaignWizardLoadStatus', onCampaignWizardLoadStatus);

        init();

    }


})();
;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignsController', campaignsController);

    campaignsController.$inject = ['$uibModal', '$log', 'CampaignWizard', 'Common'];

    function campaignsController($uibModal, $log, CampaignWizard, Common) {
        var vm = this;
        vm.isBusy = false;
        vm.filterKeyword = "";
        vm.filterOwner = "";

        vm.searchCampaigns = searchCampaigns;
        vm.getCampaignStatus = getCampaignStatus;
        vm.createCampaign = createCampaign;
        vm.formatCampaignDate = formatCampaignDate;
        vm.loadCampaignDetails = loadCampaignDetails;
        vm.launchPack = launchPack;
        vm.cloneCampaign = cloneCampaign;
        vm.extendCampaign = extendCampaign;
        vm.sendReminder = sendReminder;
        vm.addException = addException;
        vm.getDaysLeft = getDaysLeft;
        vm.getRedeemedPercentage = getRedeemedPercentage;
        vm.goToDetails = goToDetails;
        vm.getEmailContent = getEmailContent;
        vm.goToSummary = goToSummary;
        vm.goToRecipients = goToRecipients;

        // Init
        vm.statusList = [
            { title: 'Recent Activity', value: "Status!=6,ModifiedDate>" + Common.getDateStringInPast(2, 0, 0) },
            { title: 'New', value: "Status=0" },
            { title: 'Pending Review', value: "Status=1" },
            { title: 'Review Complete', value: "Status=2" },
            { title: 'Pending PO Approval', value: "Status=3" },
            { title: 'Approved', value: "Status=4" },
            { title: 'Active', value: "Status=5" },
            { title: 'Completed', value: "Status=7" },
            { title: 'Cancelled', value: "Status=6" }
        ];

        vm.sortByList = [
           { title: 'Date last changed (Descending)', value: '-ModifiedDate' },
           { title: 'Start Date (Ascending)', value: 'LaunchDate' },
           { title: 'Start Date (Descending)', value: '-LaunchDate' },
           { title: 'End Date (Ascending)', value: 'ExpirationDate' },
           { title: 'End Date (Descending)', value: '-ExpirationDate' },
           { title: 'Create Date (Ascending)', value: 'CreateDate' },
           { title: 'Create Date (Descending)', value: '-CreateDate' }

        ];

        // Init
        vm.categoryList = [
            { title: 'All Reward Types', value: "" },
            { title: 'Retail Store Awards', value: "RewardCategory=Retail Store Awards" },
            { title: 'Impact Awards', value: "RewardCategory=Impact Award (formerly Ship-It Award)" }
        ];


        vm.filterStatus = vm.statusList[0];
        vm.sortBy = vm.sortByList[0];
        vm.filterCategory = vm.categoryList[0];


        // ---- PRIVATE IMPLEMENTATIONS
        function searchCampaigns($event) {
            if ($event)
                $event.preventDefault();

            vm.isBusy = true;
            var query = 'Name*=' + vm.filterKeyword + ','+ 'OwnerName*=' + vm.filterOwner + ','+ vm.filterStatus.value + ',' + vm.filterCategory.value;


            CampaignWizard.searchCampaigns(0, 1000, query)
                .then(function (response) {
                    vm.campaigns = response.data;
                    vm.isBusy = false;
                });
        }

        function loadCampaignDetails(c) {
            if (c.hasDetails) return;
            c.CampaignEmailContent = vm.getEmailContent(c);
            c.exceptionsAllowed = Math.round(c.ExceptionRecipientBuffer / 100 * c.NumberOfRecipients);

                
            if (c.NumberOfRecipients > 0) c.redeemedPercentage = vm.getRedeemedPercentage(c);
            //RedeemptionType of 1 is "Redeem online" and has the number of days to redeem
            if (c.RedeemptionType == 1){
                c.daysLeft = vm.getDaysLeft(c.ExpirationDate, c.DaysToRedeem);
                c.daysLeftVisible = false;
                //We'll only show the chart though once launch date has passed
                var dtLaunchDate = Common.convertJsonDateObject(c.LaunchDate)
                    , curDate = new Date();
                if (curDate > dtLaunchDate) 
                    c.daysLeftVisible = true;

            }
            c.hasDetails = true;
        }

        function getCampaignStatus(statusCode) {
            var statusList = vm.statusList.filter(function (c) {
                return c.value == statusCode;
            });

            return (statusList.length > 0) ? statusList[0].title : '';
        }

        function formatCampaignDate(dateStr) {
            if (!dateStr) return '';
            return Common.convertJsonDateString(dateStr, true);
        }

        function getComponentTileClass(type) {
            switch (type) {
                case 1: return "award";
                case 2: return "swag";
                case 3: return "award-or-swag";
                case 4: return "award-and-swag";
                default: return '';
            }
        }

        function extendCampaign($event, campaign) {
            if ($event)
                $event.preventDefault();

            var modalInstance = $uibModal.open({
                templateUrl: 'ExtendCampaign.html',
                controller: 'campaignExtendCtrl',
                resolve: {
                    campaignToExtend: function () {
                        return campaign;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (extension) {
                CampaignWizard.extendCampaign(extension.campaignIdToExtend, extension)
                     .then(function (response) {
                         Common.showMessage('success', 'Reward Pack successfully extended.');
                         campaign = loadCampaignDetails(response.data);
                     });
            });
        }

        function cloneCampaign($event, campaign) {
            if ($event)
                $event.preventDefault();

            var modalInstance = $uibModal.open({
                templateUrl: 'CloneCampaign.html',
                controller: 'campaignCloneCtrl',
                resolve: {
                    campaignToClone: function () {
                        return campaign;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (clone) {
                CampaignWizard.cloneCampaign(clone.campaignIdToClone, clone)
                    .then(function (response) {
                        CampaignWizard.setCurrentCampaign(response.data, true);
                        CampaignWizard.goToGeneral();
                    });
            });
        }

        function sendReminder($event, campaign) {
            if ($event) $event.preventDefault();

            var campaignReminderDto = {
                Action: 'SENDREMINDERS',
                Result: {}
            };

            CampaignWizard.sendCampaignReminder(campaign.CampaignId, campaignReminderDto)
                .then(function (response) {
                    Common.showMessage('Success',   response.data.Result.ReminderSent + ' Reminders have been sent!');
                },
                function (error) {
                    console.log('create campaign error', error);
                });
        }

        function addException($event, campaign) {
            if ($event)
                $event.preventDefault();

            CampaignWizard.setCurrentCampaign(campaign, true);
            CampaignWizard.goToRecipients();
        }

        function goToDetails($event, campaign) {
            if ($event)
                $event.preventDefault();

            CampaignWizard.setCurrentCampaign(campaign, true);
            if (campaign.Status > 0)
                CampaignWizard.goToSummary();
            else
                CampaignWizard.goToGeneral();
        }

        function launchPack() {
            CampaignWizard.goToCreateCampaign();
        };

        function createCampaign(c) {
            CampaignWizard.createCampaign(c)
                .then(function (response) {
                },
                function (error) {
                    console.log('create campaign error', error);
                });
        }

        // ------------------------ Helpers ------------------------
        function getRedeemedPercentage(c) {
            var p = parseFloat(c.NumberRedeemed / c.NumberOfRecipients * 100);
            return (p % 1 != 0) ? p.toFixed(2) : p;
        }

        function getDaysLeft(endDate, daysToRedeem) {
            if (!endDate) return 0;
            var d = Common.convertJsonDateObject(endDate);
            var timeDiff = d.getTime() -new Date().getTime();

            return (timeDiff > 0) ? Math.min(Math.ceil(timeDiff / (1000 * 3600 * 24)), daysToRedeem): 0;
        }

        function getEmailContent(c) {
            return "msrewards@ecompanystore.com?subject=Question about " + App.Session.RewardCampaignNamingConvention + " Pack - " +c.Name;
        }

        function clean(name) {
            return name.toLowerCase()
            .replace(/ /g, '-')
            .replace(/[^\w-]+/g, '');
        }

        function goToSummary($event, campaign) {
            if ($event)
                $event.preventDefault();

            CampaignWizard.setCurrentCampaign(campaign, true);
            CampaignWizard.goToSummary();
        }

        function goToRecipients($event, campaign, filter) {
            if ($event)
                $event.preventDefault();

            CampaignWizard.setCurrentCampaign(campaign, true);
            CampaignWizard.goToRecipients(filter);
        }

        //Go ahead and do an initial search
        searchCampaigns();
    };

    angular.module('ecs.reward-campaigns').controller('campaignCloneCtrl', ['$scope', '$uibModalInstance', 'Common', 'campaignToClone', function ($scope, $uibModalInstance, Common, campaignToClone) {

        var init = function (campaignToClone) {
            $scope.clone = {
                campaignIdToClone: campaignToClone.CampaignId,
                Name: campaignToClone.Name,
                OwnerAlias: '',
                ComponentFlag: 0,
                OwnerRole: 1,
                LaunchDate: campaignToClone.LaunchDate, //this is the weird JSON date format for MS WCF
                dtLaunchDate: Common.convertJsonDateObject(campaignToClone.LaunchDate), //convert it to a javascript date object
                datePickerOpened: false
            };

            $scope.launchDateCalSettings = {
                minDate: new Date()
            };
            $scope.launchDateCalSettings.minDate.setDate($scope.launchDateCalSettings.minDate.getDate() + 1);
            $scope.minimumDate = $scope.launchDateCalSettings.minDate;

            //Force it to the min date if the launch date is in the past.
            if ($scope.minimumDate > $scope.clone.dtLaunchDate) {
                $scope.clone.dtLaunchDate = $scope.minimumDate;
                $scope.clone.LaunchDate = Common.convertToJsonDateString($scope.minimumDate);
            }
        };

        $scope.cloneCampaign = function (form) {

            if ($scope.minimumDate > $scope.clone.dtLaunchDate) {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }
            else {
                if (form.$valid) {
                    //Convert the selected date to the JSON date format for MS WCF
                    $scope.clone.LaunchDate = Common.convertToJsonDateString($scope.clone.dtLaunchDate);
                    $uibModalInstance.close($scope.clone);

                } else {
                    Common.showMessage('error', 'Please enter a valid value for all required fields.');
                }
            }

        };

        $scope.roles = [
            {
                Role: 1,
                Name: 'Full Access'
            },
            {
                Role: 2,
                Name: 'Recipients Only'
            },
            {
                Role: 3,
                Name: 'Read Only'
            }
        ];

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };

        $scope.openDatePicker = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            $scope.clone.datePickerOpened = true;
        };

        init(campaignToClone);
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignExtendCtrl', ['$scope', '$uibModalInstance', 'Common', 'campaignToExtend', function ($scope, $uibModalInstance, Common, campaignToExtend) {

        var init = function (campaignToExtend) {
            $scope.extension = {
                campaignIdToExtend: campaignToExtend.CampaignId,
                currentExpDate: Common.convertJsonDateString(campaignToExtend.ExpirationDate, true),
                dtCurExpDate: Common.convertJsonDateObject(campaignToExtend.ExpirationDate), //convert it to a javascript date object
                dtNewExpDate: Common.convertJsonDateObject(campaignToExtend.ExpirationDate), //convert it to a javascript date object
                NumberOfDays: 0,
                datePickerOpened: false,
                SendReminders: true
            };

            $scope.expDateCalSettings = {
                minDate: $scope.extension.dtCurExpDate
            };
            $scope.expDateCalSettings.minDate.setDate($scope.expDateCalSettings.minDate.getDate() + 1);
            $scope.minimumDate = $scope.expDateCalSettings.minDate;
        };

        var daydiff = function (first, second) {
            return Math.round((second - first) / (1000 * 60 * 60 * 24))+1;
        }

        $scope.extendCampaign = function (form) {

            if (form.$valid) {
                $scope.extension.NumberOfDays = daydiff($scope.extension.dtCurExpDate, $scope.extension.dtNewExpDate);
                $uibModalInstance.close($scope.extension);

            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }

        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };

        $scope.openDatePicker = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            $scope.extension.datePickerOpened = true;
        };

        init(campaignToExtend);
    }]);

    angular.module('ecs.reward-campaigns').filter('campaignstatusfilter', function () {
        return function (status) {
            if (!!status || (status >=0 && status <=7)) {
                var campaignStatus = [
                  {
                      Status: 0,
                      Name: 'New'
                  },
                  {
                      Status: 1,
                      Name: 'Pending Review'
                  },
                  {
                      Status: 2,
                      Name: 'Review Complete'
                  },
                  {
                      Status: 3,
                      Name: 'Pending PO Approval'
                  },
                  {
                      Status: 4,
                      Name: 'Approved'
                  },
                  {
                      Status: 5,
                      Name: 'Active'
                  },
                  {
                      Status: 6,
                      Name: 'Cancelled'
                  },
                  {
                      Status: 7,
                      Name: 'Complete'
                  },

                ];


                return campaignStatus[status].Name;
            }
            return 'Unknown';
        };
    });

})();
;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignsTemplatesController', campaignsTemplatesController);

    campaignsTemplatesController.$inject = ['$scope', 'CampaignWizard', '$location'];

    function campaignsTemplatesController($scope, CampaignWizard, $location) {
        $scope.campaignTemplateCategories = null;

        CampaignWizard.getCampaignTemplateCategories()
            .then(function (response) {
                $scope.campaignTemplateCategories = response.data;
            });

        $scope.goToCreateCampaignGeneral = function () {
            CampaignWizard.goToGeneral();
        };
    };

    angular.module('ecs.reward-campaigns').controller('campaignTemplateItemsCtrl', ['$scope', 'CampaignWizard', function ($scope, CampaignWizard) {

        var getCampaignsforTemplate = function (skip, top, query) {
            $scope.campaigns = [];
            CampaignWizard.searchCampaigns(skip, top, query)
                .then(function (response) {
                    $scope.campaignTemplates = response.data;
                });
        };

        /* following has hardcoded values for testing purpose 
           to be fixed later. */
        $scope.cloneCampaign = function (campaign) {
            var cloneCampaign = {
                Name: campaign.Name,
                ComponentFlag: 0,
                LaunchDate: null
            };

            CampaignWizard.cloneCampaign(campaign.CampaignId, cloneCampaign)
                .then(function (response) {
                    $scope.newClonedCampaign = response.data;
                    CampaignWizard.setCurrentCampaign($scope.newClonedCampaign, true);
                    CampaignWizard.goToGeneral();
                });
        };

        //$scope.templateCategory is set by ng-int on each accordian data panel
        getCampaignsforTemplate(0, 100, 'IsTemplate=true,RewardCategory=' + $scope.template)
    }]);
})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateGeneralTabController', campaignCreateGeneralTabController);

    campaignCreateGeneralTabController.$inject = ['$scope', '$rootScope', '$uibModal', 'CampaignWizard', '$sce', '$location', '$routeParams', 'Common', 'FileUploader'];

    function campaignCreateGeneralTabController($scope, $rootScope, $uibModal, CampaignWizard, $sce, $location, $routeParams, Common, FileUploader) {

        var editMode = false;

        $scope.clonedCampaign = null;
        $scope.awardExceptions = false;
        $scope.campaign = {};
        $scope.launchDate = null;
        $scope.namingConvention = $rootScope.store.RewardCampaignNamingConvention;
        $scope.datePickerOpened = false;
        $scope.campaignNameTooltip = $sce.trustAsHtml('<b>Reward Pack Name</b><br />This is internal name for your ' + App.Session.RewardCampaignNamingConvention + ' Pack. Your recipients will not see this.');
        $scope.deliveryOptions = [{ flag: 1, label: 'Send to MS Mailroom' }, { flag: 2, label: 'Send to Subsidiary Office' }, { flag: 3, label: 'Send to Admin' }];

        var init = function () {

            $scope.launchDateCalSettings = {
                minDate: new Date()
            };
            $scope.launchDateCalSettings.minDate.setDate($scope.launchDateCalSettings.minDate.getDate() + 1);
            $scope.minimumDate = $scope.launchDateCalSettings.minDate;

            if (!!CampaignWizard.currentCampaign) {
                //because we will be editing this object, take a copy of it so that we don't update the object in the CampaignWizard
                $scope.clonedCampaign = angular.copy(CampaignWizard.currentCampaign);
                setupCampaignForEdit();
            }
            else {
                //No current campaign, try to load it from the path
                CampaignWizard.setCurrentCampaignByIdFromLocation()
                    .then(function (result) {
                        if (result) {
                            //because we will be editing this object, take a copy of it so that we don't update the object in the CampaignWizard
                            $scope.clonedCampaign = angular.copy(CampaignWizard.currentCampaign);
                            setupCampaignForEdit();
                        }
                        else //couldn't get it, then we're in create mode
                        {
                            setupCampaignForCreate();
                        }
                    });
            }

        };

        $scope.setExceptionRecipientBuffer = function () {
            if (!!$scope.awardExceptions) {
                $scope.clonedCampaign.ExceptionRecipientBuffer = 10;
            }
            else {
                $scope.clonedCampaign.ExceptionRecipientBuffer = null;
            }
        }

        var setupCampaignForEdit = function () {
            editMode = true;
            $scope.isDisabled = !CampaignWizard.canEditCampaign();

            if (!!$scope.clonedCampaign.LaunchDate)
                $scope.launchDate = Common.convertJsonDateObject($scope.clonedCampaign.LaunchDate)

            if ((!!$scope.clonedCampaign.ExceptionRecipientBuffer) && ($scope.clonedCampaign.ExceptionRecipientBuffer > 0)) {                
                $scope.awardExceptions = true;
            }

            if ($scope.clonedCampaign.namingConvention) {
                $scope.namingConvention = $scope.clonedCampaign.namingConvention;
            }

            $scope.clonedCampaign.ExceptionDefaultAddressFlag = null;
            $scope.clonedCampaign.ExceptionDefaultAddressAdminAlias = null;
            $scope.clonedCampaign.AllowExceptionWithManagerApproval = false;
            $scope.clonedCampaign.AllowExceptionWithAdminApproval = false;

        }

        //$scope.savePartialCampaign = function () {
        //    $scope.clonedCampaign.Recipients = [];
        //    CampaignWizard.createCampaign($scope.clonedCampaign)
        //        .then(function (response) {
        //            CampaignWizard.goToGeneralWithPartialCampaign();
        //        },
        //        function (error) {
        //            console.log('create campaign error', error);
        //        });
        //}

        var setupCampaignForCreate = function () {
            editMode = false;
            $scope.isDisabled = false;

            $scope.clonedCampaign = {};
            //Default values for new campaign
            $scope.clonedCampaign.DaysToRedeem = 14;
            $scope.clonedCampaign.PurposeType = 1;
            $scope.clonedCampaign.RedeemptionType = 1;
            $scope.clonedCampaign.ComponentType = 1;
            $scope.clonedCampaign.IsTemplate = 0;
            $scope.clonedCampaign.PurposeTypeAction = 'winning the';
            $scope.clonedCampaign.ExceptionDefaultAddressFlag = null;
            $scope.clonedCampaign.ExceptionDefaultAddressAdminAlias = null;
            $scope.clonedCampaign.AllowExceptionWithManagerApproval = false;
            $scope.clonedCampaign.AllowExceptionWithAdminApproval = false;
            $scope.clonedCampaign.EmailReplyToAddress = $scope.user.EmailAddress;
            $scope.clonedCampaign.SendLaunchEmail = 0
            $scope.clonedCampaign.TotalUnitsRedeemable = 1; //MRR specific

            //Default awardException to true
            $scope.awardExceptions = true;

            $scope.clonedCampaign.AuthenticationType = 1;

        }

        $scope.redemptionTypeSelection = function (value) {
            if (!$scope.isDisabled) {
                if (!editMode) {
                    $scope.clonedCampaign.RedeemptionType = value;
                }
                else {
             
                    //If changing to "Just send the award" and we already have packs defined on the award, have them confirm it
                    var campaignPacks = CampaignWizard.currentCampaignPacks;
                
                    if ($scope.clonedCampaign.RedeemptionType !== value && value === 2 && ($scope.clonedCampaign.ComponentType === 3) && (campaignPacks.SWAGProducts.length > 0)) {

                        var modalInstance = $uibModal.open({
                            templateUrl: 'ConfirmRedeemptionChange.html',
                            controller: 'campaignConfirmRedemptionTypeCtrl',

                        });

                        modalInstance.result.then(function (confirmed) {
                            if (confirmed) $scope.clonedCampaign.RedeemptionType = 2;
                        });
                    } else {
                        //No need to confirm it
                        $scope.clonedCampaign.RedeemptionType = value;
                    }

                }
            }

        };

        $scope.back = function () {
            CampaignWizard.goToCampaignList();
        };

        var createCampaign = function () {
            CampaignWizard.createCampaign($scope.clonedCampaign)
                .then(function (response) {
                    CampaignWizard.goToOwners();
                },
                function (error) {
                    console.log('create campaign error', error);
                });
        };

        $scope.validateDaysToRedeem = function (formControl) {
            if ($scope.clonedCampaign.RedeemptionType === 1 && formControl.$viewValue === "0") {
                formControl.$setValidity('minVal', false);
            }
            else {
                formControl.$setValidity('minVal', true);
            }
        };

        $scope.continueToSaveCampaign = function (form) {
            $scope.validateDaysToRedeem(form.DaysToRedeem);
            if ($scope.isDisabled) { //continue without saving
                CampaignWizard.goToOwners();
                return true;
            }

            if (form.$valid) {

                $scope.clonedCampaign.LaunchDate = Common.convertToJsonDateString($scope.launchDate);
                $scope.clonedCampaign.NamingConvention = $scope.namingConvention;

                if ($scope.clonedCampaign.RedeemptionType === 2) {
                    $scope.clonedCampaign.DaysToRedeem = null;
                    $scope.clonedCampaign.DaysLeftFirstReminder = null;
                    $scope.clonedCampaign.DaysLeftSecondReminder = null;
                } else {

                    //Set the reminder emails dates
                    $scope.clonedCampaign.DaysLeftFirstReminder = 1;
                    $scope.clonedCampaign.DaysLeftSecondReminder = null;
                    if ($scope.clonedCampaign.DaysToRedeem > 12) {
                        $scope.clonedCampaign.DaysLeftFirstReminder = 7;
                        $scope.clonedCampaign.DaysLeftSecondReminder = 2;
                    } else if ($scope.clonedCampaign.DaysToRedeem > 6) {
                        $scope.clonedCampaign.DaysLeftFirstReminder = 3;
                    } else if ($scope.clonedCampaign.DaysToRedeem > 3) {
                        $scope.clonedCampaign.DaysLeftFirstReminder = 2;
                    }

                }

                $scope.setExceptionRecipientBuffer();

                if (!editMode) {
                    $scope.clonedCampaign.Recipients = [];
                    createCampaign();
                }
                else {
                    updateCampaign();
                }
            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }
        };

        var updateCampaign = function () {
            CampaignWizard.updateCampaign($scope.clonedCampaign.CampaignId, $scope.clonedCampaign)
                .then(function (response) {
                    //$scope.campaign = response.data;                    
                    CampaignWizard.goToOwners();
                },
                function (error) {
                    console.log('update Campaign error', error);
                });
        };

        //$scope.isValidInput = function () {
        //    if (!!$scope.clonedCampaign.Name
        //        && !!$scope.clonedCampaign.RewardName
        //        && !!$scope.clonedCampaign.DepartmentName
        //        && !!$scope.clonedCampaign.Description
        //        && !!$scope.launchDate) {
        //        return true;
        //    }
        //    else {
        //        return false;
        //    }
        //}

        $scope.openDatePicker = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            $scope.datePickerOpened = true;
        };

        init();
    };

    angular.module('ecs.reward-campaigns').controller('campaignConfirmRedemptionTypeCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {

        $scope.confirmChange = function () {
            $uibModalInstance.close(true);
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateRecipientsTabController', campaignCreateRecipientsTabController);

    campaignCreateRecipientsTabController.$inject = ['$scope', '$uibModal', '$log', 'CampaignWizard', 'Campaigns', 'Common'];

    function campaignCreateRecipientsTabController($scope, $uibModal, $log, CampaignWizard, Campaigns, Common) {

        $scope.isDisabled = true;
        $scope.canEditReicipients = false;
        $scope.goBack = function () {
            CampaignWizard.goToComponents();
        };

        $scope.saveAndContinue = function () {
            CampaignWizard.goToCommunication();
        };

        $scope.setSortOption = function ($event, option) {
            if ($event)
                $event.preventDefault();

            $scope.selectedSort = option;

        };

        $scope.setDisplayOption = function ($event, option) {
            if ($event)
                $event.preventDefault();

            $scope.selectedDisplayOption = option;
            $scope.currentPage = 1;
            if (!!$scope.campaign)
                $scope.loadCampaignRecipients();

        };

        $scope.setFilter = function ($event, filter) {
            if ($event)
                $event.preventDefault();

            $scope.selectedFilter = filter;
            $scope.currentPage = 1;
            if (!!$scope.campaign)
                $scope.loadCampaignRecipients();
        };

        $scope.setItemsPerPage = function ($event, numItems) {
            if ($event)
                $event.preventDefault();

            $scope.itemsPerPage = numItems;
            if (!!$scope.campaign)
                $scope.loadCampaignRecipients();
        };

        $scope.pageChanged = function () {
            if (!!$scope.campaign)
                $scope.loadCampaignRecipients();
        };

        $scope.needsBase = function (recipient) {
            if (!!recipient && !!recipient.AwardOptionsJSON) {
                var awardOptions = JSON.parse(recipient.AwardOptionsJSON);

                if (!!awardOptions && !!awardOptions.NeedsBase && awardOptions.NeedsBase === "True")
                    return true;
            }

            return false;

        };

        $scope.confirmDelete = function (recipient) {

            var modalInstance = $uibModal.open({
                templateUrl: 'RemoveRecipient.html',
                controller: 'campaignRemoveRecipientsController',
                resolve: {
                    recipientToRemove: function () {
                        return recipient;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (recipient) {
                CampaignWizard.removeRecipient(recipient.CampaignId, recipient.CampaignRecipientId)
                    .then(function (response) {
                        Common.showMessage('success', 'Recipient successfully removed from ' + App.Session.RewardCampaignNamingConvention + ' Pack.');
                        $scope.loadCampaignRecipients();
                    });
            });
        };

        $scope.editRecipient = function (recipient) {

            var modalInstance = $uibModal.open({
                templateUrl: 'EditRecipient.html',
                controller: 'campaignEditRecipientsController',
                size: 'lg',
                resolve: {
                    recipientToEdit: function () {
                        return recipient;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (recipient) {
                $scope.loadCampaignRecipients();
            });
        };

        $scope.addRecipients = function () {

            var modalInstance = $uibModal.open({
                templateUrl: 'AddRecipients.html',
                controller: 'campaignAddRecipientsController',
                size: 'lg',
                resolve: {
                    campaignId: function () {
                        return $scope.campaign.CampaignId;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (type, recipient) {
                $log.info(type);
                $scope.loadCampaignRecipients(null, true); //specify the status on the recipients is dirty
            });
        };

        $scope.loadCampaignRecipients = function ($event, isDirty) {
            if ($event)
                $event.preventDefault();

            if (isDirty) {
                $scope.campaignStatus.stepsComplete['Recipients'].dirty = true;
            }
            //console.log('importstatus=' + $scope.selectedFilter + ',globalsearch=' + $scope.search.term + $scope.selectedDisplayOption.value);
            Campaigns.searchCampaignRecipients($scope.campaign.CampaignId, (($scope.currentPage - 1) * $scope.itemsPerPage), $scope.itemsPerPage, 'importstatus=' + $scope.selectedFilter + ',globalsearch=' + $scope.search.term + $scope.selectedDisplayOption.value)
                .then(function (response) {
                    $scope.campaignRecipients = response.data;
                });
        };



        $scope.sortOptions = [{ column: 'LastName', label: 'Last Name' }
            , { column: 'Email', label: 'Email Address' }
            , { column: 'Status', label: 'Status' }];

        $scope.displayOptions = [{ value: '', title: 'All' }
            , { value: ',RewardStatus=2', title: 'Redeemed' }
            , { value: ',RewardStatus!=2', title: 'Not Redeemed' }
            , { value: ',IsException=1', title: 'Exceptions' }];
        $scope.selectedSort = $scope.sortOptions[0];
        $scope.selectedDisplayOption = $scope.displayOptions[0];
        $scope.selectedFilter = 'DataComplete';
        $scope.search = {};
        $scope.search.term = '';
        $scope.currentPage = 1;
        $scope.itemsPerPage = 10;

        $scope.campaign = CampaignWizard.currentCampaign;
        $scope.campaignStatus = CampaignWizard.currentCampaignStatus;



        if (!$scope.campaign) {
            //Don't have it, get it from the path
            CampaignWizard.setCurrentCampaignByIdFromLocation()
                .then(function (result) {
                    if (result) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                        $scope.campaignStatus = CampaignWizard.currentCampaignStatus;
                        $scope.isDisabled = !CampaignWizard.canEditCampaign();
                        $scope.canEditReicipients = (CampaignWizard.canEditCampaign()) || (CampaignWizard.canAddExceptions());
                        $scope.loadCampaignRecipients();
                    }
                    else //couldn't get it
                    {
                        CampaignWizard.goToCampaignList();
                    }
                });
        }
        else {
            $scope.campaignStatus = CampaignWizard.currentCampaignStatus;
            $scope.isDisabled = !CampaignWizard.canEditCampaign();
            $scope.canEditReicipients = (CampaignWizard.canEditCampaign()) || (CampaignWizard.canAddExceptions());
            //Only do this if we have the current campaign
            var navFilter = CampaignWizard.getRecipientNavigationFilter();
            if ($scope.campaign.Status == 4 || $scope.campaign.Status == 5 || $scope.campaign.Status == 7) {
                if (navFilter == "redeemed")
                    $scope.selectedDisplayOption = $scope.displayOptions[1];
                if (navFilter == "exceptions")
                    $scope.selectedDisplayOption = $scope.displayOptions[3];
            }
            $scope.loadCampaignRecipients();
        }


    };

    angular.module('ecs.reward-campaigns').controller('campaignRemoveRecipientsController', ['$scope', '$uibModalInstance', 'recipientToRemove', function ($scope, $uibModalInstance, recipientToRemove) {

        $scope.removeRecipient = function (recipient) {
            $uibModalInstance.close(recipient);
        };
        $scope.recipient = recipientToRemove;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignAddRecipientsController', ['$scope', '$uibModalInstance', '$interval', '$log', 'Common', 'FileUploader', 'CampaignWizard', 'ImportFileProgress', 'campaignId', function ($scope, $uibModalInstance, $interval, $log, Common, FileUploader, CampaignWizard, ImportFileProgress, campaignId) {


        var init = function () {
            $scope.recipient = angular.copy($scope.defaultRecipient);
            CampaignWizard.getCountries('Shipping')
                .then(function (response) {
                    $scope.countries = Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                    $scope.shippingCountries = $scope.countries;
                });
            CampaignWizard.getStateOrRegions($scope.recipient.Country)
                .then(function (response) {
                    $scope.statesLoadedForCountry = $scope.recipient.Country;
                    $scope.states = response.data;
                });

        };


        $scope.defaultRecipient = {
            EmployeeId: '',
            Email: '',
            emailAlias: '',
            CompanyName: '',
            Address1: '',
            Address2: '',
            City: '',
            Region: 'WA',
            PostalCode: '',
            Country: 'US',
            FirstName: '',
            LastName: '',
            IsEmployee: true,
            DefaultAddressFlag: 1,
        };

        $scope.statesLoadedForCountry = '';
        $scope.recipientsAddedFlag = false;

        $scope.campaignId = campaignId;
        $scope.recipient = {};

        $scope.deliveryOptions = [{ flag: 1, label: 'Send to MS Mailroom (Redmond)' }, { flag: 2, label: 'Send to Subsidiary Office' }, { flag: 3, label: 'Send to Admin' }, { flag: 4, label: 'Send to Specific Address' }];
        //$scope.deliveryOptions = [{ flag: 1, label: 'Send to MS Mailroom' }];

        $scope.close = function () {

            if ($scope.recipientsAddedFlag)
                $uibModalInstance.close('refresh');
            else
                $uibModalInstance.dismiss('cancel');
        };

        $scope.addSingleRecipient = function (form, closeModal) {
            if (form.$valid) {

                if ($scope.recipient.IsEmployee) {
                    //If it's an employee, provide the email alias as the email
                    $scope.recipient.Email = $scope.recipient.emailAlias;
                }
                else {
                    //If its not an employee, the default address flag is always 4 (Send to Address)
                    $scope.recipient.DefaultAddressFlag = 4;
                    //Clear out fields not needed for non employee
                    $scope.recipient.EmployeeId = null;
                    $scope.recipient.AdminAlias = null;
                    $scope.recipient.ShipToName = null;
                }

                CampaignWizard.addRecipient($scope.campaignId, $scope.recipient)
                    .then(function (response) {
                        Common.showMessage('success', 'Recipient successfully added to ' + App.Session.RewardCampaignNamingConvention + ' Pack.');
                        $scope.recipientsAddedFlag = true;
                        if (closeModal)
                            $uibModalInstance.close('refresh');
                        else
                            $scope.recipient = angular.copy($scope.defaultRecipient);
                    });
            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }


        };

        $scope.onCountryChanged = function () {

            $scope.recipient.Region = '';
            if ($scope.recipient.Country == 'US' || $scope.recipient.Country == 'CA' || $scope.recipient.Country == 'BR') {

                if ($scope.statesLoadedForCountry !== $scope.recipient.Country) {
                    $scope.states = [];
                    CampaignWizard.getStateOrRegions($scope.recipient.Country)
                        .then(function (response) {
                            $scope.statesLoadedForCountry = $scope.recipient.Country;
                            $scope.states = response.data;
                        });
                }
            }

        };

        $scope.clearEmployeeOptionalValidation = function (recipientFormField) {
            recipientFormField.$setPristine();
        }

        $scope.emailPatternConditional = function () {
            var regexp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return {
                test: function (value) {
                    if ($scope.recipient.IsEmployee === 1) return true;
                    else return regexp.test(value);
                }
            };
        };

        $scope.resetUploader = function () {
            $scope.uploadError = false;
            $scope.uploadComplete = false;
            $scope.inProgress = false;
            $scope.uploadResponse = null;
            $scope.rowsImported = 0;
            $scope.rowTotal = 0;
        };

        $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignRecipients/" + campaignId, autoUpload: true });
        $scope.uploadError = false;
        $scope.inProgress = false;
        $scope.rowsImported = 0;
        $scope.rowTotal = 0;
        $scope.uploadComplete = false;

        $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
            $scope.inProgress = false;
            $scope.uploadError = true;
            $scope.uploadResponse = {};
            $scope.uploadResponse.criticalError = true;
        };

        $scope.uploader.onBeforeUploadItem = function (item) {
            $scope.inProgress = true;

        };

        $scope.uploader.onCompleteItem = function (item, response, status, headers) {
            $scope.inProgress = false;
            if (status === 200) {
                $scope.uploadResponse = response;
                if (response.ImportErrors.length === 0 && response.DataValidationErrors.length === 0) {
                    $scope.uploadError = false;
                    $scope.uploadComplete = true;
                    $scope.rowsImported = 0;
                    $scope.rowTotal = $scope.uploadResponse.TotalRows;
                    $scope.recipientsAddedFlag = true;

                    ImportFileProgress.onRowImport($scope.uploadResponse.FileId, function (rowStatus) {
                        $scope.rowsImported++;
                    });

                } else {
                    $scope.uploadError = true;
                }
            }
            $scope.$apply();
        };

        init();
    }]);


    angular.module('ecs.reward-campaigns').controller('campaignEditRecipientsController', ['$scope', '$uibModalInstance', '$interval', '$log', 'Common', 'FileUploader', 'CampaignWizard', 'recipientToEdit', function ($scope, $uibModalInstance, $interval, $log, Common, FileUploader, CampaignWizard, recipientToEdit) {


        var init = function (recipientToEdit) {
            $scope.recipient = angular.copy(recipientToEdit);
            $scope.recipient.emailAlias = null;
            $scope.recipient.UpdateFlags = 0; //0 = not updating employee id or alias
            if ($scope.recipient.IsEmployee) {
                //Don't have the employeeid or alias, then default this to allow them to update it.
                if (!$scope.recipient.IsEmployee || !$scope.recipient.Email)
                    $scope.recipient.UpdateFlags = 1;

                if (!!$scope.recipient.Email) {
                    var alaisMatch = $scope.recipient.Email.match(/^([^@]*)@/);
                    $scope.recipient.emailAlias = alaisMatch ? alaisMatch[1] : $scope.recipient.Email;
                }
            }

            $scope.originalRecipient = recipientToEdit;
            $scope.showBaseOption = (!!$scope.recipient.AwardOptionsJSON && $scope.recipient.AwardOptionsJSON.indexOf('NeedsBase') >= 0);
            $scope.recipient.needsBase = $scope.showBaseOption ? (JSON.parse($scope.recipient.AwardOptionsJSON).NeedsBase === "True") : false;

            CampaignWizard.getCountries('Shipping')
                .then(function (response) {
                    $scope.countries = Common.isMicrosoftStore($scope.store.StoreCode) ? response.data.filter(c => !Common.getEmbargoedCountries().includes(c.CountryCode)) : response.data;
                    $scope.shippingCountries = $scope.countries;
                });
            if (!!$scope.recipient.Country && $scope.recipient.Country !== '') {
                CampaignWizard.getStateOrRegions($scope.recipient.Country)
                    .then(function (response) {
                        $scope.statesLoadedForCountry = $scope.recipient.Country;
                        $scope.states = response.data;
                    });
            }
        };



        $scope.statesLoadedForCountry = '';
        $scope.recipient = {};
        $scope.originalRecipient = {};
        $scope.deliveryOptions = [{ flag: 1, label: 'Send to MS Mailroom (Redmond)' }, { flag: 2, label: 'Send to Subsidiary Office' }, { flag: 3, label: 'Send to Admin' }, { flag: 4, label: 'Send to Specific Address' }];


        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
        $scope.editRecipient = function (form) {

            if (form.$valid) {
                if ($scope.showBaseOption) {
                    var awardOptions = { NeedsBase: "False" };
                    if ($scope.recipient.needsBase)
                        awardOptions = { NeedsBase: "True" };

                    $scope.recipient.AwardOptionsJSON = JSON.stringify(awardOptions);
                }

                if ($scope.recipient.IsEmployee) {
                    if ($scope.recipient.UpdateFlags == 1) {
                        //If it's an employee and we specified Update Flag to update from Employee Id or Email Alais, provide the email alias as the email
                        $scope.recipient.Email = $scope.recipient.emailAlias;
                    }
                }
                else {
                    //If its not an employee, the default address flag is always 4 (Send to Address)
                    $scope.recipient.DefaultAddressFlag = 4;
                    //Clear out fields not needed for non employee
                    $scope.recipient.EmployeeId = null;
                    $scope.recipient.AdminAlias = null;
                    $scope.recipient.ShipToName = null;
                }

                CampaignWizard.updateRecipient($scope.recipient.CampaignId, $scope.recipient.CampaignRecipientId, $scope.recipient)
                    .then(function (response) {
                        Common.showMessage('success', 'Recipient successfully updated.');
                        $scope.originalRecipient = angular.copy($scope.recipient);
                        $uibModalInstance.close($scope.originalRecipient);

                    });

            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }


        };

        $scope.onCountryChanged = function () {

            $scope.recipient.Region = '';
            if ($scope.recipient.Country == 'US' || $scope.recipient.Country == 'CA' || $scope.recipient.Country == 'BR') {

                if ($scope.statesLoadedForCountry !== $scope.recipient.Country) {
                    $scope.states = [];
                    CampaignWizard.getStateOrRegions($scope.recipient.Country)
                        .then(function (response) {
                            $scope.statesLoadedForCountry = $scope.recipient.Country;
                            $scope.states = response.data;
                        });
                }
            }

        };


        $scope.emailPatternConditional = function () {
            var regexp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return {
                test: function (value) {
                    if ($scope.recipient.IsEmployee === 1) return true;
                    else return regexp.test(value);
                }
            };
        };


        init(recipientToEdit);
    }]);
})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateComponentsTabController', campaignCreateComponentsTabController);

    campaignCreateComponentsTabController.$inject = ['$scope', '$uibModal', 'CampaignWizard', 'Campaigns', 'Common', 'ProductUrlService', '$filter', 'Products', '$log'];

    function campaignCreateComponentsTabController($scope, $uibModal, CampaignWizard, Campaigns, Common, ProductUrlService, $filter, Products, $log) {

        $scope.campaign = {};
        $scope.validatePoints = null;
        $scope.validate = null;
        $scope.isDisabled = true;
        $scope.loadingChildProducts = false;
        $scope.showEditButton = true;
        $scope.currentChildProductName = null;

        $scope.UpdateDefaultProduct = true;

        var init = function () {

            if (!CampaignWizard.currentCampaign) {
                //Don't have it, get it from the path
                CampaignWizard.setCurrentCampaignByIdFromLocation()
                    .then(function (result) {
                        if (result) {
                            //because we will be editing this object, take a copy of it so that we don't update the object in the CampaignWizard
                            $scope.campaign = angular.copy(CampaignWizard.currentCampaign);
                            $scope.isDisabled = !CampaignWizard.canEditCampaign();
                            $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
                            setRedeemAsPointsInStore();
                        }
                        else //couldn't get it
                        {
                            CampaignWizard.goToCampaignList();
                        }
                    });
            }
            else {
                //because we will be editing this object, take a copy of it so that we don't update the object in the CampaignWizard
                $scope.campaign = angular.copy(CampaignWizard.currentCampaign);
                $scope.isDisabled = !CampaignWizard.canEditCampaign();
                $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
                setRedeemAsPointsInStore();
            }

            //DON'T PUT CODE HERE! IT NEEDS TO EXIST IN THE IF OR ELSE PATHS ABOVE WHERE WE SET $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
        };

        //DON'T UPDATE THE objConfigJson with properties that you need in the UI. You are updating the ACTUAL object that then get's saved in the campaign pack and in the database. 
        //ALSO, THERE IS OTHER CODE USES objConfigJSON!! WHEN YOU CHANGE A PROPERTY LIKE THIS IT BREAKS ALL THE OTHER CODE THAT USES IT
        //The long term fix is to update the JSON strings in the DB so that Required is not a string but a bool value, but we need to test that
        //for now, if you are checked for Required, look for Required === 'True'
        //var boolifyRequiredFields = function () {
        //    if (!!$scope.campaignPacks.AwardPack && !!$scope.campaignPacks.AwardPack.objConfigJSON.Lines) {                
        //        angular.forEach($scope.campaignPacks.AwardPack.objConfigJSON.Lines, function (Lines, index) {
        //            Lines.Required = Boolean(Lines.Required);
        //        });
        //    }
        //};

        var setRedeemAsPointsInStore = function () {
            if ($scope.campaign.RedeemAsPointsInStore == null) {
                $scope.campaign.RedeemAsPointsInStore = false;
            }
        }

        $scope.validate = function () {

            var errorMessage = '';
            var isValid = true;
            if (!$scope.campaign.Points || $scope.campaign.Points == '') {
                $scope.campaign.Points = 0;
            }
            //var redeemAsPoints = ($scope.campaign.RedeemAsPointsGiftCard || $scope.campaign.RedeemAsDonation);
            //if (redeemAsPoints && $scope.campaign.Points === 0) {
            //    errorMessage = 'Please provide the award points amount.';
            //    isValid = false;
            //}

            var redeemAsPoints = ($scope.campaign.RedeemAsDonation || $scope.campaign.RedeemAsPointsInStore);
            if ($scope.campaign.Points > 0 && !redeemAsPoints) {
                errorMessage = 'Please select a redemption option for the award points.';
                isValid = false;
            }

            if (redeemAsPoints && $scope.campaign.Points === 0) {
                if (errorMessage != '') {
                    errorMessage += '\n';
                }
                errorMessage = 'Please provide the amount of points available for this ' + App.Session.RewardCampaignNamingConvention + ' Pack.';
                isValid = false;
            }

            var charitiesValid = $scope.validateCharities();
            if (!charitiesValid) {
                if (errorMessage != '') {
                    errorMessage += '\n';
                }
                errorMessage += 'Please provide at least one charity to which the recipient can donate.';
                isValid = false;
            }
            if (!isValid) {
                Common.showMessage('error', errorMessage);
            }
            return isValid;
        };

        $scope.validateCharities = function () {
            if ($scope.campaign.RedeemAsDonation) {
                if ($scope.campaign.AvailableCharities != null) {
                    return ($scope.campaign.AvailableCharities.length > 0);
                }
                return false;
            }
            return true;
        };

        $scope.goBack = function () {
            CampaignWizard.goToOwners();
        };

        $scope.goToSWAGSearch = function () {
            //If it's Award AND SWAG, they have to configure the award first.
            if ($scope.campaign.ComponentType === 4 & !$scope.campaignPacks.AwardPack) {
                Common.showMessage('error', 'Sorry! You must first configure the Award before adding any SWAG.');
            }
            else {
                CampaignWizard.goToSWAGSearch();
            }
        };

        $scope.saveAndContinue = function () {

            if ($scope.isDisabled) {
                CampaignWizard.goToRecipients();
            }
            else if ($scope.validate()) {
                $scope.checkDonation();
                CampaignWizard.updateCampaign($scope.campaign.CampaignId, $scope.campaign)
                    .then(function (response) {
                        CampaignWizard.goToRecipients();
                    },
                    function (error) {
                        console.log('update Campaign error', error);
                    });
            }
        };

        $scope.setComponentType = function ($event, value) {
            if ($event)
                $event.preventDefault();

            //Do we need to confirm it first
            /*
                1. The component type did change, the new component type is 1 and the SWAG components have already been configured
                2. The component type did change, the new component type is 2 and the Award component has already been configured
                3. The component type did change, the new component type is 4 and the SWAG components have already been configured and the Award component HAS NOT already been configured
            */
            if (($scope.campaign.ComponentType !== value && value === 1 && $scope.campaignPacks.SWAGProducts.length > 0)
                || ($scope.campaign.ComponentType !== value && value === 2 && !!$scope.campaignPacks.AwardPack)
                || ($scope.campaign.ComponentType !== value && value === 4 && $scope.campaignPacks.SWAGProducts.length > 0 && !$scope.campaignPacks.AwardPack)

                ) {

                var modalInstance = $uibModal.open({
                    templateUrl: 'ConfirmComponentTypeChange.html',
                    controller: 'campaignConfirmComponentTypeController',
                    resolve: {
                        newValue: function () {
                            return value;
                        },
                        newCampaignPacks: function () {
                            return $scope.campaignPacks;
                        }
                    }

                });

                modalInstance.result.then(function (newValue) {
                    updateComponentType(newValue);
                });
            } else {
                //No need to confirm it, just update
                updateComponentType(value);
            }


        };

        var updateComponentType = function (value) {
            //Update the Component type right away (don't use the copy we have in scope as it could have changed)
            var campaign = CampaignWizard.currentCampaign;
            campaign.ComponentType = value;

            // 4 = Award and Swag; 2 products will be shipped
            if (value == 4) { 
                campaign.TotalUnitsRedeemable = 2;
            } else {
                campaign.TotalUnitsRedeemable = 1;
            }
            CampaignWizard.updateCampaign($scope.campaign.CampaignId, campaign)
                .then(function (response) {
                    //Get the campaign packs again
                    CampaignWizard.getPacks($scope.campaign.CampaignId)
                        .then(function (response) {
                            $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
                            //$scope.apply();
                        });

                    //Copy updated campaign back to scope (yup it will overwrite any changes we may have made, but didn't save. Oh well)
                    $scope.campaign = angular.copy(CampaignWizard.currentCampaign);

                },
                function (error) {
                    Common.showMessage('error', 'There was an error updating your ' + App.Session.RewardCampaignNamingConvention + ' Pack. Please try again.');
                });

        };

        $scope.checkDonation = function () {
            if (!$scope.campaign.RedeemAsDonation) {
                $scope.campaign.AvailableCharities = null;
            }
        };

        $scope.deleteCharity = function (c) {
            var index = $scope.campaign.AvailableCharities.indexOf(c);
            $scope.campaign.AvailableCharities.splice(index, 1);
        };

        $scope.addCharity = function () {
            $scope.campaign.AvailableCharities.push($scope.newCharity);
            $scope.newCharity = undefined;
        };

        $scope.editAward = function () {
            CampaignWizard.goToComponentAwards();
        }

        $scope.editSWAGProduct = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'EditSWAGProduct.html',
                controller: 'campaignEditSWAGProductController',
                size: 'lg',
                resolve: {
                    productToEdit: function () {
                        return product;
                    },
                    imagePath: function () {
                        return $scope.$appConfig.ProductImageBaseURL;
                    },
                }
            });

            //refresh the list
            modalInstance.result.then(function () {
                //Get packs from Wizard after the update
                $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
            });
        };

        $scope.confirmDelete = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'RemoveSWAGProduct.html',
                controller: 'campaignRemoveSWAGProductController',
                resolve: {
                    productToRemove: function () {
                        return product;
                    }
                }
            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (productToRemove) {
                var groupIndex = null;
                var productIndex = null;
                var found = false;

                var packToUpdate;
                if ($scope.campaign.ComponentType === 4)
                    packToUpdate = angular.copy($scope.campaignPacks.AwardPack);
                else
                    packToUpdate = angular.copy($scope.campaignPacks.SWAGPack);

                for (var i = 0; i < packToUpdate.Groups.length; i++) {
                    var group = packToUpdate.Groups[i];
                    if (group.CampaignPackGroupId === productToRemove.CampaignPackGroupId) {
                        for (var j = 0; j < group.Products.length; j++) {
                            var product = group.Products[j];
                            if (product.CampaignPackGroupProductId === productToRemove.CampaignPackGroupProductId) {
                                groupIndex = i;
                                productIndex = j;
                                found = true;
                                break;
                            }
                        }
                    }
                }
                if (found) {
                    packToUpdate.Groups[groupIndex].Products.splice(productIndex, 1);

                    CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                    .then(function (response) {
                        //Get packs from Wizard after the update
                        $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
                    });
                }
                else {
                    Common.showMessage('error', 'Something is amiss. We couldn\'t find the product to delete. Please try again.');
                }
            });

        };

        $scope.customizeSWAGProduct = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'CustomizeSWAGProduct.html',
                controller: 'campaignCustomizeSWAGProductController',
                size: 'lg',
                resolve: {
                    productToCustomize: function () {
                        return product;
                    },
                    imagePath: function () {
                        return $scope.$appConfig.ProductImageBaseURL;
                    },
                }
            });

            //refresh the list
            modalInstance.result.then(function () {
                //Get packs from Wizard after the update
                $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
            });
        };

        $scope.removeCustomizationFromSwagProduct = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'RemoveCustomization.html',
                controller: 'campaignRemoveCustomizationController',
                resolve: {
                    productToRemove: function () {
                        return product;
                    }
                }
            });

            modalInstance.result.then(function (productToRemove) {
                var found = false;

                var packToUpdate;
                if (CampaignWizard.currentCampaign.ComponentType === 4) //Award AND Swag all go under the Award Pack
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
                else
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.SWAGPack);

                for (var i = 0; i < packToUpdate.Groups.length; i++) {
                    var group = packToUpdate.Groups[i];
                    if (group.CampaignPackGroupId === productToRemove.CampaignPackGroupId) {
                        for (var j = 0; j < group.Products.length; j++) {
                            var product = group.Products[j];
                            if (product.CampaignPackGroupProductId == productToRemove.CampaignPackGroupProductId) {
                                product.Customization = null;
                                found = true;
                                break
                            }
                        }
                    }
                }
                if (found) {
                    CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                        .then(function (response) {
                            //Get packs from Wizard after the delete
                            $scope.campaignPacks = CampaignWizard.currentCampaignPacks;

                        });
                } else {
                    Common.showMessage('error', 'Something is a miss. We couldn\'t find the product to delete. Please try again.');
                }
            });
        };

        $scope.showCustomizationText = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'CustomizationText.html',
                controller: 'campaignCustomizationTextController',
                resolve: {
                    customization: function () {
                        return product.Customization;
                    }
                }
            });

            modalInstance.result.then(function () {

            });
        };

        $scope.showCustomizationComments = function (product) {
            var modalInstance = $uibModal.open({
                templateUrl: 'CustomizationComments.html',
                controller: 'campaignCustomizationCommentsController',
                resolve: {
                    customization: function () {
                        return product.Customization;
                    }
                }
            });

            modalInstance.result.then(function () {

            });
        };

        $scope.loadChildProducts = function (product) {
            $scope.loadingChildProducts = true;
            $scope.showEditButton = false;
            

            if (!product || !product.IsConfigurable) {
                $scope.childProducts = null;
                return;
            }

            $scope.childProducts = null;

            Products.getBackendChildProducts(product.ProductNumber).then(
                function (response) {
                    $scope.childProducts = response.data;
                    product.DefaultTemplateProductNumber = product.DefaultTemplateProductNumber == null ? $scope.childProducts[0].ProductNumber : product.DefaultTemplateProductNumber;
                    $scope.loadingChildProducts = false;
                    $scope.showDefaultProductButton = true;
                },
                function (message) {
                    $log.log('Error getting child products', message);
                });
        }

        $scope.setCurrentChildProductName = function (product) {
            if (!!product.DefaultTemplateProductNumber) {
                Products.getBackendChildProducts(product.ProductNumber).then(
                    function (response) {
                        if(!!response.data)
                        product.currentChildProductName = $filter('filter')(response.data, { ProductNumber: product.DefaultTemplateProductNumber })[0].Name;
                    },
                    function (message) {
                        $log.log('Error getting child products', message);
                    });
            }
        }

        $scope.hideChildProducts = function () {
            $scope.showDefaultProductButton = false;
            $scope.loadingChildProducts = false;
            $scope.showEditButton = true;
        }

        $scope.saveDefaultTemplateProduct = function (productToSave, OptionType) {

            var packToUpdate;
            if (CampaignWizard.currentCampaign.ComponentType === 4) //Award AND Swag all go under the Award Pack
                packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
            else
                packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.SWAGPack);

            for (var i = 0; i < packToUpdate.Groups.length; i++) {
                var group = packToUpdate.Groups[i];
                if (group.CampaignPackGroupId === productToSave.CampaignPackGroupId) {
                    for (var j = 0; j < group.Products.length; j++) {
                        var product = group.Products[j];
                        if (product.CampaignPackGroupProductId == productToSave.CampaignPackGroupProductId) {
                            product.DefaultTemplateProductNumber = productToSave.DefaultTemplateProductNumber;
                            product.DefaultTemplateOption = OptionType;
                            break
                        }
                    }
                }
            }

            CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                    .then(function (response) {
                        $scope.showDefaultProductButton = false;
                        $scope.childProducts = null;
                        $scope.showEditButton = true;
                    });
        }

        $scope.loadChildProductsToUpdate = function (product, OptionType) {
            if (!!product && !!product.IsConfigurable) {
                
                product.UpdateDefaultProduct = true;
                product.loadingChildProductsToUpdate = true;

                Products.getBackendChildProducts(product.ProductNumber).then(
                function (response) {
                    product.childProductsToUpdate = response.data;
                    product.DefaultTemplateProductNumber = product.childProductsToUpdate[0].ProductNumber;
                    product.loadingChildProductsToUpdate = false;
                    product.showDefaultProductButtonToUpdate = true;
                },
                function (message) {
                    $log.log('Error getting child products', message);
                });
            }
            else {
                $scope.updateDefaultTemplateProduct(product, OptionType);
            }
        }

        $scope.hideChildProductsToUpdate = function (product) {
            product.UpdateDefaultProduct = false;
            product.childProductsToUpdate = null;
            product.showDefaultProductButtonToUpdate = false;
            product.checkChild = null;
        }

        $scope.updateDefaultTemplateProduct = function (productToSave, OptionType) {

            var packToUpdate;
            if (CampaignWizard.currentCampaign.ComponentType === 4) //Award AND Swag all go under the Award Pack
                packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
            else
                packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.SWAGPack);

            for (var i = 0; i < packToUpdate.Groups.length; i++) {
                var group = packToUpdate.Groups[i];
                if (group.CampaignPackGroupId === productToSave.CampaignPackGroupId) {
                    for (var j = 0; j < group.Products.length; j++) {
                        var product = group.Products[j];
                        if (product.CampaignPackGroupProductId == productToSave.CampaignPackGroupProductId) {
                            product.DefaultTemplateProductNumber = productToSave.DefaultTemplateProductNumber;
                            product.DefaultTemplateOption = OptionType;
                            product.IsDefault = true;
                        }
                        else {
                            product.DefaultTemplateProductNumber = null;
                            product.DefaultTemplateOption = null;
                            product.IsDefault = false;
                        }
                    }
                }
            }

            CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                    .then(function (response) {
                        $scope.showDefaultProductButton = false;
                        $scope.childProducts = null;
                        $scope.showEditButton = true;
                    });
        }

        //call init function to set everything up
        init();
    };

    angular.module('ecs.reward-campaigns').controller('campaignEditSWAGProductController', ['$scope', '$uibModalInstance', '$interval', '$log', 'Common', 'CampaignWizard', 'productToEdit', 'imagePath', function ($scope, $uibModalInstance, $interval, $log, Common, CampaignWizard, productToEdit, imagePath) {

        var init = function (productToEdit, imagePath) {
            $scope.product = angular.copy(productToEdit);
            $scope.originalProduct = productToEdit;
            $scope.imagePath = imagePath;
        };

        $scope.product = {};
        $scope.originalProduct = {};

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };

        $scope.editProduct = function (form) {
            if (form.$valid) {

                var packToUpdate;
                if (CampaignWizard.currentCampaign.ComponentType === 4) //Award AND Swag all go under the Award Pack
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
                else
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.SWAGPack);

                for (var i = 0; i < packToUpdate.Groups.length; i++) {
                    var group = packToUpdate.Groups[i];
                    if (group.CampaignPackGroupId === $scope.product.CampaignPackGroupId) {
                        for (var j = 0; j < group.Products.length; j++) {
                            var product = group.Products[j];
                            if (product.CampaignPackGroupProductId == $scope.product.CampaignPackGroupProductId) {
                                product.ProductName = $scope.product.ProductName;
                                product.ProductDescription = $scope.product.ProductDescription;
                                break
                            }
                        }
                    }
                }
                CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                    .then(function (response) {
                        $uibModalInstance.close();
                    });
            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }
        };

        init(productToEdit, imagePath);
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignRemoveSWAGProductController', ['$scope', '$uibModalInstance', 'productToRemove', function ($scope, $uibModalInstance, productToRemove) {

        $scope.removeProduct = function (product) {
            $uibModalInstance.close(product);
        };

        $scope.product = productToRemove;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignConfirmComponentTypeController', ['$scope', '$uibModalInstance', 'newValue', 'newCampaignPacks', function ($scope, $uibModalInstance, newValue, newCampaignPacks) {
        $scope.newCampaignPacks = newCampaignPacks;
        $scope.newValue = newValue;
        $scope.ComponentName = null;

        if ($scope.newValue === 1) {
            $scope.ComponentName = "Just Award";
        }
        else if ($scope.newValue === 2) {
            $scope.ComponentName = "Just some SWAG";
        }
        else if ($scope.newValue === 4) {
            $scope.ComponentName = "Award AND SWAG";
        }
        $scope.confirmChange = function (value) {
            $uibModalInstance.close(value);
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignCustomizeSWAGProductController', ['$scope', '$uibModalInstance', '$interval', '$log', 'Common', 'CampaignWizard', 'productToCustomize', 'imagePath', 'FileUploader', function ($scope, $uibModalInstance, $interval, $log, Common, CampaignWizard, productToCustomize, imagePath, FileUploader) {

        var init = function (productToCustomize) {
            $scope.product = angular.copy(productToCustomize);
            $scope.originalProduct = productToCustomize;
            $scope.customization = productToCustomize.Customization;
            if (!$scope.customization) {
                $scope.customization = {};
            }
            if (!!$scope.customization) {
                $scope.customization.ArtworkFile = Boolean($scope.customization.ArtworkFile);
            }
            $scope.imagePath = imagePath;
            $scope.uploadFile();
            $scope.uploadFileMode = !$scope.customization.ArtworkFile;
        };

        $scope.product = {};
        $scope.originalProduct = {};
        $scope.customization = {};

        $scope.toggleCustomLogo = function () {
            if (!$scope.customization) {
                $scope.customization = {};
            }
            if ($scope.customization.CustomLogo) {
                $scope.customization.CustomLogo = false;
                $scope.customization.ArtworkFile = null;
                $scope.customization.ArtworkPreviewURL = null;
            }
            else {
                $scope.customization.CustomLogo = true;
            }
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };

        $scope.uploadFileMode = false;

        $scope.uploadFile = function () {
        
            $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignSWAGLogoArtwork/" + CampaignWizard.currentCampaign.CampaignId, autoUpload: true });
            $scope.uploadFileMode = true;
            $scope.uploadError = false;
            $scope.inProgress = false;
            $scope.uploadComplete = false;

            $scope.resetUploader = function () {
                $scope.uploadError = false;
                $scope.uploadComplete = false;
                $scope.inProgress = false;
                $scope.uploadResponse = null;
            };

            $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
                $scope.inProgress = false;
                $scope.uploadError = true;
                $scope.uploadResponse = {};
                $scope.uploadResponse.criticalError = true;
                console.log(status);
            };

            $scope.uploader.onBeforeUploadItem = function (item) {
                $scope.inProgress = true;
            };

            $scope.uploader.onCompleteItem = function (item, response, status, headers) {
                $scope.inProgress = false;
                
                if (status === 200) {
                    $scope.uploadResponse = response;
                    if (!$scope.customization) {
                        $scope.customization = {};
                    }
                    $scope.customization.ArtworkFile = response.OriginalArtworkFile;
                    $scope.customization.ArtworkPreviewURL = response.PreviewUrl;
                    
                    //$scope.config = $scope.clonedCampaign.LogoUrl + '?decache=' + Math.random();
                    $scope.uploadError = false;
                    $scope.uploadComplete = true;
                    $scope.uploadFileMode = false;
                } else {
                    $scope.uploadError = true;
                }
            };
        };

        $scope.customizeProduct = function (form) {
            if (form.$valid) {

                var packToUpdate;
                if (CampaignWizard.currentCampaign.ComponentType === 4) //Award AND Swag all go under the Award Pack
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
                else
                    packToUpdate = angular.copy(CampaignWizard.currentCampaignPacks.SWAGPack);

                for (var i = 0; i < packToUpdate.Groups.length; i++) {
                    var group = packToUpdate.Groups[i];
                    if (group.CampaignPackGroupId === $scope.product.CampaignPackGroupId) {
                        for (var j = 0; j < group.Products.length; j++) {
                            var product = group.Products[j];
                            if (product.CampaignPackGroupProductId == $scope.product.CampaignPackGroupProductId) {
                                var customization = product.Customization;
                                if (!customization)
                                {
                                    customization = { Text: "", ArtworkFile: "", Comments: "", CustomLogo: false, ArtworkPreviewURL : "", CampaignPackGroupProductId: null };
                                }
                                customization.CampaignPackGroupProductId = $scope.product.CampaignPackGroupProductId;
                                customization.Text = $scope.customization.Text;
                                customization.Comments = $scope.customization.Comments;
                                customization.ArtworkFile = $scope.customization.ArtworkFile;
                                customization.CustomLogo = $scope.customization.CustomLogo;
                                customization.ArtworkPreviewURL = $scope.customization.ArtworkPreviewURL;
                                product.Customization = customization;
                                break
                            }
                        }
                    }
                }
                CampaignWizard.updatePack(packToUpdate.CampaignId, packToUpdate.CampaignPackId, packToUpdate)
                    .then(function (response) {
                        $uibModalInstance.close();
                    });
            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }
        };

        init(productToCustomize, imagePath);
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignRemoveCustomizationController', ['$scope', '$uibModalInstance', 'CampaignWizard', 'productToRemove', function ($scope, $uibModalInstance, CampaignWizard, productToRemove) {
        $scope.product = productToRemove;

        $scope.removeCustomization = function (product) {
            $uibModalInstance.close(product);
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignCustomizationTextController', ['$scope', '$uibModalInstance', 'customization', function ($scope, $uibModalInstance, customization) {

        $scope.customization = customization;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignCustomizationCommentsController', ['$scope', '$uibModalInstance', 'customization', function ($scope, $uibModalInstance, customization) {

        $scope.customization = customization;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);
})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateSummaryTabCtrl', campaignCreateSummaryTabCtrl);

    campaignCreateSummaryTabCtrl.$inject = ['$scope', '$uibModal', '$log', 'CampaignWizard', 'Campaigns', 'Common'];

    function campaignCreateSummaryTabCtrl($scope, $uibModal, $log, CampaignWizard, Campaigns, Common) {

        $scope.campaign = CampaignWizard.currentCampaign;
        $scope.campaignStatus = CampaignWizard.currentCampaignStatus;
        $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
        $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
        $scope.isDisabled = !CampaignWizard.canEditCampaign();
        var init = function () {

            if (!$scope.campaign) {
                //Don't have it, get it from the path
                CampaignWizard.setCurrentCampaignByIdFromLocation()
                    .then(function (result) {
                        if (result) {
                            $scope.campaign = CampaignWizard.currentCampaign;
                            $scope.campaignStatus = CampaignWizard.currentCampaignStatus;
                            $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
                            $scope.campaignPacks = CampaignWizard.currentCampaignPacks;
                            $scope.getCampaignFees();
                        }
                        else //couldn't get it
                        {
                            CampaignWizard.goToCampaignList();
                        }
                    });
            }
            else {
                $scope.getCampaignFees();
            } 

        };

        $scope.goToGeneral = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToGeneral();
        };
        $scope.goToOwners = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToOwners();
        };
        $scope.goToComponents = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToComponents();
        };
        $scope.goToRecipients = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToRecipients();
        };
        $scope.goToCommunication = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToCommunication();
        };

        $scope.onSubmitForReview = function () {
            CampaignWizard.submitForReview($scope.campaign.CampaignId)
                .then(function (response) {
                    $scope.campaign = CampaignWizard.currentCampaign;
                    $scope.getCampaignFees();
                });
        };

        $scope.onLaunch = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'launch';
                    }
                }

            });

            modalInstance.result.then(function () {
                CampaignWizard.launchCampaign($scope.campaign.CampaignId)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                    });
            });

        };

        $scope.onSubmitForPOApproval = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'poapproval';
                    }
                }

            });

            modalInstance.result.then(function () {
                CampaignWizard.submitForPOApproval($scope.campaign.CampaignId)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                        $scope.$goPunchoutCampaign($scope.campaign.CampaignId);
                    });
            });

        };

        $scope.onCancel = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'cancel';
                    }
                }

            });

            modalInstance.result.then(function () {
                CampaignWizard.cancelCampaign($scope.campaign.CampaignId)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                    });
            });

            
        };

        $scope.onUnlock = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'unlock';
                    }
                }

            });

            modalInstance.result.then(function () {
                var campaignToUpdate = angular.copy($scope.campaign);
                campaignToUpdate.Status = 0;
                CampaignWizard.updateCampaign(campaignToUpdate.CampaignId, campaignToUpdate)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                        calcTotals();
                    });
            });

            
        };
        $scope.onReviewComplete = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'reviewcomplete';
                    }
                }

            });

            modalInstance.result.then(function () {
                CampaignWizard.submitReviewComplete($scope.campaign.CampaignId)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                    });
            });


        };
        $scope.onRewardComplete = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ConfirmSummaryAction.html',
                controller: 'campaignSummaryConfirmActionController',
                resolve: {
                    type: function () {
                        return 'rewardcomplete';
                    }
                }

            });

            modalInstance.result.then(function () {
                var campaignToUpdate = angular.copy($scope.campaign);
                campaignToUpdate.Status = 7;
                CampaignWizard.updateCampaign(campaignToUpdate.CampaignId, campaignToUpdate)
                    .then(function (response) {
                        $scope.campaign = CampaignWizard.currentCampaign;
                        calcTotals();
                    });
            });


        };
        $scope.onUpdateCampaignWithPO = function () {

            if (!!$scope.campaign.PONumber && $scope.campaign.PONumber !== '') {
                CampaignWizard.updateCampaign($scope.campaign.CampaignId, $scope.campaign)
                .then(function (response) {
                    $scope.campaign = CampaignWizard.currentCampaign;
                    $scope.updatePOValidationError = false;
                    calcTotals();
                });

            }
            else {
                $scope.updatePOValidationError = true;
            }
        };

        $scope.getCampaignFees = function () {
            CampaignWizard.getFees($scope.campaign.CampaignId)
                .then(function (response) {
                    $scope.campaignFees = response.data;
                    calcTotals();
                });
        };

        var calcTotals = function () {

            var exceptionRecipients = Math.round($scope.campaign.ExceptionRecipientBuffer / 100 * $scope.campaign.NumberOfRecipients);
            $scope.campaign.budgetExceptionRecipients = exceptionRecipients;

            var recipientCount = $scope.campaign.NumberOfRecipients;
            if (!!$scope.campaign.ExceptionRecipientBuffer)
                recipientCount += exceptionRecipients;

            $scope.campaign.budgetSubTotal = ($scope.campaign.RewardAmount * recipientCount);
            $scope.campaign.budgetTotal = $scope.campaign.budgetSubTotal;
            for (var i = 0; i < $scope.campaignFees.length; i++) {
                $scope.campaign.budgetTotal += $scope.campaignFees[i].TotalAmount;
            }

        }

        $scope.generalVisible = false;
        $scope.ownersVisible = false;
        $scope.componentsVisible = false;
        $scope.recipientsVisible = false;
        $scope.communicationsVisible = false;
        $scope.updatePOValidationError = false;


        init();
    };

    angular.module('ecs.reward-campaigns').controller('campaignSummaryConfirmActionController', ['$scope', '$uibModalInstance', 'type', function ($scope, $uibModalInstance, type) {

        $scope.confirm = function () {
            $uibModalInstance.close();
        };
        $scope.type = type;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('ctrlCampaignCreateOwnersTab', ctrlCampaignCreateOwnersTab);

    ctrlCampaignCreateOwnersTab.$inject = ['$scope','$uibModal', '$log', 'CampaignWizard',  'Common'];

    function ctrlCampaignCreateOwnersTab($scope, $uibModal, $log, CampaignWizard, Common) {
        /* jshint validthis:true */
        $scope.campaignOwners = [];
        $scope.campaignOwnersRoles = [
            {
                RoleId:1,
                Name:'Full Access'
            },
            {
                RoleId:2,
                Name:'Recipients Only'
            },
            {
                RoleId:3,
                Name:'Read Only'
            }

        ];     
            
        $scope.newOwner = { AliasName: '', RoleId: 1 };
        $scope.isDisabled = function () {
            return !CampaignWizard.canEditCampaign();
        };
  
        $scope.getOwners = function (campaingid) {
            CampaignWizard.getCampaignOwners(campaingid)
                .then(function () {
                    $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
                });
        };

        $scope.addOwner = function (owner) {
                      
            var newOwner = {
                "AliasName": owner.AliasName,
                "CampaignId": $scope.campaign.CampaignId,
                "Role": owner.RoleId,
            }
            CampaignWizard.addCampaignOwner($scope.campaign.CampaignId, newOwner)
               .then(function () {
                   Common.showMessage('success', 'Owner successfully added to ' + App.Session.RewardCampaignNamingConvention + ' Pack.');
                   $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
               }, function () {
                   Common.showMessage('failure', 'Owner cannot be added. Check if the email alias is valid');
                   $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
               });
        }

        $scope.confirmDelete = function (owner) {

            var modalInstance = $uibModal.open({
                templateUrl: 'RemoveOwner.html',
                controller: 'campaignRemoveOwnerController',
                resolve: {
                    ownerToRemove: function () {
                        return owner;
                    }
                }

            });

            //If confirmed, delete the recipient and refresh the list
            modalInstance.result.then(function (owner) {
                CampaignWizard.removeCampaignOwner($scope.campaign.CampaignId, owner.CampaignOwnerId)
                .then(function (response) {
                    Common.showMessage('success', 'Owner successfully deleted from ' + App.Session.RewardCampaignNamingConvention + ' Pack.');
                    $scope.getOwners($scope.campaign.CampaignId);
                });
            });
        }

        $scope.campaign = CampaignWizard.currentCampaign;
        $scope.campaignOwners = CampaignWizard.currentCampaignOwners;
        $scope.goBack = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToGeneral();
        }
        $scope.saveAndContinue = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToComponents();
        }
        activate();

        function activate() {
            if (!$scope.campaign) {
                //Don't have it, get it from the path
                CampaignWizard.setCurrentCampaignByIdFromLocation()
                    .then(function (result) {
                        if (result) {
                            $scope.campaign = CampaignWizard.currentCampaign;
                            $scope.getOwners($scope.campaign.CampaignId);
                        }
                        else //couldn't get it
                        {
                            CampaignWizard.goToCampaignList();
                        }
                    });
            }
            else if (!$scope.campaignOwners) {
                $scope.getOwners($scope.campaign.CampaignId);
            }
        }
    }

    
    angular.module('ecs.reward-campaigns').controller('campaignRemoveOwnerController', ['$scope', '$uibModalInstance', 'ownerToRemove', function ($scope, $uibModalInstance, ownerToRemove) {

        $scope.removeOwner = function (owner) {
            $uibModalInstance.close(owner);
        };
        $scope.owner = ownerToRemove;

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

    angular.module('ecs.reward-campaigns').filter('rolefilter', function () {
        return function (roleId) {
            if (!!roleId) {
                var roles = [
                  {
                      RoleId: 1,
                      Name: 'Full Access'
                  },
                  {
                      RoleId: 2,
                      Name: 'Recipients Only'
                  },
                  {
                      RoleId: 3,
                      Name: 'Read Only'
                  }

                ];
                return roles[roleId - 1].Name;
            }
            return '';
        };
    });
})();
;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateComponentAwardsController', campaignCreateComponentAwardsController);

    campaignCreateComponentAwardsController.$inject = ['$scope', 'CampaignWizard', '$filter','Common', 'FileUploader'];

    function campaignCreateComponentAwardsController($scope, CampaignWizard, $filter, Common, FileUploader) {

        $scope.typeaheadProductType = ['Windows', 'Office', 'Bing', 'Xbox One', 'Visual Studio', 'SQL Server', 'Dynamics AX'];

        $scope.awardPack = null;
        $scope.availableTrophies = null;
        $scope.trophyName = null;
        $scope.trophy = null;
        $scope.configJSON = null;
        $scope.customDescription = null;
        $scope.datePickerOpened = false;
        $scope.uploadFileMode = false;
        $scope.uploader = new FileUploader();
        $scope.isPersonalized = false;
       

        $scope.uploadFile = function () {
            
            $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignAwardArtwork/" + CampaignWizard.currentCampaign.CampaignId, autoUpload: true });
            $scope.uploadFileMode = true;
            $scope.uploadError = false;
            $scope.inProgress = false;
            $scope.uploadComplete = false;

            $scope.resetUploader = function () {
                $scope.uploadError = false;
                $scope.uploadComplete = false;
                $scope.inProgress = false;
                $scope.uploadResponse = null;
            };

            $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
    
                $scope.inProgress = false;
                $scope.uploadError = true;
                $scope.uploadResponse = {};
                $scope.uploadResponse.criticalError = true;
            };

            $scope.uploader.onBeforeUploadItem = function (item) {
               
                $scope.inProgress = true;
            };

            $scope.uploader.onCompleteItem = function (item, response, status, headers) {
               
                $scope.inProgress = false;
                if (status === 200) {
                    $scope.uploadResponse = response;
                    $scope.configJSON.CustomArtWorkFile = response.OriginalArtworkFile;
                    $scope.configJSON.CustomArtworkPreviewURL = response.PreviewUrl;
                    $scope.uploadError = false;
                    $scope.uploadComplete = true;
                    $scope.uploadFileMode = false;
                } else {
                    $scope.uploadError = true;
                }
            };
        };

        $scope.goBack = function () {
            CampaignWizard.goToComponents();
        };

        $scope.toggleCustomArtwork = function () {
         
            if ($scope.configJSON.CustomArtwork) {
                $scope.configJSON.CustomArtwork = false;
                $scope.configJSON.CustomArtworkPreviewURL = null;
                $scope.configJSON.CustomArtWorkFile = null;
            }
            else {
                $scope.configJSON.CustomArtwork = true;
            }
        };

        var init = function () {

            //If we don't have the current campaign or packs, get back to the list
            if (!CampaignWizard.currentCampaign || !CampaignWizard.currentCampaignPacks)
                CampaignWizard.goToCampaignList();

            $scope.awardPack = null;
            if (!!CampaignWizard.currentCampaignPacks.AwardPack) {
                //Edit mode
                setEditMode();
        
                
            } else {
                //Add mode
                setAddMode();
            }
            
            $scope.uploadFile();
            $scope.uploadFileMode = !$scope.awardPack;

        };

        var setEditMode = function () {
            //Take a copy of our current award pack so we don't change the one in the wizard shared with other pages
            $scope.awardPack = angular.copy(CampaignWizard.currentCampaignPacks.AwardPack);
            setInitialTrophyFromPack($scope.awardPack);
            $scope.customDescription = $scope.awardPack.TrophyType == 3 ? $scope.awardPack.Description : '';
            getIsPersonalizedValue($scope.awardPack);
            //$scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignAwardArtwork/" + CampaignWizard.currentCampaign.CampaignId, autoUpload: true });
            //$scope.uploadFile();
            //$scope.uploadFileMode = !$scope.awardPack;
        };

        var setAddMode = function () {
            //Get the available trophies
            $scope.getAvailableTrophies();
            $scope.customDescription = '';
        }

        var setInitialTrophyFromPack = function (selectedTrophyPack) {
            //Create the trophy from the current pack and the add it to the availableTrophies array
            var currentTrophy = {
                TrophyId: selectedTrophyPack.TrophyId,
                Name: selectedTrophyPack.Name,
                ImageUrl: selectedTrophyPack.TrophyImageURL,
                Type: selectedTrophyPack.TrophyType,
                CampaignPackDescription: selectedTrophyPack.Description,
                objConfigJson: selectedTrophyPack.objConfigJSON,
                isVisible: true,
                isCurrent: true
            };
            $scope.availableTrophies = [currentTrophy];

            $scope.setSelectedTrophy(currentTrophy);
        };        

        $scope.getAvailableTrophies = function () {
            CampaignWizard.getCampaignTrophies()
            .then(function (response) {
                $scope.availableTrophies = response.data;

                var currentTrophy = $scope.availableTrophies[0];
                currentTrophy.isCurrent = true;

                $scope.setSelectedTrophy(currentTrophy);

            },
            function (error) {
                console.log(error);
            });
        }

        $scope.switchTrophy = function (trophy) {
            if (!!$scope.awardPack) {
                //Edit mode, don't do anything
                return;
            }

            angular.forEach($scope.availableTrophies, function (t, index) {
                if (trophy.TrophyId == t.TrophyId)
                    t.isCurrent = true;
                else
                    t.isCurrent = false;
            });

            $scope.setSelectedTrophy(trophy);
        };

        $scope.setSelectedTrophy = function (trophy) {
            $scope.trophy = trophy;
            $scope.configJSON = !!trophy.objConfigJson ? trophy.objConfigJson : JSON.parse(trophy.ConfigJSON);
            $scope.configJSON.CanBePersonalized = Boolean($scope.configJSON.CanBePersonalized);
            if (!!$scope.configJSON.RTM) {
                $scope.configJSON.RTM = new Date($scope.configJSON.RTM);
            }
        };

        var setupNewTrophyPack = function (campaign, trophy) {
            var newTrophyPack = {
                "CampaignId": campaign.CampaignId,
                "Name": trophy.Name,
                "IsDefault": "true",
                "Description": (trophy.Type != 3) ? (!!trophy.CampaignPackDescription ? trophy.CampaignPackDescription : trophy.Name) : $scope.customDescription,
                "GenerateSAPOrder": "false",
                "Type": "1",
                "TrophyId": trophy.TrophyId,
                "Groups": [{
                    "Name": !!trophy.CampaignPackDescription ? trophy.CampaignPackDescription : trophy.Name,
                    "DisplayOrder": "1",
                    "Type": "1",
                    Products: [{
                        "ProductNumber": trophy.ProductNumber,
                        "ProductName": trophy.Name,
                        "IsDefault": "true",
                        "IsPersonalized": trophy.Type === 2 ? $scope.isPersonalized : (!!$scope.configJSON.CanBePersonalized && $scope.configJSON.CanBePersonalized ? true : false),
                        "IsConfigurable": "false",
                        "ProductDescription": trophy.Name,
                        "Amount": trophy.Amount,
                        "ConfigJson": (trophy.Type != 3) ? JSON.stringify($scope.configJSON) : null
                    }]
                }]
            };

            return newTrophyPack;
        };

        var getIsPersonalizedValue = function (selectedTrophyPack) {
            for (var i = 0; i < selectedTrophyPack.Groups.length; i++) {
                var group = selectedTrophyPack.Groups[i];
                for (var j = 0; j < group.Products.length; j++) {
                    if (group.Type === 1) {
                        var product = group.Products[j];
                        $scope.isPersonalized = product.IsPersonalized;
                    }
                }
            }
        };

        $scope.attachTrophy = function (form) {

            if (form.$valid) {
                if (!!$scope.awardPack) {
                    //Edit mode


                    if ($scope.awardPack.TrophyType != 3) {
                        if (!!$scope.configJSON) {
                            //Loop through the groups in our award pack to make sure we're setting the product on the award group
                            //For campaigns with Award AND Swag, we'll have multiple groups of different types
                            for (var i = 0; i < $scope.awardPack.Groups.length; i++) {
                                var group = $scope.awardPack.Groups[i];
                                if (group.Type === 1) {
                                    var product = group.Products[0].ConfigJson = JSON.stringify($scope.configJSON);
                                    group.Products[0].IsPersonalized = $scope.isPersonalized;
                                }
                            }
                        }
                    }
                    else {
                        $scope.awardPack.Description = $scope.customDescription;
                    }

                    CampaignWizard.updatePack(CampaignWizard.currentCampaign.CampaignId, $scope.awardPack.CampaignPackId, $scope.awardPack)
                        .then(function (response) {
                            if (!CampaignWizard.currentCampaign.LogoUrl) {
                                CampaignWizard.setCurrentCampainLogoUrlIfNull(response.data.CampaignId).then(function (response) {
                                    CampaignWizard.goToComponents();
                                });
                            }
                            else {
                                CampaignWizard.goToComponents();
                            }
                        });
                }
                else {

                    $scope.awardPack = setupNewTrophyPack(CampaignWizard.currentCampaign, $scope.trophy);
                    CampaignWizard.addPack(CampaignWizard.currentCampaign.CampaignId, $scope.awardPack)
                        .then(function (response) {
                            if (!CampaignWizard.currentCampaign.LogoUrl) {
                                CampaignWizard.setCurrentCampainLogoUrlIfNull(response.data.CampaignId).then(function (response) {
                                    CampaignWizard.goToComponents();
                                });
                            }
                            else {
                                CampaignWizard.goToComponents();
                            }
                        });
                }
            }
            else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }
        }

        $scope.openDatePicker = function ($event) {
            $event.preventDefault();
            $event.stopPropagation();
            $scope.datePickerOpened = true;
        };

        init();
    }
})();;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateSwagSearchTab', campaignCreateSwagSearchTab);


    campaignCreateSwagSearchTab.$inject = ['$scope', '$rootScope', '$uibModal', '$timeout', 'Products', '$log', 'CampaignWizard', 'Campaigns', 'Common', '$filter'];

    function campaignCreateSwagSearchTab($scope, $rootScope, $uibModal, $timeout, Products, $log, CampaignWizard, Campaigns, Common, $filter) {

        /* jshint validthis:true */
        var facetsObj = {};

        var init = function () {

            //If we don't have the current campaign or packs, get back to the list
            if (!CampaignWizard.currentCampaign || !CampaignWizard.currentCampaignPacks)
                CampaignWizard.goToCampaignList();

            $scope.campaign = CampaignWizard.currentCampaign;
            $scope.campaignPacks = CampaignWizard.currentCampaignPacks;

            getItems();
        };



        //display Search results
        var displayResults = function (append, order) {
            $scope.noResults = false;
            $scope.initialSearch = false;
            $scope.lastSearchTerm = $scope.searchTerm;
            if (!$scope.searchResults) {
                $scope.noResults = true;
                return;
            }

            if ($scope.searchResults.ShouldRedirect) {
                //If we got here something is not right, just show no search results
                $scope.searchProducts = searchResults.Products;
                $scope.noResults = true;
            }
            else {
                $scope.searchProducts = append ? $scope.searchProducts.concat($scope.searchResults.Products) : $scope.searchResults.Products;
                $scope.facets = $scope.searchResults.Facets;
                facetsObj = Common.updateFacetsObj($scope);
                $scope.sortOrder = order || $scope.sortOrder;

                if ($scope.searchProducts.length === 0) {
                    $scope.noResults = true;
                } else {

                    //Don't like this, but don't know a better way
                    for (var i = 0; i < $scope.productsToAdd.length; i++) {
                        var productInList = $scope.productsToAdd[i];
                        for (var j = 0; j < $scope.searchProducts.length; j++) {
                            if (productInList.ProductNumber === $scope.searchProducts[j].ProductNumber) {
                                $scope.searchProducts[j].Added = true;
                                break;
                            }
                        }
                    }

                    //Did we get the max records to return from the API, hook up the scroll listener, we're done scrolling.
                    //Commenting out. Will get mike to look at it. For now, we'll return top 100 records
                    //if ($scope.searchResults.Products.length >= $scope.searchSettings.RecordsToReturn) {
                    //    var product = $scope.searchProducts[$scope.searchProducts.length - 1];

                    //    $timeout(function () {
                    //        setScrollListener(product.ProductNumber);

                    //    }, 500);
                    //}
                }

            }
        };

        $scope.addOrRemoveProduct = function (product) {
            if (!!product) {

                //Is this product already added
                if (!!product.Added) {

                    product.Added = false;
                    var index = -1;
                    for (var i = 0; i < $scope.productsToAdd.length; i++) {
                        if ($scope.productsToAdd[i].ProductNumber === product.ProductNumber) {
                            index = i;
                            break;
                        }
                    }
                    //If we found it remove it from the array
                    if (index >= 0) {
                        $scope.productsToAdd.splice(index, 1);
                    }

                }
                else {
                    product.Added = true;
                    $scope.productsToAdd.push(product);
                }
            }
        };

        $scope.saveAndContinue = function () {
            if (!!$scope.productsToAdd.length > 0) {

                var packWithSWAG = null;
                var groupWithSWAG = null;
                var existingPack = true;
                if ($scope.campaign.ComponentType === 4) {
                    //Award AND SWAG, then swag goes on the Award Pack
                    if (!$scope.campaignPacks.AwardPack) {
                        Common.showMessage('error', 'Sorry! You must first configure the Award before adding any SWAG.');
                        CampaignWizard.goToComponents();
                        return;
                    }

                    packWithSWAG = angular.copy($scope.campaignPacks.AwardPack);
                    //Get the swag group
                    for (var i = 0; i < packWithSWAG.Groups.length; i++) {
                        if (packWithSWAG.Groups[i].Type === 2) {
                            groupWithSWAG = packWithSWAG.Groups[i];
                            break;
                        }
                    }
                    if (!groupWithSWAG) {
                        //Don't have the group, create one
                        groupWithSWAG = {
                            Type: 2,
                            DisplayOrder: 2, //trophy always goes first
                            Name: 'SWAG Merchandise',
                            Products: []
                        }
                        packWithSWAG.Groups.push(groupWithSWAG);
                    }

                }
                else {
                    //For Just SWAG or Award OR Swag component types, SWAG is on the SWAG Pack
                    if (!$scope.campaignPacks.SWAGPack) {
                        existingPack = false;

                        //We need to create the SWAG pack
                        packWithSWAG = {
                            CampaignId: $scope.campaign.CampaignId,
                            Name: 'SWAG Merchandise',
                            IsDefault: ($scope.campaign.ComponentType === 2) ? true : false, //If we're just SWAG, then this is the default
                            Description: 'SWAG Merchandise',
                            GenerateSAPOrder: true,
                            Type: 2,
                            TrophyId: null,
                            Groups: []
                        };
                    }
                    else {
                        packWithSWAG = angular.copy($scope.campaignPacks.SWAGPack);
                    }
                    if (packWithSWAG.Groups.length > 0) {
                        //Get the first group on the SWAG pack (if it exists)
                        groupWithSWAG = packWithSWAG.Groups[0];
                    }
                    if (!groupWithSWAG) {
                        //Don't have the group, create one
                        groupWithSWAG = {
                            Type: 2,
                            DisplayOrder: 1, //In SWAG pack, the SWAG group always goes first
                            Name: 'SWAG Merchandise',
                            Products: []
                        }
                        packWithSWAG.Groups.push(groupWithSWAG);
                    }
                }

                if (!packWithSWAG || !groupWithSWAG) {
                    Common.showMessage('error', 'Something is amiss!! We could not add the products to your ' + App.Session.RewardCampaignNamingConvention + ' Pack. Please try again.');
                    return;
                }
                //Ok, we should have the pack and group for the swag
                jQuery.each($scope.productsToAdd, function (index, item) {

                    groupWithSWAG.Products.push({
                        ProductNumber: (!!item.TemplateProductNumber && item.TemplateProductNumber !== '') ? item.TemplateProductNumber : item.ProductNumber,
                        ProductName: item.Name,
                        IsDefault: (groupWithSWAG.Products.length === 0) ? true : false,
                        IsPersonalized: false,
                        IsConfigurable: item.IsGroup,
                        ProductDescription: (!!item.Description && item.Description !== '') ? item.Description.substring(0, 250) : 'Please provide a description...',
                        Amount: item.Price
                    });
                });

                if (existingPack) {
                    CampaignWizard.updatePack($scope.campaign.CampaignId, packWithSWAG.CampaignPackId, packWithSWAG)
                        .then(function (response) {
                            CampaignWizard.goToComponents();
                        });
                } else {
                    CampaignWizard.addPack($scope.campaign.CampaignId, packWithSWAG)
                        .then(function (response) {
                            CampaignWizard.goToComponents();
                        });
                }
            }
            else {
                //Didn't have any, just go back to components
                CampaignWizard.goToComponents();
            }
        };


        $scope.goBack = function () {
            //If we don't do it this way, we don't seem to get the currentCampaign in the Wizard
            CampaignWizard.goToComponents();
        };


        var sortItems = function ($event, order) {
            getItems($event, order, true);
        };

        var getItems = function ($event, order, sort, append) {

            if ($event) {
                $event.preventDefault();
            }

            var searchProducts = $scope.searchProducts,
                skip = skip || 0,
                top = sort ? searchProducts.length : $scope.searchSettings.RecordsToReturn;

            //If we're appending the results (i.e. get next 25, then skip all the products we've retrieved.
            if (append) {
                skip = searchProducts.length;
                $rootScope.$broadcast('loader_show', '103');
            } else {
                $rootScope.$broadcast('loader_show', '102');
                if ($('#sidebar').offset())
                    $scope.$scrollTop();
            }



            Products.searchProducts({
                'skip': skip,
                'top': top,
                'pricelevel': '01',
                'orderBy': order || $scope.sortOrder,
                'q': 'keyword=' + $scope.searchTerm + Common.getFacets($scope)

            }).then(function (response) {
                $scope.searchResults = response.data;
                displayResults(append, order);
            })
        };


        /*

        Method setScrollListener
        
        @param id is the ProductNumber property of the last product in the list. 
        
        ProductSearch.html has a repeater that assigns the ProductNumber as the id attribute for each
        product in the list.  In the method below the ProductNumber of the last item in the current 
        list of products is passed in and jquery is used to fetch the DOM elemenet with that id. 
        An interval is then set up to check every 250ms to see if the user has scrolled to the top 
        value of this element, plus a buffer.  Once its within the buffer area the call to getNext is 
        made and the interval is cancelled.

        */
        var scrollListenerInterval = null;
        var setScrollListener = function (id) {
            var target = $('#' + id),
                buffer = 750; //num of pixels above the element with this id to trigger getNext()

            if (target && target.length > 0) {
                scrollListenerInterval = setInterval(function () {
                    if ($(window).scrollTop() + buffer >= target.offset().top) {
                        getNext();
                        clearInterval(scrollListenerInterval);
                    }
                }, 250);

            }
        };

        var getSortLabel = function () {

            var sortLabels = {
                'NEWEST': 'Newest',
                'PRICELOW-HI': 'Lowest Price',
                'PRICEHI-LOW': 'Highest Price',
                'NAMEA-Z': 'Alphabetical'

            }

            return sortLabels[$scope.sortOrder] || 'Sort Chosen';
        };


        var getNext = function () {
            getItems(null, null, false, true);
        };


        var lookForFacets = function () {
            $timeout(function () {
                $scope.noFacetsVisible = $(".facets .facet-value").filter(':visible').length === 0;

            }, 100);
        };

        var refineSearch = function (scope, facetToRemove, value) {

            Common.refineSearch($scope, facetToRemove, value);
        };



        $scope.$on('onRepeatLast', lookForFacets);

        $scope.campaignPacks = null;
        $scope.campaign = null;
        $scope.searchResults = {};
        $scope.productsToAdd = [];
        $scope.searchProducts = [];
        $scope.searchTerm = '';
        $scope.lastSearchTerm = '';
        $scope.noResults = false;
        $scope.sortOrder = 'NEWEST';
        $scope.activeFacets = [];
        $scope.facetHidden = {};
        $scope.searchSettings = {
            RecordsToReturn: 100
        };

        //Expose methods to scope
        $scope.toggleFacet = Common.toggleFacet;
        $scope.getNext = getNext;
        $scope.sortItems = sortItems;
        $scope.getItems = getItems;
        $scope.getSortLabel = getSortLabel;
        $scope.refineSearch = refineSearch;

        $scope.changeFocus = Common.changeFocus;

        $scope.initialSearch = true;
        init();

    }
})();
;(function () {
    'use strict';

    angular
        .module('ecs.reward-campaigns')
        .controller('campaignCreateCommunicationTabController', campaignCreateCommunicationTabController);

    campaignCreateCommunicationTabController.$inject = ['$scope', '$uibModal', 'CampaignWizard', '$sce', '$location', '$routeParams', 'Common', 'FileUploader'];

    function campaignCreateCommunicationTabController($scope, $uibModal, CampaignWizard, $sce, $location, $routeParams, Common, FileUploader) {

        $scope.campaign = {};
        $scope.isDisabled = true;
        $scope.campaignPacks = {};
        $scope.purposeTypes = [{ value: 0, label: '- custom text -' }, { value: 1, label: 'Congratulations on' }, { value: 2, label: 'Thank You for' }];
        $scope.purposeTypeActions = ['achieving', 'achieving the', 'achieving your', 'attaining the', 'attaining your', 'being', 'completing the', 'completing your', 'delivering', 'earning the', 'earning your', 'reaching the', 'voluntering for', 'winning the', 'winning your', 'your'];
        $scope.showLogoUploader = false;
        $scope.decachedImageUrl = null;
        $scope.showDepartmentLogoUploader = false;
        $scope.decachedDepartmentImageUrl = null;
        $scope.introEmail = {};
        $scope.introEmail.isCustomized = false;
        $scope.introEmail.content = {};
        $scope.reminderEmail = {};
        $scope.reminderEmail.isCustomized = false;
        $scope.reminderEmail.content = {};


        var init = function () {
            if (!CampaignWizard.currentCampaign) {
                CampaignWizard.setCurrentCampaignByIdFromLocation()
                    .then(function (result) {
                        if (result) {
                            $scope.campaign = angular.copy(CampaignWizard.currentCampaign);
                            setupCampaignForEdit();
                        }
                        else
                        {
                            CampaignWizard.goToCampaignList();
                        }
                    });
            }
            else {
                $scope.campaign = angular.copy(CampaignWizard.currentCampaign);
                setupCampaignForEdit();
            }
        };

        var setupCampaignForEdit = function () {
            if (!$scope.campaign.EmailFromName && !$scope.campaign.EmailFromAddress) {
                $scope.campaign.EmailFromName = 'Microsoft ' + App.Session.RewardCampaignNamingConvention + 's';
                $scope.campaign.EmailFromAddress = 'msrewards@ecompanystore.com';
            }
            $scope.isDisabled = !CampaignWizard.canEditCampaign();
            $scope.introEmail.isCustomized = (!!$scope.campaign.IntroEmailJson && $scope.campaign.IntroEmailJson !== '');
            $scope.onCustomizeIntroEmailChange();

            $scope.reminderEmail.isCustomized = (!!$scope.campaign.ReminderEmailJson && $scope.campaign.ReminderEmailJson !== '');
            $scope.onCustomizeReminderEmailChange();

            uploadRewardLogo();
            uploadDepartmentLogo();
        }

        var uploadRewardLogo = function () {
            $scope.decachedImageUrl = !!$scope.campaign.LogoUrl ? $scope.campaign.LogoUrl + '?decache=' + Math.random() : null;
            if (!$scope.campaign.LogoUrl) {
                $scope.showLogoUploader = true;
            }
            $scope.uploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignRewardLogo/" + $scope.campaign.CampaignId, autoUpload: true });
            $scope.uploadError = false;
            $scope.uploadComplete = false;

            $scope.resetUploader = function () {
                $scope.uploadError = false;
                $scope.uploadComplete = false;
                $scope.uploadResponse = null;
            };

            $scope.uploader.onErrorItem = function (fileItem, response, status, headers) {
                $scope.uploadError = true;
                console.log(status);
            };

            $scope.uploader.onCompleteItem = function (item, response, status, headers) {

                if (status === 200) {
                    $scope.uploadResponse = response;
                    $scope.campaign.LogoUrl = response.PreviewUrl;
                    $scope.decachedImageUrl = $scope.campaign.LogoUrl + '?decache=' + Math.random();
                    $scope.uploadError = false;
                    $scope.uploadComplete = true;
                    $scope.showLogoUploader = false;
                } else {
                    $scope.uploadError = true;
                }
            };
        }

        var uploadDepartmentLogo = function () {
            $scope.decachedDepartmentImageUrl = !!$scope.campaign.DepartmentLogoUrl ? $scope.campaign.DepartmentLogoUrl + '?decache=' + Math.random() : null;
            if (!$scope.campaign.DepartmentLogoUrl) {
                $scope.showDepartmentLogoUploader = true;
            }
            $scope.departmentLogoUploader = new FileUploader({ url: App.Configuration.RootPath + "File/CampaignDepartmentLogo/" + $scope.campaign.CampaignId, autoUpload: true });
            $scope.departmentLogoUploadError = false;
            $scope.departmentLogoUploadComplete = false;

            $scope.departmentLogoResetUploader = function () {
                $scope.departmentLogoUploadError = false;
                $scope.departmentLogoUploadComplete = false;
                $scope.departmentLogoUploadResponse = null;
            };

            $scope.departmentLogoUploader.onErrorItem = function (fileItem, response, status, headers) {
                $scope.departmentLogoUploadError = true;
                console.log(status);
            };


            $scope.departmentLogoUploader.onCompleteItem = function (item, response, status, headers) {
                if (status === 200) {
                    $scope.departmentLogoUploadResponse = response;
                    $scope.campaign.DepartmentLogoUrl = response.PreviewUrl;
                    $scope.decachedDepartmentImageUrl = $scope.campaign.DepartmentLogoUrl + '?decache=' + Math.random();
                    $scope.departmentLogoUploadError = false;
                    $scope.departmentLogoUploadComplete = true;
                    $scope.showDepartmentLogoUploader = false;
                } else {
                    $scope.departmentLogoUploadError = true;
                }
            };
        };

        $scope.onCustomizeIntroEmailChange = function ($event) {
            if ($event)
                $event.preventDefault();

            if ($scope.introEmail.isCustomized) {
                //Do we have the JSON on the campaign object, if so use that, otherwise, setup the default based on 
                if (!!$scope.campaign.IntroEmailJson && $scope.campaign.IntroEmailJson !== '')
                    $scope.introEmail.content = JSON.parse($scope.campaign.IntroEmailJson);
                else {
                    $scope.introEmail.content = {};
                    $scope.introEmail.content.Greeting = "Hello";
                    $scope.introEmail.content.IntroText = ($scope.campaign.PurposeType == 1 ? "Congratulations on " : "Thank you for ") + ((!!$scope.campaign.PurposeTypeAction && $scope.campaign.PurposeTypeAction !== '') ? ($scope.campaign.PurposeTypeAction + ' ') : '') + $scope.campaign.RewardName + '!';
                    $scope.introEmail.content.MessageText = $scope.campaign.Description;
                    if ($scope.campaign.RedeemptionType == 1)
                        $scope.introEmail.content.MessageText = $scope.introEmail.content.MessageText + "<br /><br />You are now invited to view and redeem your " + App.Session.RewardCampaignNamingConvention.toLowerCase() + " from the Microsoft " + App.Session.RewardCampaignNamingConvention + "s & Recognition Portal. Please redeem your " + App.Session.RewardCampaignNamingConvention.toLowerCase();
                    $scope.introEmail.content.DateFormat = "1";
                    $scope.introEmail.content.DefaultActionText = ", otherwise you will receive the default item for this reward.";
                    $scope.introEmail.content.ViewLink = "View My " + App.Session.RewardCampaignNamingConvention;
                    $scope.introEmail.content.QuestionsText = ($scope.campaign.RedeemptionType == 1 ? "For questions or assistance in placing your order, please contact" : "For questions about your order, please contact");
                    $scope.introEmail.content.QuestionsSendToEmail = "customercare@ecompanystore.com";
                    $scope.introEmail.content.Salutation = "Regards,";
                    $scope.introEmail.content.FromName = $scope.campaign.DepartmentName;
                }
            } else {
                $scope.introEmail.content = {};
            }


        };

        $scope.onCustomizeReminderEmailChange = function ($event) {
            if ($event)
                $event.preventDefault();

            if ($scope.reminderEmail.isCustomized) {
                //Do we have the JSON on the campaign object, if so use that, otherwise, setup the default based on 
                if (!!$scope.campaign.ReminderEmailJson && $scope.campaign.ReminderEmailJson !== '')
                    $scope.reminderEmail.content = JSON.parse($scope.campaign.ReminderEmailJson);
                else {
                    $scope.reminderEmail.content = {};
                    $scope.reminderEmail.content.Greeting = "Hello";
                    $scope.reminderEmail.content.IntroText = ($scope.campaign.PurposeType == 1 ? "Congratulations on " : "Thank you for ") + ((!!$scope.campaign.PurposeTypeAction && $scope.campaign.PurposeTypeAction !== '') ? ($scope.campaign.PurposeTypeAction + ' ') : '') + $scope.campaign.RewardName + '!';
                    $scope.reminderEmail.content.MessageText = "Just a reminder you have ";
                    $scope.reminderEmail.content.DateFormat = "1";
                    $scope.reminderEmail.content.DefaultActionText = " to redeem your " + App.Session.RewardCampaignNamingConvention.toLowerCase() + " in the Microsoft " + App.Session.RewardCampaignNamingConvention + "s & Recognition Portal.";
                    $scope.reminderEmail.content.ViewLink = "View My " + App.Session.RewardCampaignNamingConvention;
                    $scope.reminderEmail.content.QuestionsText = "For questions or assistance in placing your order, please contact";
                    $scope.reminderEmail.content.QuestionsSendToEmail = "customercare@ecompanystore.com";
                    $scope.reminderEmail.content.Salutation = "Regards,";
                    $scope.reminderEmail.content.FromName = $scope.campaign.DepartmentName;
                }
            } else {
                $scope.reminderEmail.content = {};
            }


        };

        $scope.formatJSONDate = function (jsonDate) {
            if (!jsonDate) return '';
            return Common.convertJsonLongDateString(jsonDate, true);

        };
        
        $scope.continueToSaveCampaign = function (form) {
            if ($scope.isDisabled) { //continue without saving
                CampaignWizard.goToSummary();
                return true;
            }
            if (form.$valid) {

                if (!$scope.campaign.EmailReplyToAddress || $scope.campaign.EmailReplyToAddress === '')
                    $scope.campaign.EmailReplyToAddress = $scope.campaign.EmailFromAddress;

                if (!$scope.campaign.SendLaunchEmail && $scope.campaign.RedeemptionType === 2) {
                    $scope.campaign.RewardName = $scope.campaign.Name;
                }

                if ($scope.introEmail.isCustomized) {
                    $scope.campaign.IntroEmailJson = JSON.stringify($scope.introEmail.content);
                }
                else
                    $scope.campaign.IntroEmailJson = null;

                if ($scope.reminderEmail.isCustomized) {
                    $scope.campaign.ReminderEmailJson = JSON.stringify($scope.reminderEmail.content);
                }
                else
                    $scope.campaign.ReminderEmailJson = null;


                updateCampaign();
            } else {
                Common.showMessage('error', 'Please enter a valid value for all required fields.');
            }

        };

        $scope.back = function () {
            CampaignWizard.goToRecipients();
        };

        var updateCampaign = function () {
            CampaignWizard.updateCampaign($scope.campaign.CampaignId, $scope.campaign)
                .then(function (response) {
                    //$scope.campaign = response.data;                    
                    CampaignWizard.goToSummary();
                },
                function (error) {
                    console.log('update Campaign error', error);
                });
        };

        $scope.previewRewardMessageToRecipients = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'previewRewardMessageToRecipient.html',
                controller: 'previewRewardMessageToRecipientCtrl',
                resolve: {
                    campaign: function () {
                        return $scope.campaign;
                    },
                }
            });
        };

        $scope.showUploader = function () {
            $scope.showLogoUploader = true;
        };

        $scope.showDepartmentUploader = function () {
            $scope.showDepartmentLogoUploader = true;
        };

        $scope.showChangeEmailFromDialog = function () {
            var modalInstance = $uibModal.open({
                templateUrl: 'ChangeEmailsFromDialog.html',
                controller: 'campaignChangeEmailsFromCtrl',
                size: 'lg',

            });

            modalInstance.result.then(function (newemail) {
                if (newemail) $scope.changeEmailFrom(newemail);
            });
        };
        $scope.changeEmailFrom = function (newemail) {
            if (newemail) {
                $scope.campaign.EmailFromName = newemail.Name;
                $scope.campaign.EmailFromAddress = newemail.Email + '@ecompanystore.com';
            }
        };

        init();



    };

    angular.module('ecs.reward-campaigns').controller('previewRewardMessageToRecipientCtrl', ['$scope', '$uibModalInstance', 'campaign', function ($scope, $uibModalInstance, campaign) {
        var init = function (campaign) {
            $scope.campaign = angular.copy(campaign);
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };

        init(campaign);
    }]);

    angular.module('ecs.reward-campaigns').controller('campaignChangeEmailsFromCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {


        $scope.newEmailFrom = {
            Name: '',
            Email: ''
        };

        $scope.nameisinvalid = false;
        $scope.emailisinvalid = false;
        $scope.check = function (field) {
            if (field == 'name') {
                $scope.nameisinvalid = (!$scope.newEmailFrom.Name);
            } else if (field == 'email') {
                $scope.emailisinvalid = (!$scope.newEmailFrom.Email);
            } else {
                $scope.emailisinvalid = (!$scope.newEmailFrom.Email);
                $scope.nameisinvalid = (!$scope.newEmailFrom.Name);
            }
        };
        $scope.confirmChange = function () {

            $uibModalInstance.close($scope.newEmailFrom);
        };

        $scope.close = function () {
            $uibModalInstance.dismiss('cancel');
        };
    }]);

})();;angular
    .module('ecs.service.postalCodeOptionalCountries', [])
    .constant('PostalCodeOptionalCountries', [
        "AE",  //Dubai
        "AM", //Armenia
        "AO", //Angola
        "AZ", //Azerbaijan
        "BH", //Bahrain
        "BO", //Bolivia
        "CL", //Chile
        "CO", //Columbia
        "CR", //Costa Rica
        "DE", //Germany???
        "DO", //Dominican Republic
        "EC", //Ecuador
        "EG", //Egypt
        "GB", //Great Britan??
        "GT", //Guatemala
        "HK", //Hong Kong
        "HN", //Honduras
        "IE", //Ireland
        "JO", //Jordan
        "KE", //Kenya
        "KW", //Kuwait
        "LB", //Lebanon
        "LY", //Libya
        "ME", //Montenegro
        "MO", //Macao
        "MU", //Maritius
        "NA", //Nambia
        "NG", //Nigeria
        "PA", //Panama
        "PK", //Pakistan
        "PY", //Paraguay
        "QA", //Qatar
        "SN", //Senegal
        "SV", //El Salvador
        "TT", //Trinadad and Tobago
        "VE" 

    ]);;/*!
* Bootstrap.js by @fat & @mdo
* Copyright 2012 Twitter, Inc.
* http://www.apache.org/licenses/LICENSE-2.0.txt
*/
!function($){"use strict";$(function(){$.support.transition=function(){var transitionEnd=function(){var name,el=document.createElement("bootstrap"),transEndEventNames={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(name in transEndEventNames)if(void 0!==el.style[name])return transEndEventNames[name]}();return transitionEnd&&{end:transitionEnd}}()})}(window.jQuery),!function($){"use strict";var dismiss='[data-dismiss="alert"]',Alert=function(el){$(el).on("click",dismiss,this.close)};Alert.prototype.close=function(e){function removeElement(){$parent.trigger("closed").remove()}var $parent,$this=$(this),selector=$this.attr("data-target");selector||(selector=$this.attr("href"),selector=selector&&selector.replace(/.*(?=#[^\s]*$)/,"")),$parent=$(selector),e&&e.preventDefault(),$parent.length||($parent=$this.hasClass("alert")?$this:$this.parent()),$parent.trigger(e=$.Event("close")),e.isDefaultPrevented()||($parent.removeClass("in"),$.support.transition&&$parent.hasClass("fade")?$parent.on($.support.transition.end,removeElement):removeElement())};var old=$.fn.alert;$.fn.alert=function(option){return this.each(function(){var $this=$(this),data=$this.data("alert");data||$this.data("alert",data=new Alert(this)),"string"==typeof option&&data[option].call($this)})},$.fn.alert.Constructor=Alert,$.fn.alert.noConflict=function(){return $.fn.alert=old,this},$(document).on("click.alert.data-api",dismiss,Alert.prototype.close)}(window.jQuery),!function($){"use strict";var Button=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.button.defaults,options)};Button.prototype.setState=function(state){var d="disabled",$el=this.$element,data=$el.data(),val=$el.is("input")?"val":"html";state+="Text",data.resetText||$el.data("resetText",$el[val]()),$el[val](data[state]||this.options[state]),setTimeout(function(){"loadingText"==state?$el.addClass(d).attr(d,d):$el.removeClass(d).removeAttr(d)},0)},Button.prototype.toggle=function(){var $parent=this.$element.closest('[data-toggle="buttons-radio"]');$parent&&$parent.find(".active").removeClass("active"),this.$element.toggleClass("active")};var old=$.fn.button;$.fn.button=function(option){return this.each(function(){var $this=$(this),data=$this.data("button"),options="object"==typeof option&&option;data||$this.data("button",data=new Button(this,options)),"toggle"==option?data.toggle():option&&data.setState(option)})},$.fn.button.defaults={loadingText:"loading..."},$.fn.button.Constructor=Button,$.fn.button.noConflict=function(){return $.fn.button=old,this},$(document).on("click.button.data-api","[data-toggle^=button]",function(e){var $btn=$(e.target);$btn.hasClass("btn")||($btn=$btn.closest(".btn")),$btn.button("toggle")})}(window.jQuery),!function($){"use strict";var Carousel=function(element,options){this.$element=$(element),this.options=options,"hover"==this.options.pause&&this.$element.on("mouseenter",$.proxy(this.pause,this)).on("mouseleave",$.proxy(this.cycle,this))};Carousel.prototype={cycle:function(e){return e||(this.paused=!1),this.options.interval&&!this.paused&&(this.interval=setInterval($.proxy(this.next,this),this.options.interval)),this},to:function(pos){var $active=this.$element.find(".item.active"),children=$active.parent().children(),activePos=children.index($active),that=this;if(!(pos>children.length-1||0>pos))return this.sliding?this.$element.one("slid",function(){that.to(pos)}):activePos==pos?this.pause().cycle():this.slide(pos>activePos?"next":"prev",$(children[pos]))},pause:function(e){return e||(this.paused=!0),this.$element.find(".next, .prev").length&&$.support.transition.end&&(this.$element.trigger($.support.transition.end),this.cycle()),clearInterval(this.interval),this.interval=null,this},next:function(){return this.sliding?void 0:this.slide("next")},prev:function(){return this.sliding?void 0:this.slide("prev")},slide:function(type,next){var e,$active=this.$element.find(".item.active"),$next=next||$active[type](),isCycling=this.interval,direction="next"==type?"left":"right",fallback="next"==type?"first":"last",that=this;if(this.sliding=!0,isCycling&&this.pause(),$next=$next.length?$next:this.$element.find(".item")[fallback](),e=$.Event("slide",{relatedTarget:$next[0]}),!$next.hasClass("active")){if($.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(e),e.isDefaultPrevented())return;$next.addClass(type),$next[0].offsetWidth,$active.addClass(direction),$next.addClass(direction),this.$element.one($.support.transition.end,function(){$next.removeClass([type,direction].join(" ")).addClass("active"),$active.removeClass(["active",direction].join(" ")),that.sliding=!1,setTimeout(function(){that.$element.trigger("slid")},0)})}else{if(this.$element.trigger(e),e.isDefaultPrevented())return;$active.removeClass("active"),$next.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return isCycling&&this.cycle(),this}}};var old=$.fn.carousel;$.fn.carousel=function(option){return this.each(function(){var $this=$(this),data=$this.data("carousel"),options=$.extend({},$.fn.carousel.defaults,"object"==typeof option&&option),action="string"==typeof option?option:options.slide;data||$this.data("carousel",data=new Carousel(this,options)),"number"==typeof option?data.to(option):action?data[action]():options.interval&&data.cycle()})},$.fn.carousel.defaults={interval:5e3,pause:"hover"},$.fn.carousel.Constructor=Carousel,$.fn.carousel.noConflict=function(){return $.fn.carousel=old,this},$(document).on("click.carousel.data-api","[data-slide]",function(e){var href,$this=$(this),$target=$($this.attr("data-target")||(href=$this.attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,"")),options=$.extend({},$target.data(),$this.data());$target.carousel(options),e.preventDefault()})}(window.jQuery),!function($){"use strict";var Collapse=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.collapse.defaults,options),this.options.parent&&(this.$parent=$(this.options.parent)),this.options.toggle&&this.toggle()};Collapse.prototype={constructor:Collapse,dimension:function(){var hasWidth=this.$element.hasClass("width");return hasWidth?"width":"height"},show:function(){var dimension,scroll,actives,hasData;if(!this.transitioning){if(dimension=this.dimension(),scroll=$.camelCase(["scroll",dimension].join("-")),actives=this.$parent&&this.$parent.find("> .accordion-group > .in"),actives&&actives.length){if(hasData=actives.data("collapse"),hasData&&hasData.transitioning)return;actives.collapse("hide"),hasData||actives.data("collapse",null)}this.$element[dimension](0),this.transition("addClass",$.Event("show"),"shown"),$.support.transition&&this.$element[dimension](this.$element[0][scroll])}},hide:function(){var dimension;this.transitioning||(dimension=this.dimension(),this.reset(this.$element[dimension]()),this.transition("removeClass",$.Event("hide"),"hidden"),this.$element[dimension](0))},reset:function(size){var dimension=this.dimension();return this.$element.removeClass("collapse")[dimension](size||"auto")[0].offsetWidth,this.$element[null!==size?"addClass":"removeClass"]("collapse"),this},transition:function(method,startEvent,completeEvent){var that=this,complete=function(){"show"==startEvent.type&&that.reset(),that.transitioning=0,that.$element.trigger(completeEvent)};this.$element.trigger(startEvent),startEvent.isDefaultPrevented()||(this.transitioning=1,this.$element[method]("in"),$.support.transition&&this.$element.hasClass("collapse")?this.$element.one($.support.transition.end,complete):complete())},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var old=$.fn.collapse;$.fn.collapse=function(option){return this.each(function(){var $this=$(this),data=$this.data("collapse"),options="object"==typeof option&&option;data||$this.data("collapse",data=new Collapse(this,options)),"string"==typeof option&&data[option]()})},$.fn.collapse.defaults={toggle:!0},$.fn.collapse.Constructor=Collapse,$.fn.collapse.noConflict=function(){return $.fn.collapse=old,this},$(document).on("click.collapse.data-api","[data-toggle=collapse]",function(e){var href,$this=$(this),target=$this.attr("data-target")||e.preventDefault()||(href=$this.attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,""),option=$(target).data("collapse")?"toggle":$this.data();$this[$(target).hasClass("in")?"addClass":"removeClass"]("collapsed"),$(target).collapse(option)})}(window.jQuery),!function($){"use strict";function clearMenus(){$(toggle).each(function(){getParent($(this)).removeClass("open")})}function getParent($this){var $parent,selector=$this.attr("data-target");return selector||(selector=$this.attr("href"),selector=selector&&/#/.test(selector)&&selector.replace(/.*(?=#[^\s]*$)/,"")),$parent=$(selector),$parent.length||($parent=$this.parent()),$parent}var toggle="[data-toggle=dropdown]",Dropdown=function(element){var $el=$(element).on("click.dropdown.data-api",this.toggle);$("html").on("click.dropdown.data-api",function(){$el.parent().removeClass("open")})};Dropdown.prototype={constructor:Dropdown,toggle:function(){var $parent,isActive,$this=$(this);if(!$this.is(".disabled, :disabled"))return $parent=getParent($this),isActive=$parent.hasClass("open"),clearMenus(),isActive||$parent.toggleClass("open"),$this.focus(),!1},keydown:function(e){var $this,$items,$parent,isActive,index;if(/(38|40|27)/.test(e.keyCode)&&($this=$(this),e.preventDefault(),e.stopPropagation(),!$this.is(".disabled, :disabled"))){if($parent=getParent($this),isActive=$parent.hasClass("open"),!isActive||isActive&&27==e.keyCode)return $this.click();$items=$("[role=menu] li:not(.divider):visible a",$parent),$items.length&&(index=$items.index($items.filter(":focus")),38==e.keyCode&&index>0&&index--,40==e.keyCode&&$items.length-1>index&&index++,~index||(index=0),$items.eq(index).focus())}}};var old=$.fn.dropdown;$.fn.dropdown=function(option){return this.each(function(){var $this=$(this),data=$this.data("dropdown");data||$this.data("dropdown",data=new Dropdown(this)),"string"==typeof option&&data[option].call($this)})},$.fn.dropdown.Constructor=Dropdown,$.fn.dropdown.noConflict=function(){return $.fn.dropdown=old,this},$(document).on("click.dropdown.data-api touchstart.dropdown.data-api",clearMenus).on("click.dropdown touchstart.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("touchstart.dropdown.data-api",".dropdown-menu",function(e){e.stopPropagation()}).on("click.dropdown.data-api touchstart.dropdown.data-api",toggle,Dropdown.prototype.toggle).on("keydown.dropdown.data-api touchstart.dropdown.data-api",toggle+", [role=menu]",Dropdown.prototype.keydown)}(window.jQuery),!function($){"use strict";var Modal=function(element,options){this.options=options,this.$element=$(element).delegate('[data-dismiss="modal"]',"click.dismiss.modal",$.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};Modal.prototype={constructor:Modal,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var that=this,e=$.Event("show");this.$element.trigger(e),this.isShown||e.isDefaultPrevented()||(this.isShown=!0,this.escape(),this.backdrop(function(){var transition=$.support.transition&&that.$element.hasClass("fade");that.$element.parent().length||that.$element.appendTo(document.body),that.$element.show(),transition&&that.$element[0].offsetWidth,that.$element.addClass("in").attr("aria-hidden",!1),that.enforceFocus(),transition?that.$element.one($.support.transition.end,function(){that.$element.focus().trigger("shown")}):that.$element.focus().trigger("shown")}))},hide:function(e){e&&e.preventDefault(),e=$.Event("hide"),this.$element.trigger(e),this.isShown&&!e.isDefaultPrevented()&&(this.isShown=!1,this.escape(),$(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),$.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal())},enforceFocus:function(){var that=this;$(document).on("focusin.modal",function(e){that.$element[0]===e.target||that.$element.has(e.target).length||that.$element.focus()})},escape:function(){var that=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(e){27==e.which&&that.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var that=this,timeout=setTimeout(function(){that.$element.off($.support.transition.end),that.hideModal()},500);this.$element.one($.support.transition.end,function(){clearTimeout(timeout),that.hideModal()})},hideModal:function(){this.$element.hide().trigger("hidden"),this.backdrop()},removeBackdrop:function(){this.$backdrop.remove(),this.$backdrop=null},backdrop:function(callback){var animate=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var doAnimate=$.support.transition&&animate;this.$backdrop=$('<div class="modal-backdrop '+animate+'" />').appendTo(document.body),this.$backdrop.click("static"==this.options.backdrop?$.proxy(this.$element[0].focus,this.$element[0]):$.proxy(this.hide,this)),doAnimate&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in"),doAnimate?this.$backdrop.one($.support.transition.end,callback):callback()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),$.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one($.support.transition.end,$.proxy(this.removeBackdrop,this)):this.removeBackdrop()):callback&&callback()}};var old=$.fn.modal;$.fn.modal=function(option){return this.each(function(){var $this=$(this),data=$this.data("modal"),options=$.extend({},$.fn.modal.defaults,$this.data(),"object"==typeof option&&option);data||$this.data("modal",data=new Modal(this,options)),"string"==typeof option?data[option]():options.show&&data.show()})},$.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},$.fn.modal.Constructor=Modal,$.fn.modal.noConflict=function(){return $.fn.modal=old,this},$(document).on("click.modal.data-api",'[data-toggle="modal"]',function(e){var $this=$(this),href=$this.attr("href"),$target=$($this.attr("data-target")||href&&href.replace(/.*(?=#[^\s]+$)/,"")),option=$target.data("modal")?"toggle":$.extend({remote:!/#/.test(href)&&href},$target.data(),$this.data());e.preventDefault(),$target.modal(option).one("hide",function(){$this.focus()})})}(window.jQuery),!function($){"use strict";var Tooltip=function(element,options){this.init("tooltip",element,options)};Tooltip.prototype={constructor:Tooltip,init:function(type,element,options){var eventIn,eventOut;this.type=type,this.$element=$(element),this.options=this.getOptions(options),this.enabled=!0,"click"==this.options.trigger?this.$element.on("click."+this.type,this.options.selector,$.proxy(this.toggle,this)):"manual"!=this.options.trigger&&(eventIn="hover"==this.options.trigger?"mouseenter":"focus",eventOut="hover"==this.options.trigger?"mouseleave":"blur",this.$element.on(eventIn+"."+this.type,this.options.selector,$.proxy(this.enter,this)),this.$element.on(eventOut+"."+this.type,this.options.selector,$.proxy(this.leave,this))),this.options.selector?this._options=$.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(options){return options=$.extend({},$.fn[this.type].defaults,options,this.$element.data()),options.delay&&"number"==typeof options.delay&&(options.delay={show:options.delay,hide:options.delay}),options},enter:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);return self.options.delay&&self.options.delay.show?(clearTimeout(this.timeout),self.hoverState="in",this.timeout=setTimeout(function(){"in"==self.hoverState&&self.show()},self.options.delay.show),void 0):self.show()},leave:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);return this.timeout&&clearTimeout(this.timeout),self.options.delay&&self.options.delay.hide?(self.hoverState="out",this.timeout=setTimeout(function(){"out"==self.hoverState&&self.hide()},self.options.delay.hide),void 0):self.hide()},show:function(){var $tip,inside,pos,actualWidth,actualHeight,placement,tp;if(this.hasContent()&&this.enabled){switch($tip=this.tip(),this.setContent(),this.options.animation&&$tip.addClass("fade"),placement="function"==typeof this.options.placement?this.options.placement.call(this,$tip[0],this.$element[0]):this.options.placement,inside=/in/.test(placement),$tip.detach().css({top:0,left:0,display:"block"}).insertAfter(this.$element),pos=this.getPosition(inside),actualWidth=$tip[0].offsetWidth,actualHeight=$tip[0].offsetHeight,inside?placement.split(" ")[1]:placement){case"bottom":tp={top:pos.top+pos.height,left:pos.left+pos.width/2-actualWidth/2};break;case"top":tp={top:pos.top-actualHeight,left:pos.left+pos.width/2-actualWidth/2};break;case"left":tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left-actualWidth};break;case"right":tp={top:pos.top+pos.height/2-actualHeight/2,left:pos.left+pos.width}}$tip.offset(tp).addClass(placement).addClass("in")}},setContent:function(){var $tip=this.tip(),title=this.getTitle();$tip.find(".tooltip-inner")[this.options.html?"html":"text"](title),$tip.removeClass("fade in top bottom left right")},hide:function(){function removeWithAnimation(){var timeout=setTimeout(function(){$tip.off($.support.transition.end).detach()},500);$tip.one($.support.transition.end,function(){clearTimeout(timeout),$tip.detach()})}var $tip=this.tip();return $tip.removeClass("in"),$.support.transition&&this.$tip.hasClass("fade")?removeWithAnimation():$tip.detach(),this},fixTitle:function(){var $e=this.$element;($e.attr("title")||"string"!=typeof $e.attr("data-original-title"))&&$e.attr("data-original-title",$e.attr("title")||"").removeAttr("title")},hasContent:function(){return this.getTitle()},getPosition:function(inside){return $.extend({},inside?{top:0,left:0}:this.$element.offset(),{width:this.$element[0].offsetWidth,height:this.$element[0].offsetHeight})},getTitle:function(){var title,$e=this.$element,o=this.options;return title=$e.attr("data-original-title")||("function"==typeof o.title?o.title.call($e[0]):o.title)},tip:function(){return this.$tip=this.$tip||$(this.options.template)},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(e){var self=$(e.currentTarget)[this.type](this._options).data(this.type);self[self.tip().hasClass("in")?"hide":"show"]()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var old=$.fn.tooltip;$.fn.tooltip=function(option){return this.each(function(){var $this=$(this),data=$this.data("tooltip"),options="object"==typeof option&&option;data||$this.data("tooltip",data=new Tooltip(this,options)),"string"==typeof option&&data[option]()})},$.fn.tooltip.Constructor=Tooltip,$.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover",title:"",delay:0,html:!1},$.fn.tooltip.noConflict=function(){return $.fn.tooltip=old,this}}(window.jQuery),!function($){"use strict";var Popover=function(element,options){this.init("popover",element,options)};Popover.prototype=$.extend({},$.fn.tooltip.Constructor.prototype,{constructor:Popover,setContent:function(){var $tip=this.tip(),title=this.getTitle(),content=this.getContent();$tip.find(".popover-title")[this.options.html?"html":"text"](title),$tip.find(".popover-content")[this.options.html?"html":"text"](content),$tip.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var content,$e=this.$element,o=this.options;return content=$e.attr("data-content")||("function"==typeof o.content?o.content.call($e[0]):o.content)},tip:function(){return this.$tip||(this.$tip=$(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var old=$.fn.popover;$.fn.popover=function(option){return this.each(function(){var $this=$(this),data=$this.data("popover"),options="object"==typeof option&&option;data||$this.data("popover",data=new Popover(this,options)),"string"==typeof option&&data[option]()})},$.fn.popover.Constructor=Popover,$.fn.popover.defaults=$.extend({},$.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><div class="popover-inner"><h3 class="popover-title"></h3><div class="popover-content"></div></div></div>'}),$.fn.popover.noConflict=function(){return $.fn.popover=old,this}}(window.jQuery),!function($){"use strict";function ScrollSpy(element,options){var href,process=$.proxy(this.process,this),$element=$(element).is("body")?$(window):$(element);this.options=$.extend({},$.fn.scrollspy.defaults,options),this.$scrollElement=$element.on("scroll.scroll-spy.data-api",process),this.selector=(this.options.target||(href=$(element).attr("href"))&&href.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=$("body"),this.refresh(),this.process()}ScrollSpy.prototype={constructor:ScrollSpy,refresh:function(){var $targets,self=this;this.offsets=$([]),this.targets=$([]),$targets=this.$body.find(this.selector).map(function(){var $el=$(this),href=$el.data("target")||$el.attr("href"),$href=/^#\w/.test(href)&&$(href);return $href&&$href.length&&[[$href.position().top+self.$scrollElement.scrollTop(),href]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){self.offsets.push(this[0]),self.targets.push(this[1])})},process:function(){var i,scrollTop=this.$scrollElement.scrollTop()+this.options.offset,scrollHeight=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,maxScroll=scrollHeight-this.$scrollElement.height(),offsets=this.offsets,targets=this.targets,activeTarget=this.activeTarget;if(scrollTop>=maxScroll)return activeTarget!=(i=targets.last()[0])&&this.activate(i);for(i=offsets.length;i--;)activeTarget!=targets[i]&&scrollTop>=offsets[i]&&(!offsets[i+1]||offsets[i+1]>=scrollTop)&&this.activate(targets[i])},activate:function(target){var active,selector;this.activeTarget=target,$(this.selector).parent(".active").removeClass("active"),selector=this.selector+'[data-target="'+target+'"],'+this.selector+'[href="'+target+'"]',active=$(selector).parent("li").addClass("active"),active.parent(".dropdown-menu").length&&(active=active.closest("li.dropdown").addClass("active")),active.trigger("activate")}};var old=$.fn.scrollspy;$.fn.scrollspy=function(option){return this.each(function(){var $this=$(this),data=$this.data("scrollspy"),options="object"==typeof option&&option;data||$this.data("scrollspy",data=new ScrollSpy(this,options)),"string"==typeof option&&data[option]()})},$.fn.scrollspy.Constructor=ScrollSpy,$.fn.scrollspy.defaults={offset:10},$.fn.scrollspy.noConflict=function(){return $.fn.scrollspy=old,this},$(window).on("load",function(){$('[data-spy="scroll"]').each(function(){var $spy=$(this);$spy.scrollspy($spy.data())})})}(window.jQuery),!function($){"use strict";var Tab=function(element){this.element=$(element)};Tab.prototype={constructor:Tab,show:function(){var previous,$target,e,$this=this.element,$ul=$this.closest("ul:not(.dropdown-menu)"),selector=$this.attr("data-target");selector||(selector=$this.attr("href"),selector=selector&&selector.replace(/.*(?=#[^\s]*$)/,"")),$this.parent("li").hasClass("active")||(previous=$ul.find(".active:last a")[0],e=$.Event("show",{relatedTarget:previous}),$this.trigger(e),e.isDefaultPrevented()||($target=$(selector),this.activate($this.parent("li"),$ul),this.activate($target,$target.parent(),function(){$this.trigger({type:"shown",relatedTarget:previous})})))},activate:function(element,container,callback){function next(){$active.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),element.addClass("active"),transition?(element[0].offsetWidth,element.addClass("in")):element.removeClass("fade"),element.parent(".dropdown-menu")&&element.closest("li.dropdown").addClass("active"),callback&&callback()}var $active=container.find("> .active"),transition=callback&&$.support.transition&&$active.hasClass("fade");transition?$active.one($.support.transition.end,next):next(),$active.removeClass("in")}};var old=$.fn.tab;$.fn.tab=function(option){return this.each(function(){var $this=$(this),data=$this.data("tab");data||$this.data("tab",data=new Tab(this)),"string"==typeof option&&data[option]()})},$.fn.tab.Constructor=Tab,$.fn.tab.noConflict=function(){return $.fn.tab=old,this},$(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(e){e.preventDefault(),$(this).tab("show")})}(window.jQuery),!function($){"use strict";var Typeahead=function(element,options){this.$element=$(element),this.options=$.extend({},$.fn.typeahead.defaults,options),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=$(this.options.menu),this.shown=!1,this.listen()};Typeahead.prototype={constructor:Typeahead,select:function(){var val=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(val)).change(),this.hide()},updater:function(item){return item},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:pos.top+pos.height,left:pos.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(){var items;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(items=$.isFunction(this.source)?this.source(this.query,$.proxy(this.process,this)):this.source,items?this.process(items):this)},process:function(items){var that=this;return items=$.grep(items,function(item){return that.matcher(item)}),items=this.sorter(items),items.length?this.render(items.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(item){return~item.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(items){for(var item,beginswith=[],caseSensitive=[],caseInsensitive=[];item=items.shift();)item.toLowerCase().indexOf(this.query.toLowerCase())?~item.indexOf(this.query)?caseSensitive.push(item):caseInsensitive.push(item):beginswith.push(item);return beginswith.concat(caseSensitive,caseInsensitive)},highlighter:function(item){var query=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return item.replace(RegExp("("+query+")","ig"),function($1,match){return"<strong>"+match+"</strong>"})},render:function(items){var that=this;return items=$(items).map(function(i,item){return i=$(that.options.item).attr("data-value",item),i.find("a").html(that.highlighter(item)),i[0]}),items.first().addClass("active"),this.$menu.html(items),this},next:function(){var active=this.$menu.find(".active").removeClass("active"),next=active.next();next.length||(next=$(this.$menu.find("li")[0])),next.addClass("active")},prev:function(){var active=this.$menu.find(".active").removeClass("active"),prev=active.prev();prev.length||(prev=this.$menu.find("li").last()),prev.addClass("active")},listen:function(){this.$element.on("blur",$.proxy(this.blur,this)).on("keypress",$.proxy(this.keypress,this)).on("keyup",$.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",$.proxy(this.keydown,this)),this.$menu.on("click",$.proxy(this.click,this)).on("mouseenter","li",$.proxy(this.mouseenter,this))},eventSupported:function(eventName){var isSupported=eventName in this.$element;return isSupported||(this.$element.setAttribute(eventName,"return;"),isSupported="function"==typeof this.$element[eventName]),isSupported},move:function(e){if(this.shown){switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()}},keydown:function(e){this.suppressKeyPressRepeat=~$.inArray(e.keyCode,[40,38,9,13,27]),this.move(e)},keypress:function(e){this.suppressKeyPressRepeat||this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},blur:function(){var that=this;setTimeout(function(){that.hide()},150)},click:function(e){e.stopPropagation(),e.preventDefault(),this.select()},mouseenter:function(e){this.$menu.find(".active").removeClass("active"),$(e.currentTarget).addClass("active")}};var old=$.fn.typeahead;$.fn.typeahead=function(option){return this.each(function(){var $this=$(this),data=$this.data("typeahead"),options="object"==typeof option&&option;data||$this.data("typeahead",data=new Typeahead(this,options)),"string"==typeof option&&data[option]()})},$.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},$.fn.typeahead.Constructor=Typeahead,$.fn.typeahead.noConflict=function(){return $.fn.typeahead=old,this},$(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(e){var $this=$(this);$this.data("typeahead")||(e.preventDefault(),$this.typeahead($this.data()))})}(window.jQuery),!function($){"use strict";var Affix=function(element,options){this.options=$.extend({},$.fn.affix.defaults,options),this.$window=$(window).on("scroll.affix.data-api",$.proxy(this.checkPosition,this)).on("click.affix.data-api",$.proxy(function(){setTimeout($.proxy(this.checkPosition,this),1)},this)),this.$element=$(element),this.checkPosition()};Affix.prototype.checkPosition=function(){if(this.$element.is(":visible")){var affix,scrollHeight=$(document).height(),scrollTop=this.$window.scrollTop(),position=this.$element.offset(),offset=this.options.offset,offsetBottom=offset.bottom,offsetTop=offset.top,reset="affix affix-top affix-bottom";"object"!=typeof offset&&(offsetBottom=offsetTop=offset),"function"==typeof offsetTop&&(offsetTop=offset.top()),"function"==typeof offsetBottom&&(offsetBottom=offset.bottom()),affix=null!=this.unpin&&scrollTop+this.unpin<=position.top?!1:null!=offsetBottom&&position.top+this.$element.height()>=scrollHeight-offsetBottom?"bottom":null!=offsetTop&&offsetTop>=scrollTop?"top":!1,this.affixed!==affix&&(this.affixed=affix,this.unpin="bottom"==affix?position.top-scrollTop:null,this.$element.removeClass(reset).addClass("affix"+(affix?"-"+affix:"")))}};var old=$.fn.affix;$.fn.affix=function(option){return this.each(function(){var $this=$(this),data=$this.data("affix"),options="object"==typeof option&&option;data||$this.data("affix",data=new Affix(this,options)),"string"==typeof option&&data[option]()})},$.fn.affix.Constructor=Affix,$.fn.affix.defaults={offset:0},$.fn.affix.noConflict=function(){return $.fn.affix=old,this},$(window).on("load",function(){$('[data-spy="affix"]').each(function(){var $spy=$(this),data=$spy.data();data.offset=data.offset||{},data.offsetBottom&&(data.offset.bottom=data.offsetBottom),data.offsetTop&&(data.offset.top=data.offsetTop),$spy.affix(data)})})}(window.jQuery);;/*
 * angular-ui-bootstrap
 * http://angular-ui.github.io/bootstrap/

 * Version: 0.14.3 - 2015-10-23
 * License: MIT
 */
angular.module("ui.bootstrap",["ui.bootstrap.tpls","ui.bootstrap.collapse","ui.bootstrap.accordion","ui.bootstrap.alert","ui.bootstrap.buttons","ui.bootstrap.carousel","ui.bootstrap.dateparser","ui.bootstrap.position","ui.bootstrap.datepicker","ui.bootstrap.dropdown","ui.bootstrap.stackedMap","ui.bootstrap.modal","ui.bootstrap.pagination","ui.bootstrap.tooltip","ui.bootstrap.popover","ui.bootstrap.progressbar","ui.bootstrap.rating","ui.bootstrap.tabs","ui.bootstrap.timepicker","ui.bootstrap.typeahead"]),angular.module("ui.bootstrap.tpls",["template/accordion/accordion-group.html","template/accordion/accordion.html","template/alert/alert.html","template/carousel/carousel.html","template/carousel/slide.html","template/datepicker/datepicker.html","template/datepicker/day.html","template/datepicker/month.html","template/datepicker/popup.html","template/datepicker/year.html","template/modal/backdrop.html","template/modal/window.html","template/pagination/pager.html","template/pagination/pagination.html","template/tooltip/tooltip-html-popup.html","template/tooltip/tooltip-popup.html","template/tooltip/tooltip-template-popup.html","template/popover/popover-html.html","template/popover/popover-template.html","template/popover/popover.html","template/progressbar/bar.html","template/progressbar/progress.html","template/progressbar/progressbar.html","template/rating/rating.html","template/tabs/tab.html","template/tabs/tabset.html","template/timepicker/timepicker.html","template/typeahead/typeahead-match.html","template/typeahead/typeahead-popup.html"]),angular.module("ui.bootstrap.collapse",[]).directive("uibCollapse",["$animate","$injector",function(a,b){var c=b.has("$animateCss")?b.get("$animateCss"):null;return{link:function(b,d,e){function f(){d.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),c?c(d,{addClass:"in",easing:"ease",to:{height:d[0].scrollHeight+"px"}}).start()["finally"](g):a.addClass(d,"in",{to:{height:d[0].scrollHeight+"px"}}).then(g)}function g(){d.removeClass("collapsing").addClass("collapse").css({height:"auto"})}function h(){return d.hasClass("collapse")||d.hasClass("in")?(d.css({height:d[0].scrollHeight+"px"}).removeClass("collapse").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(c?c(d,{removeClass:"in",to:{height:"0"}}).start()["finally"](i):a.removeClass(d,"in",{to:{height:"0"}}).then(i))):i()}function i(){d.css({height:"0"}),d.removeClass("collapsing").addClass("collapse")}b.$watch(e.uibCollapse,function(a){a?h():f()})}}}]),angular.module("ui.bootstrap.collapse").value("$collapseSuppressWarning",!1).directive("collapse",["$animate","$injector","$log","$collapseSuppressWarning",function(a,b,c,d){var e=b.has("$animateCss")?b.get("$animateCss"):null;return{link:function(b,f,g){function h(){f.removeClass("collapse").addClass("collapsing").attr("aria-expanded",!0).attr("aria-hidden",!1),e?e(f,{easing:"ease",to:{height:f[0].scrollHeight+"px"}}).start().done(i):a.animate(f,{},{height:f[0].scrollHeight+"px"}).then(i)}function i(){f.removeClass("collapsing").addClass("collapse in").css({height:"auto"})}function j(){return f.hasClass("collapse")||f.hasClass("in")?(f.css({height:f[0].scrollHeight+"px"}).removeClass("collapse in").addClass("collapsing").attr("aria-expanded",!1).attr("aria-hidden",!0),void(e?e(f,{to:{height:"0"}}).start().done(k):a.animate(f,{},{height:"0"}).then(k))):k()}function k(){f.css({height:"0"}),f.removeClass("collapsing").addClass("collapse")}d||c.warn("collapse is now deprecated. Use uib-collapse instead."),b.$watch(g.collapse,function(a){a?j():h()})}}}]),angular.module("ui.bootstrap.accordion",["ui.bootstrap.collapse"]).constant("uibAccordionConfig",{closeOthers:!0}).controller("UibAccordionController",["$scope","$attrs","uibAccordionConfig",function(a,b,c){this.groups=[],this.closeOthers=function(d){var e=angular.isDefined(b.closeOthers)?a.$eval(b.closeOthers):c.closeOthers;e&&angular.forEach(this.groups,function(a){a!==d&&(a.isOpen=!1)})},this.addGroup=function(a){var b=this;this.groups.push(a),a.$on("$destroy",function(c){b.removeGroup(a)})},this.removeGroup=function(a){var b=this.groups.indexOf(a);-1!==b&&this.groups.splice(b,1)}}]).directive("uibAccordion",function(){return{controller:"UibAccordionController",controllerAs:"accordion",transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion.html"}}}).directive("uibAccordionGroup",function(){return{require:"^uibAccordion",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(a,b,c,d){d.addGroup(a),a.openClass=c.openClass||"panel-open",a.panelClass=c.panelClass,a.$watch("isOpen",function(c){b.toggleClass(a.openClass,!!c),c&&d.closeOthers(a)}),a.toggleOpen=function(b){a.isDisabled||b&&32!==b.which||(a.isOpen=!a.isOpen)}}}}).directive("uibAccordionHeading",function(){return{transclude:!0,template:"",replace:!0,require:"^uibAccordionGroup",link:function(a,b,c,d,e){d.setHeading(e(a,angular.noop))}}}).directive("uibAccordionTransclude",function(){return{require:["?^uibAccordionGroup","?^accordionGroup"],link:function(a,b,c,d){d=d[0]?d[0]:d[1],a.$watch(function(){return d[c.uibAccordionTransclude]},function(a){a&&(b.find("span").html(""),b.find("span").append(a))})}}}),angular.module("ui.bootstrap.accordion").value("$accordionSuppressWarning",!1).controller("AccordionController",["$scope","$attrs","$controller","$log","$accordionSuppressWarning",function(a,b,c,d,e){e||d.warn("AccordionController is now deprecated. Use UibAccordionController instead."),angular.extend(this,c("UibAccordionController",{$scope:a,$attrs:b}))}]).directive("accordion",["$log","$accordionSuppressWarning",function(a,b){return{restrict:"EA",controller:"AccordionController",controllerAs:"accordion",transclude:!0,replace:!1,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion.html"},link:function(){b||a.warn("accordion is now deprecated. Use uib-accordion instead.")}}}]).directive("accordionGroup",["$log","$accordionSuppressWarning",function(a,b){return{require:"^accordion",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/accordion/accordion-group.html"},scope:{heading:"@",isOpen:"=?",isDisabled:"=?"},controller:function(){this.setHeading=function(a){this.heading=a}},link:function(c,d,e,f){b||a.warn("accordion-group is now deprecated. Use uib-accordion-group instead."),f.addGroup(c),c.openClass=e.openClass||"panel-open",c.panelClass=e.panelClass,c.$watch("isOpen",function(a){d.toggleClass(c.openClass,!!a),a&&f.closeOthers(c)}),c.toggleOpen=function(a){c.isDisabled||a&&32!==a.which||(c.isOpen=!c.isOpen)}}}}]).directive("accordionHeading",["$log","$accordionSuppressWarning",function(a,b){return{restrict:"EA",transclude:!0,template:"",replace:!0,require:"^accordionGroup",link:function(c,d,e,f,g){b||a.warn("accordion-heading is now deprecated. Use uib-accordion-heading instead."),f.setHeading(g(c,angular.noop))}}}]).directive("accordionTransclude",["$log","$accordionSuppressWarning",function(a,b){return{require:"^accordionGroup",link:function(c,d,e,f){b||a.warn("accordion-transclude is now deprecated. Use uib-accordion-transclude instead."),c.$watch(function(){return f[e.accordionTransclude]},function(a){a&&(d.find("span").html(""),d.find("span").append(a))})}}}]),angular.module("ui.bootstrap.alert",[]).controller("UibAlertController",["$scope","$attrs","$interpolate","$timeout",function(a,b,c,d){a.closeable=!!b.close;var e=angular.isDefined(b.dismissOnTimeout)?c(b.dismissOnTimeout)(a.$parent):null;e&&d(function(){a.close()},parseInt(e,10))}]).directive("uibAlert",function(){return{controller:"UibAlertController",controllerAs:"alert",templateUrl:function(a,b){return b.templateUrl||"template/alert/alert.html"},transclude:!0,replace:!0,scope:{type:"@",close:"&"}}}),angular.module("ui.bootstrap.alert").value("$alertSuppressWarning",!1).controller("AlertController",["$scope","$attrs","$controller","$log","$alertSuppressWarning",function(a,b,c,d,e){e||d.warn("AlertController is now deprecated. Use UibAlertController instead."),angular.extend(this,c("UibAlertController",{$scope:a,$attrs:b}))}]).directive("alert",["$log","$alertSuppressWarning",function(a,b){return{controller:"AlertController",controllerAs:"alert",templateUrl:function(a,b){return b.templateUrl||"template/alert/alert.html"},transclude:!0,replace:!0,scope:{type:"@",close:"&"},link:function(){b||a.warn("alert is now deprecated. Use uib-alert instead.")}}}]),angular.module("ui.bootstrap.buttons",[]).constant("uibButtonConfig",{activeClass:"active",toggleEvent:"click"}).controller("UibButtonsController",["uibButtonConfig",function(a){this.activeClass=a.activeClass||"active",this.toggleEvent=a.toggleEvent||"click"}]).directive("uibBtnRadio",function(){return{require:["uibBtnRadio","ngModel"],controller:"UibButtonsController",controllerAs:"buttons",link:function(a,b,c,d){var e=d[0],f=d[1];b.find("input").css({display:"none"}),f.$render=function(){b.toggleClass(e.activeClass,angular.equals(f.$modelValue,a.$eval(c.uibBtnRadio)))},b.on(e.toggleEvent,function(){if(!c.disabled){var d=b.hasClass(e.activeClass);(!d||angular.isDefined(c.uncheckable))&&a.$apply(function(){f.$setViewValue(d?null:a.$eval(c.uibBtnRadio)),f.$render()})}})}}}).directive("uibBtnCheckbox",function(){return{require:["uibBtnCheckbox","ngModel"],controller:"UibButtonsController",controllerAs:"button",link:function(a,b,c,d){function e(){return g(c.btnCheckboxTrue,!0)}function f(){return g(c.btnCheckboxFalse,!1)}function g(b,c){return angular.isDefined(b)?a.$eval(b):c}var h=d[0],i=d[1];b.find("input").css({display:"none"}),i.$render=function(){b.toggleClass(h.activeClass,angular.equals(i.$modelValue,e()))},b.on(h.toggleEvent,function(){c.disabled||a.$apply(function(){i.$setViewValue(b.hasClass(h.activeClass)?f():e()),i.$render()})})}}}),angular.module("ui.bootstrap.buttons").value("$buttonsSuppressWarning",!1).controller("ButtonsController",["$controller","$log","$buttonsSuppressWarning",function(a,b,c){c||b.warn("ButtonsController is now deprecated. Use UibButtonsController instead."),angular.extend(this,a("UibButtonsController"))}]).directive("btnRadio",["$log","$buttonsSuppressWarning",function(a,b){return{require:["btnRadio","ngModel"],controller:"ButtonsController",controllerAs:"buttons",link:function(c,d,e,f){b||a.warn("btn-radio is now deprecated. Use uib-btn-radio instead.");var g=f[0],h=f[1];d.find("input").css({display:"none"}),h.$render=function(){d.toggleClass(g.activeClass,angular.equals(h.$modelValue,c.$eval(e.btnRadio)))},d.bind(g.toggleEvent,function(){if(!e.disabled){var a=d.hasClass(g.activeClass);(!a||angular.isDefined(e.uncheckable))&&c.$apply(function(){h.$setViewValue(a?null:c.$eval(e.btnRadio)),h.$render()})}})}}}]).directive("btnCheckbox",["$document","$log","$buttonsSuppressWarning",function(a,b,c){return{require:["btnCheckbox","ngModel"],controller:"ButtonsController",controllerAs:"button",link:function(d,e,f,g){function h(){return j(f.btnCheckboxTrue,!0)}function i(){return j(f.btnCheckboxFalse,!1)}function j(a,b){var c=d.$eval(a);return angular.isDefined(c)?c:b}c||b.warn("btn-checkbox is now deprecated. Use uib-btn-checkbox instead.");var k=g[0],l=g[1];e.find("input").css({display:"none"}),l.$render=function(){e.toggleClass(k.activeClass,angular.equals(l.$modelValue,h()))},e.bind(k.toggleEvent,function(){f.disabled||d.$apply(function(){l.$setViewValue(e.hasClass(k.activeClass)?i():h()),l.$render()})}),e.on("keypress",function(b){f.disabled||32!==b.which||a[0].activeElement!==e[0]||d.$apply(function(){l.$setViewValue(e.hasClass(k.activeClass)?i():h()),l.$render()})})}}}]),angular.module("ui.bootstrap.carousel",[]).controller("UibCarouselController",["$scope","$element","$interval","$animate",function(a,b,c,d){function e(b,c,e){s||(angular.extend(b,{direction:e,active:!0}),angular.extend(m.currentSlide||{},{direction:e,active:!1}),d.enabled()&&!a.noTransition&&!a.$currentTransition&&b.$element&&m.slides.length>1&&(b.$element.data(q,b.direction),m.currentSlide&&m.currentSlide.$element&&m.currentSlide.$element.data(q,b.direction),a.$currentTransition=!0,o?d.on("addClass",b.$element,function(b,c){"close"===c&&(a.$currentTransition=null,d.off("addClass",b))}):b.$element.one("$animate:close",function(){a.$currentTransition=null})),m.currentSlide=b,r=c,g())}function f(a){if(angular.isUndefined(n[a].index))return n[a];var b;n.length;for(b=0;b<n.length;++b)if(n[b].index==a)return n[b]}function g(){h();var b=+a.interval;!isNaN(b)&&b>0&&(k=c(i,b))}function h(){k&&(c.cancel(k),k=null)}function i(){var b=+a.interval;l&&!isNaN(b)&&b>0&&n.length?a.next():a.pause()}function j(b){b.length||(a.$currentTransition=null)}var k,l,m=this,n=m.slides=a.slides=[],o=angular.version.minor>=4,p="uib-noTransition",q="uib-slideDirection",r=-1;m.currentSlide=null;var s=!1;m.select=a.select=function(b,c){var d=a.indexOfSlide(b);void 0===c&&(c=d>m.getCurrentIndex()?"next":"prev"),b&&b!==m.currentSlide&&!a.$currentTransition&&e(b,d,c)},a.$on("$destroy",function(){s=!0}),m.getCurrentIndex=function(){return m.currentSlide&&angular.isDefined(m.currentSlide.index)?+m.currentSlide.index:r},a.indexOfSlide=function(a){return angular.isDefined(a.index)?+a.index:n.indexOf(a)},a.next=function(){var b=(m.getCurrentIndex()+1)%n.length;return 0===b&&a.noWrap()?void a.pause():m.select(f(b),"next")},a.prev=function(){var b=m.getCurrentIndex()-1<0?n.length-1:m.getCurrentIndex()-1;return a.noWrap()&&b===n.length-1?void a.pause():m.select(f(b),"prev")},a.isActive=function(a){return m.currentSlide===a},a.$watch("interval",g),a.$watchCollection("slides",j),a.$on("$destroy",h),a.play=function(){l||(l=!0,g())},a.pause=function(){a.noPause||(l=!1,h())},m.addSlide=function(b,c){b.$element=c,n.push(b),1===n.length||b.active?(m.select(n[n.length-1]),1===n.length&&a.play()):b.active=!1},m.removeSlide=function(a){angular.isDefined(a.index)&&n.sort(function(a,b){return+a.index>+b.index});var b=n.indexOf(a);n.splice(b,1),n.length>0&&a.active?b>=n.length?m.select(n[b-1]):m.select(n[b]):r>b&&r--,0===n.length&&(m.currentSlide=null)},a.$watch("noTransition",function(a){b.data(p,a)})}]).directive("uibCarousel",[function(){return{transclude:!0,replace:!0,controller:"UibCarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"}}}]).directive("uibSlide",function(){return{require:"^uibCarousel",restrict:"EA",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(a,b,c,d){d.addSlide(a,b),a.$on("$destroy",function(){d.removeSlide(a)}),a.$watch("active",function(b){b&&d.select(a)})}}}).animation(".item",["$injector","$animate",function(a,b){function c(a,b,c){a.removeClass(b),c&&c()}var d="uib-noTransition",e="uib-slideDirection",f=null;return a.has("$animateCss")&&(f=a.get("$animateCss")),{beforeAddClass:function(a,g,h){if("active"==g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k+" "+j,h);return a.addClass(j),f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()},beforeRemoveClass:function(a,g,h){if("active"===g&&a.parent()&&a.parent().parent()&&!a.parent().parent().data(d)){var i=!1,j=a.data(e),k="next"==j?"left":"right",l=c.bind(this,a,k,h);return f?f(a,{addClass:k}).start().done(l):b.addClass(a,k).then(function(){i||l(),h()}),function(){i=!0}}h()}}}]),angular.module("ui.bootstrap.carousel").value("$carouselSuppressWarning",!1).controller("CarouselController",["$scope","$element","$controller","$log","$carouselSuppressWarning",function(a,b,c,d,e){e||d.warn("CarouselController is now deprecated. Use UibCarouselController instead."),angular.extend(this,c("UibCarouselController",{$scope:a,$element:b}))}]).directive("carousel",["$log","$carouselSuppressWarning",function(a,b){return{transclude:!0,replace:!0,controller:"CarouselController",controllerAs:"carousel",require:"carousel",templateUrl:function(a,b){return b.templateUrl||"template/carousel/carousel.html"},scope:{interval:"=",noTransition:"=",noPause:"=",noWrap:"&"},link:function(){b||a.warn("carousel is now deprecated. Use uib-carousel instead.")}}}]).directive("slide",["$log","$carouselSuppressWarning",function(a,b){return{require:"^carousel",transclude:!0,replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/carousel/slide.html"},scope:{active:"=?",actual:"=?",index:"=?"},link:function(c,d,e,f){b||a.warn("slide is now deprecated. Use uib-slide instead."),f.addSlide(c,d),c.$on("$destroy",function(){f.removeSlide(c)}),c.$watch("active",function(a){a&&f.select(c)})}}}]),angular.module("ui.bootstrap.dateparser",[]).service("uibDateParser",["$log","$locale","orderByFilter",function(a,b,c){function d(a){var b=[],d=a.split("");return angular.forEach(g,function(c,e){var f=a.indexOf(e);if(f>-1){a=a.split(""),d[f]="("+c.regex+")",a[f]="$";for(var g=f+1,h=f+e.length;h>g;g++)d[g]="",a[g]="$";a=a.join(""),b.push({index:f,apply:c.apply})}}),{regex:new RegExp("^"+d.join("")+"$"),map:c(b,"index")}}function e(a,b,c){return 1>c?!1:1===b&&c>28?29===c&&(a%4===0&&a%100!==0||a%400===0):3===b||5===b||8===b||10===b?31>c:!0}var f,g,h=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;this.init=function(){f=b.id,this.parsers={},g={yyyy:{regex:"\\d{4}",apply:function(a){this.year=+a}},yy:{regex:"\\d{2}",apply:function(a){this.year=+a+2e3}},y:{regex:"\\d{1,4}",apply:function(a){this.year=+a}},MMMM:{regex:b.DATETIME_FORMATS.MONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.MONTH.indexOf(a)}},MMM:{regex:b.DATETIME_FORMATS.SHORTMONTH.join("|"),apply:function(a){this.month=b.DATETIME_FORMATS.SHORTMONTH.indexOf(a)}},MM:{regex:"0[1-9]|1[0-2]",apply:function(a){this.month=a-1}},M:{regex:"[1-9]|1[0-2]",apply:function(a){this.month=a-1}},dd:{regex:"[0-2][0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},d:{regex:"[1-2]?[0-9]{1}|3[0-1]{1}",apply:function(a){this.date=+a}},EEEE:{regex:b.DATETIME_FORMATS.DAY.join("|")},EEE:{regex:b.DATETIME_FORMATS.SHORTDAY.join("|")},HH:{regex:"(?:0|1)[0-9]|2[0-3]",apply:function(a){this.hours=+a}},hh:{regex:"0[0-9]|1[0-2]",apply:function(a){this.hours=+a}},H:{regex:"1?[0-9]|2[0-3]",apply:function(a){this.hours=+a}},h:{regex:"[0-9]|1[0-2]",apply:function(a){this.hours=+a}},mm:{regex:"[0-5][0-9]",apply:function(a){this.minutes=+a}},m:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.minutes=+a}},sss:{regex:"[0-9][0-9][0-9]",apply:function(a){this.milliseconds=+a}},ss:{regex:"[0-5][0-9]",apply:function(a){this.seconds=+a}},s:{regex:"[0-9]|[1-5][0-9]",apply:function(a){this.seconds=+a}},a:{regex:b.DATETIME_FORMATS.AMPMS.join("|"),apply:function(a){12===this.hours&&(this.hours=0),"PM"===a&&(this.hours+=12)}}}},this.init(),this.parse=function(c,g,i){if(!angular.isString(c)||!g)return c;g=b.DATETIME_FORMATS[g]||g,g=g.replace(h,"\\$&"),b.id!==f&&this.init(),this.parsers[g]||(this.parsers[g]=d(g));var j=this.parsers[g],k=j.regex,l=j.map,m=c.match(k);if(m&&m.length){var n,o;angular.isDate(i)&&!isNaN(i.getTime())?n={year:i.getFullYear(),month:i.getMonth(),date:i.getDate(),hours:i.getHours(),minutes:i.getMinutes(),seconds:i.getSeconds(),milliseconds:i.getMilliseconds()}:(i&&a.warn("dateparser:","baseDate is not a valid date"),n={year:1900,month:0,date:1,hours:0,minutes:0,seconds:0,milliseconds:0});for(var p=1,q=m.length;q>p;p++){var r=l[p-1];r.apply&&r.apply.call(n,m[p])}return e(n.year,n.month,n.date)&&(angular.isDate(i)&&!isNaN(i.getTime())?(o=new Date(i),o.setFullYear(n.year,n.month,n.date,n.hours,n.minutes,n.seconds,n.milliseconds||0)):o=new Date(n.year,n.month,n.date,n.hours,n.minutes,n.seconds,n.milliseconds||0)),o}}}]),angular.module("ui.bootstrap.dateparser").value("$dateParserSuppressWarning",!1).service("dateParser",["$log","$dateParserSuppressWarning","uibDateParser",function(a,b,c){b||a.warn("dateParser is now deprecated. Use uibDateParser instead."),angular.extend(this,c)}]),angular.module("ui.bootstrap.position",[]).factory("$uibPosition",["$document","$window",function(a,b){function c(a,c){return a.currentStyle?a.currentStyle[c]:b.getComputedStyle?b.getComputedStyle(a)[c]:a.style[c]}function d(a){return"static"===(c(a,"position")||"static")}var e=function(b){for(var c=a[0],e=b.offsetParent||c;e&&e!==c&&d(e);)e=e.offsetParent;return e||c};return{position:function(b){var c=this.offset(b),d={top:0,left:0},f=e(b[0]);f!=a[0]&&(d=this.offset(angular.element(f)),d.top+=f.clientTop-f.scrollTop,d.left+=f.clientLeft-f.scrollLeft);var g=b[0].getBoundingClientRect();return{width:g.width||b.prop("offsetWidth"),height:g.height||b.prop("offsetHeight"),top:c.top-d.top,left:c.left-d.left}},offset:function(c){var d=c[0].getBoundingClientRect();return{width:d.width||c.prop("offsetWidth"),height:d.height||c.prop("offsetHeight"),top:d.top+(b.pageYOffset||a[0].documentElement.scrollTop),left:d.left+(b.pageXOffset||a[0].documentElement.scrollLeft)}},positionElements:function(a,b,c,d){var e,f,g,h,i=c.split("-"),j=i[0],k=i[1]||"center";e=d?this.offset(a):this.position(a),f=b.prop("offsetWidth"),g=b.prop("offsetHeight");var l={center:function(){return e.left+e.width/2-f/2},left:function(){return e.left},right:function(){return e.left+e.width}},m={center:function(){return e.top+e.height/2-g/2},top:function(){return e.top},bottom:function(){return e.top+e.height}};switch(j){case"right":h={top:m[k](),left:l[j]()};break;case"left":h={top:m[k](),left:e.left-f};break;case"bottom":h={top:m[j](),left:l[k]()};break;default:h={top:e.top-g,left:l[k]()}}return h}}}]),angular.module("ui.bootstrap.position").value("$positionSuppressWarning",!1).service("$position",["$log","$positionSuppressWarning","$uibPosition",function(a,b,c){b||a.warn("$position is now deprecated. Use $uibPosition instead."),angular.extend(this,c)}]),angular.module("ui.bootstrap.datepicker",["ui.bootstrap.dateparser","ui.bootstrap.position"]).value("$datepickerSuppressError",!1).constant("uibDatepickerConfig",{formatDay:"dd",formatMonth:"MMMM",formatYear:"yyyy",formatDayHeader:"EEE",formatDayTitle:"MMMM yyyy",formatMonthTitle:"yyyy",datepickerMode:"day",minMode:"day",maxMode:"year",showWeeks:!0,startingDay:0,yearRange:20,minDate:null,maxDate:null,shortcutPropagation:!1}).controller("UibDatepickerController",["$scope","$attrs","$parse","$interpolate","$log","dateFilter","uibDatepickerConfig","$datepickerSuppressError",function(a,b,c,d,e,f,g,h){var i=this,j={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){i[c]=angular.isDefined(b[c])?6>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):g[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){i[d]=a?new Date(a):null,i.refreshView()}):i[d]=g[d]?new Date(g[d]):null}),angular.forEach(["minMode","maxMode"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(c){i[d]=angular.isDefined(c)?c:b[d],a[d]=i[d],("minMode"==d&&i.modes.indexOf(a.datepickerMode)<i.modes.indexOf(i[d])||"maxMode"==d&&i.modes.indexOf(a.datepickerMode)>i.modes.indexOf(i[d]))&&(a.datepickerMode=i[d])}):(i[d]=g[d]||null,a[d]=i[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(j.$isEmpty(j.$modelValue)||j.$invalid)&&(i.activeDate=a,i.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===i.compare(b.date,i.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){j=a,j.$render=function(){i.render()}},this.render=function(){if(j.$viewValue){var a=new Date(j.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=j.$viewValue?new Date(j.$viewValue):null;j.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=j.$viewValue?new Date(j.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},a.select=function(b){if(a.datepickerMode===i.minMode){var c=j.$viewValue?new Date(j.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),j.$setViewValue(c),j.$render()}else i.activeDate=b,a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=i.activeDate.getFullYear()+a*(i.step.years||0),c=i.activeDate.getMonth()+a*(i.step.months||0);i.activeDate.setFullYear(b,c,1),i.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===i.maxMode&&1===b||a.datepickerMode===i.minMode&&-1===b||(a.datepickerMode=i.modes[i.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var k=function(){i.element[0].focus()};a.$on("uib:datepicker.focus",k),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),i.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(i.isDisabled(i.activeDate))return;a.select(i.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(i.handleKeyDown(c,b),i.refreshView()):a.toggleMode("up"===c?1:-1)}}]).controller("UibDaypickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a,b){return 1!==b||a%4!==0||a%100===0&&a%400!==0?f[b]:29}function e(a){var b=new Date(a);b.setDate(b.getDate()+4-(b.getDay()||7));var c=b.getTime();return b.setMonth(0),b.setDate(1),Math.floor(Math.round((c-b)/864e5)/7)+1}var f=[31,28,31,30,31,30,31,31,30,31,30,31];this.step={months:1},this.element=b,this.init=function(b){angular.extend(b,this),a.showWeeks=b.showWeeks,b.refreshView()},this.getDates=function(a,b){for(var c,d=new Array(b),e=new Date(a),f=0;b>f;)c=new Date(e),d[f++]=c,e.setDate(e.getDate()+1);return d},this._refreshView=function(){var b=this.activeDate.getFullYear(),d=this.activeDate.getMonth(),f=new Date(this.activeDate);f.setFullYear(b,d,1);var g=this.startingDay-f.getDay(),h=g>0?7-g:-g,i=new Date(f);h>0&&i.setDate(-h+1);for(var j=this.getDates(i,42),k=0;42>k;k++)j[k]=angular.extend(this.createDateObject(j[k],this.formatDay),{secondary:j[k].getMonth()!==d,uid:a.uniqueId+"-"+k});a.labels=new Array(7);for(var l=0;7>l;l++)a.labels[l]={abbr:c(j[l].date,this.formatDayHeader),full:c(j[l].date,"EEEE")};if(a.title=c(this.activeDate,this.formatDayTitle),a.rows=this.split(j,7),a.showWeeks){a.weekNumbers=[];for(var m=(11-this.startingDay)%7,n=a.rows.length,o=0;n>o;o++)a.weekNumbers.push(e(a.rows[o][m].date))}},this.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},this.handleKeyDown=function(a,b){var c=this.activeDate.getDate();if("left"===a)c-=1;else if("up"===a)c-=7;else if("right"===a)c+=1;else if("down"===a)c+=7;else if("pageup"===a||"pagedown"===a){var e=this.activeDate.getMonth()+("pageup"===a?-1:1);this.activeDate.setMonth(e,1),c=Math.min(d(this.activeDate.getFullYear(),this.activeDate.getMonth()),c)}else"home"===a?c=1:"end"===a&&(c=d(this.activeDate.getFullYear(),this.activeDate.getMonth()));this.activeDate.setDate(c)}}]).controller("UibMonthpickerController",["$scope","$element","dateFilter",function(a,b,c){this.step={years:1},this.element=b,this.init=function(a){angular.extend(a,this),a.refreshView()},this._refreshView=function(){for(var b,d=new Array(12),e=this.activeDate.getFullYear(),f=0;12>f;f++)b=new Date(this.activeDate),b.setFullYear(e,f,1),d[f]=angular.extend(this.createDateObject(b,this.formatMonth),{uid:a.uniqueId+"-"+f});a.title=c(this.activeDate,this.formatMonthTitle),a.rows=this.split(d,3)},this.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth())-new Date(b.getFullYear(),b.getMonth())},this.handleKeyDown=function(a,b){var c=this.activeDate.getMonth();if("left"===a)c-=1;else if("up"===a)c-=3;else if("right"===a)c+=1;else if("down"===a)c+=3;else if("pageup"===a||"pagedown"===a){var d=this.activeDate.getFullYear()+("pageup"===a?-1:1);this.activeDate.setFullYear(d)}else"home"===a?c=0:"end"===a&&(c=11);this.activeDate.setMonth(c)}}]).controller("UibYearpickerController",["$scope","$element","dateFilter",function(a,b,c){function d(a){return parseInt((a-1)/e,10)*e+1}var e;this.element=b,this.yearpickerInit=function(){e=this.yearRange,this.step={years:e}},this._refreshView=function(){for(var b,c=new Array(e),f=0,g=d(this.activeDate.getFullYear());e>f;f++)b=new Date(this.activeDate),b.setFullYear(g+f,0,1),c[f]=angular.extend(this.createDateObject(b,this.formatYear),{uid:a.uniqueId+"-"+f});a.title=[c[0].label,c[e-1].label].join(" - "),a.rows=this.split(c,5)},this.compare=function(a,b){return a.getFullYear()-b.getFullYear()},this.handleKeyDown=function(a,b){var c=this.activeDate.getFullYear();"left"===a?c-=1:"up"===a?c-=5:"right"===a?c+=1:"down"===a?c+=5:"pageup"===a||"pagedown"===a?c+=("pageup"===a?-1:1)*this.step.years:"home"===a?c=d(this.activeDate.getFullYear()):"end"===a&&(c=d(this.activeDate.getFullYear())+e-1),this.activeDate.setFullYear(c)}}]).directive("uibDatepicker",function(){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/datepicker.html"},scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["uibDatepicker","^ngModel"],controller:"UibDatepickerController",controllerAs:"datepicker",link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}).directive("uibDaypicker",function(){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/day.html"},require:["^?uibDatepicker","uibDaypicker","^?datepicker"],controller:"UibDaypickerController",link:function(a,b,c,d){var e=d[0]||d[2],f=d[1];f.init(e)}}}).directive("uibMonthpicker",function(){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/month.html"},require:["^?uibDatepicker","uibMonthpicker","^?datepicker"],controller:"UibMonthpickerController",link:function(a,b,c,d){var e=d[0]||d[2],f=d[1];f.init(e)}}}).directive("uibYearpicker",function(){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/year.html"},require:["^?uibDatepicker","uibYearpicker","^?datepicker"],controller:"UibYearpickerController",link:function(a,b,c,d){var e=d[0]||d[2];angular.extend(e,d[1]),e.yearpickerInit(),e.refreshView()}}}).constant("uibDatepickerPopupConfig",{datepickerPopup:"yyyy-MM-dd",datepickerPopupTemplateUrl:"template/datepicker/popup.html",datepickerTemplateUrl:"template/datepicker/datepicker.html",html5Types:{date:"yyyy-MM-dd","datetime-local":"yyyy-MM-ddTHH:mm:ss.sss",month:"yyyy-MM"},currentText:"Today",clearText:"Clear",closeText:"Done",closeOnDateSelection:!0,appendToBody:!1,showButtonBar:!0,onOpenFocus:!0}).controller("UibDatepickerPopupController",["$scope","$element","$attrs","$compile","$parse","$document","$rootScope","$uibPosition","dateFilter","uibDateParser","uibDatepickerPopupConfig","$timeout",function(a,b,c,d,e,f,g,h,i,j,k,l){
function m(a){return a.replace(/([A-Z])/g,function(a){return"-"+a.toLowerCase()})}function n(b){if(angular.isNumber(b)&&(b=new Date(b)),b){if(angular.isDate(b)&&!isNaN(b))return b;if(angular.isString(b)){var c=j.parse(b,r,a.date);return isNaN(c)?void 0:c}return void 0}return null}function o(a,b){var d=a||b;if(!c.ngRequired&&!d)return!0;if(angular.isNumber(d)&&(d=new Date(d)),d){if(angular.isDate(d)&&!isNaN(d))return!0;if(angular.isString(d)){var e=j.parse(d,r);return!isNaN(e)}return!1}return!0}function p(c){var d=A[0],e=b[0].contains(c.target),f=void 0!==d.contains&&d.contains(c.target);!a.isOpen||e||f||a.$apply(function(){a.isOpen=!1})}function q(c){27===c.which&&a.isOpen?(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!1}),b[0].focus()):40!==c.which||a.isOpen||(c.preventDefault(),c.stopPropagation(),a.$apply(function(){a.isOpen=!0}))}var r,s,t,u,v,w,x,y,z,A,B={},C=!1;a.watchData={},this.init=function(h){if(z=h,s=angular.isDefined(c.closeOnDateSelection)?a.$parent.$eval(c.closeOnDateSelection):k.closeOnDateSelection,t=angular.isDefined(c.datepickerAppendToBody)?a.$parent.$eval(c.datepickerAppendToBody):k.appendToBody,u=angular.isDefined(c.onOpenFocus)?a.$parent.$eval(c.onOpenFocus):k.onOpenFocus,v=angular.isDefined(c.datepickerPopupTemplateUrl)?c.datepickerPopupTemplateUrl:k.datepickerPopupTemplateUrl,w=angular.isDefined(c.datepickerTemplateUrl)?c.datepickerTemplateUrl:k.datepickerTemplateUrl,a.showButtonBar=angular.isDefined(c.showButtonBar)?a.$parent.$eval(c.showButtonBar):k.showButtonBar,k.html5Types[c.type]?(r=k.html5Types[c.type],C=!0):(r=c.datepickerPopup||c.uibDatepickerPopup||k.datepickerPopup,c.$observe("uibDatepickerPopup",function(a,b){var c=a||k.datepickerPopup;if(c!==r&&(r=c,z.$modelValue=null,!r))throw new Error("uibDatepickerPopup must have a date format specified.")})),!r)throw new Error("uibDatepickerPopup must have a date format specified.");if(C&&c.datepickerPopup)throw new Error("HTML5 date input types do not support custom formats.");if(x=angular.element("<div uib-datepicker-popup-wrap><div uib-datepicker></div></div>"),x.attr({"ng-model":"date","ng-change":"dateSelection(date)","template-url":v}),y=angular.element(x.children()[0]),y.attr("template-url",w),C&&"month"===c.type&&(y.attr("datepicker-mode",'"month"'),y.attr("min-mode","month")),c.datepickerOptions){var l=a.$parent.$eval(c.datepickerOptions);l&&l.initDate&&(a.initDate=l.initDate,y.attr("init-date","initDate"),delete l.initDate),angular.forEach(l,function(a,b){y.attr(m(b),a)})}angular.forEach(["minMode","maxMode","minDate","maxDate","datepickerMode","initDate","shortcutPropagation"],function(b){if(c[b]){var d=e(c[b]);if(a.$parent.$watch(d,function(c){a.watchData[b]=c,("minDate"===b||"maxDate"===b)&&(B[b]=new Date(c))}),y.attr(m(b),"watchData."+b),"datepickerMode"===b){var f=d.assign;a.$watch("watchData."+b,function(b,c){angular.isFunction(f)&&b!==c&&f(a.$parent,b)})}}}),c.dateDisabled&&y.attr("date-disabled","dateDisabled({ date: date, mode: mode })"),c.showWeeks&&y.attr("show-weeks",c.showWeeks),c.customClass&&y.attr("custom-class","customClass({ date: date, mode: mode })"),C?z.$formatters.push(function(b){return a.date=b,b}):(z.$$parserName="date",z.$validators.date=o,z.$parsers.unshift(n),z.$formatters.push(function(b){return a.date=b,z.$isEmpty(b)?b:i(b,r)})),z.$viewChangeListeners.push(function(){a.date=j.parse(z.$viewValue,r,a.date)}),b.bind("keydown",q),A=d(x)(a),x.remove(),t?f.find("body").append(A):b.after(A),a.$on("$destroy",function(){a.isOpen===!0&&(g.$$phase||a.$apply(function(){a.isOpen=!1})),A.remove(),b.unbind("keydown",q),f.unbind("click",p)})},a.getText=function(b){return a[b+"Text"]||k[b+"Text"]},a.isDisabled=function(b){return"today"===b&&(b=new Date),a.watchData.minDate&&a.compare(b,B.minDate)<0||a.watchData.maxDate&&a.compare(b,B.maxDate)>0},a.compare=function(a,b){return new Date(a.getFullYear(),a.getMonth(),a.getDate())-new Date(b.getFullYear(),b.getMonth(),b.getDate())},a.dateSelection=function(c){angular.isDefined(c)&&(a.date=c);var d=a.date?i(a.date,r):null;b.val(d),z.$setViewValue(d),s&&(a.isOpen=!1,b[0].focus())},a.keydown=function(c){27===c.which&&(a.isOpen=!1,b[0].focus())},a.select=function(b){if("today"===b){var c=new Date;angular.isDate(a.date)?(b=new Date(a.date),b.setFullYear(c.getFullYear(),c.getMonth(),c.getDate())):b=new Date(c.setHours(0,0,0,0))}a.dateSelection(b)},a.close=function(){a.isOpen=!1,b[0].focus()},a.$watch("isOpen",function(c){c?(a.position=t?h.offset(b):h.position(b),a.position.top=a.position.top+b.prop("offsetHeight"),l(function(){u&&a.$broadcast("uib:datepicker.focus"),f.bind("click",p)},0,!1)):f.unbind("click",p)})}]).directive("uibDatepickerPopup",function(){return{require:["ngModel","uibDatepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(a,b,c,d){var e=d[0],f=d[1];f.init(e)}}}).directive("uibDatepickerPopupWrap",function(){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"}}}),angular.module("ui.bootstrap.datepicker").value("$datepickerSuppressWarning",!1).controller("DatepickerController",["$scope","$attrs","$parse","$interpolate","$log","dateFilter","uibDatepickerConfig","$datepickerSuppressError","$datepickerSuppressWarning",function(a,b,c,d,e,f,g,h,i){i||e.warn("DatepickerController is now deprecated. Use UibDatepickerController instead.");var j=this,k={$setViewValue:angular.noop};this.modes=["day","month","year"],angular.forEach(["formatDay","formatMonth","formatYear","formatDayHeader","formatDayTitle","formatMonthTitle","showWeeks","startingDay","yearRange","shortcutPropagation"],function(c,e){j[c]=angular.isDefined(b[c])?6>e?d(b[c])(a.$parent):a.$parent.$eval(b[c]):g[c]}),angular.forEach(["minDate","maxDate"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(a){j[d]=a?new Date(a):null,j.refreshView()}):j[d]=g[d]?new Date(g[d]):null}),angular.forEach(["minMode","maxMode"],function(d){b[d]?a.$parent.$watch(c(b[d]),function(c){j[d]=angular.isDefined(c)?c:b[d],a[d]=j[d],("minMode"==d&&j.modes.indexOf(a.datepickerMode)<j.modes.indexOf(j[d])||"maxMode"==d&&j.modes.indexOf(a.datepickerMode)>j.modes.indexOf(j[d]))&&(a.datepickerMode=j[d])}):(j[d]=g[d]||null,a[d]=j[d])}),a.datepickerMode=a.datepickerMode||g.datepickerMode,a.uniqueId="datepicker-"+a.$id+"-"+Math.floor(1e4*Math.random()),angular.isDefined(b.initDate)?(this.activeDate=a.$parent.$eval(b.initDate)||new Date,a.$parent.$watch(b.initDate,function(a){a&&(k.$isEmpty(k.$modelValue)||k.$invalid)&&(j.activeDate=a,j.refreshView())})):this.activeDate=new Date,a.isActive=function(b){return 0===j.compare(b.date,j.activeDate)?(a.activeDateId=b.uid,!0):!1},this.init=function(a){k=a,k.$render=function(){j.render()}},this.render=function(){if(k.$viewValue){var a=new Date(k.$viewValue),b=!isNaN(a);b?this.activeDate=a:h||e.error('Datepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')}this.refreshView()},this.refreshView=function(){if(this.element){this._refreshView();var a=k.$viewValue?new Date(k.$viewValue):null;k.$setValidity("dateDisabled",!a||this.element&&!this.isDisabled(a))}},this.createDateObject=function(a,b){var c=k.$viewValue?new Date(k.$viewValue):null;return{date:a,label:f(a,b),selected:c&&0===this.compare(a,c),disabled:this.isDisabled(a),current:0===this.compare(a,new Date),customClass:this.customClass(a)}},this.isDisabled=function(c){return this.minDate&&this.compare(c,this.minDate)<0||this.maxDate&&this.compare(c,this.maxDate)>0||b.dateDisabled&&a.dateDisabled({date:c,mode:a.datepickerMode})},this.customClass=function(b){return a.customClass({date:b,mode:a.datepickerMode})},this.split=function(a,b){for(var c=[];a.length>0;)c.push(a.splice(0,b));return c},this.fixTimeZone=function(a){var b=a.getHours();a.setHours(23===b?b+2:0)},a.select=function(b){if(a.datepickerMode===j.minMode){var c=k.$viewValue?new Date(k.$viewValue):new Date(0,0,0,0,0,0,0);c.setFullYear(b.getFullYear(),b.getMonth(),b.getDate()),k.$setViewValue(c),k.$render()}else j.activeDate=b,a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)-1]},a.move=function(a){var b=j.activeDate.getFullYear()+a*(j.step.years||0),c=j.activeDate.getMonth()+a*(j.step.months||0);j.activeDate.setFullYear(b,c,1),j.refreshView()},a.toggleMode=function(b){b=b||1,a.datepickerMode===j.maxMode&&1===b||a.datepickerMode===j.minMode&&-1===b||(a.datepickerMode=j.modes[j.modes.indexOf(a.datepickerMode)+b])},a.keys={13:"enter",32:"space",33:"pageup",34:"pagedown",35:"end",36:"home",37:"left",38:"up",39:"right",40:"down"};var l=function(){j.element[0].focus()};a.$on("uib:datepicker.focus",l),a.keydown=function(b){var c=a.keys[b.which];if(c&&!b.shiftKey&&!b.altKey)if(b.preventDefault(),j.shortcutPropagation||b.stopPropagation(),"enter"===c||"space"===c){if(j.isDisabled(j.activeDate))return;a.select(j.activeDate)}else!b.ctrlKey||"up"!==c&&"down"!==c?(j.handleKeyDown(c,b),j.refreshView()):a.toggleMode("up"===c?1:-1)}}]).directive("datepicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/datepicker.html"},scope:{datepickerMode:"=?",dateDisabled:"&",customClass:"&",shortcutPropagation:"&?"},require:["datepicker","^ngModel"],controller:"DatepickerController",controllerAs:"datepicker",link:function(c,d,e,f){b||a.warn("datepicker is now deprecated. Use uib-datepicker instead.");var g=f[0],h=f[1];g.init(h)}}}]).directive("daypicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/day.html",require:["^datepicker","daypicker"],controller:"UibDaypickerController",link:function(c,d,e,f){b||a.warn("daypicker is now deprecated. Use uib-daypicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("monthpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/month.html",require:["^datepicker","monthpicker"],controller:"UibMonthpickerController",link:function(c,d,e,f){b||a.warn("monthpicker is now deprecated. Use uib-monthpicker instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("yearpicker",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,templateUrl:"template/datepicker/year.html",require:["^datepicker","yearpicker"],controller:"UibYearpickerController",link:function(c,d,e,f){b||a.warn("yearpicker is now deprecated. Use uib-yearpicker instead.");var g=f[0];angular.extend(g,f[1]),g.yearpickerInit(),g.refreshView()}}}]).directive("datepickerPopup",["$log","$datepickerSuppressWarning",function(a,b){return{require:["ngModel","datepickerPopup"],controller:"UibDatepickerPopupController",scope:{isOpen:"=?",currentText:"@",clearText:"@",closeText:"@",dateDisabled:"&",customClass:"&"},link:function(c,d,e,f){b||a.warn("datepicker-popup is now deprecated. Use uib-datepicker-popup instead.");var g=f[0],h=f[1];h.init(g)}}}]).directive("datepickerPopupWrap",["$log","$datepickerSuppressWarning",function(a,b){return{replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/datepicker/popup.html"},link:function(){b||a.warn("datepicker-popup-wrap is now deprecated. Use uib-datepicker-popup-wrap instead.")}}}]),angular.module("ui.bootstrap.dropdown",["ui.bootstrap.position"]).constant("uibDropdownConfig",{openClass:"open"}).service("uibDropdownService",["$document","$rootScope",function(a,b){var c=null;this.open=function(b){c||(a.bind("click",d),a.bind("keydown",e)),c&&c!==b&&(c.isOpen=!1),c=b},this.close=function(b){c===b&&(c=null,a.unbind("click",d),a.unbind("keydown",e))};var d=function(a){if(c&&(!a||"disabled"!==c.getAutoClose())){var d=c.getToggleElement();if(!(a&&d&&d[0].contains(a.target))){var e=c.getDropdownElement();a&&"outsideClick"===c.getAutoClose()&&e&&e[0].contains(a.target)||(c.isOpen=!1,b.$$phase||c.$apply())}}},e=function(a){27===a.which?(c.focusToggleElement(),d()):c.isKeynavEnabled()&&/(38|40)/.test(a.which)&&c.isOpen&&(a.preventDefault(),a.stopPropagation(),c.focusDropdownEntry(a.which))}}]).controller("UibDropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest",function(a,b,c,d,e,f,g,h,i,j,k){var l,m,n=this,o=a.$new(),p=e.openClass,q=angular.noop,r=c.onToggle?d(c.onToggle):angular.noop,s=!1,t=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(m=d(c.isOpen),q=m.assign,a.$watch(m,function(a){o.isOpen=!!a})),s=angular.isDefined(c.dropdownAppendToBody),t=angular.isDefined(c.uibKeyboardNav),s&&n.dropdownMenu&&(i.find("body").append(n.dropdownMenu),b.on("$destroy",function(){n.dropdownMenu.remove()}))},this.toggle=function(a){return o.isOpen=arguments.length?!!a:!o.isOpen},this.isOpen=function(){return o.isOpen},o.getToggleElement=function(){return n.toggleElement},o.getAutoClose=function(){return c.autoClose||"always"},o.getElement=function(){return b},o.isKeynavEnabled=function(){return t},o.focusDropdownEntry=function(a){var c=n.dropdownMenu?angular.element(n.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(n.selectedOption)?n.selectedOption=n.selectedOption===c.length-1?n.selectedOption:n.selectedOption+1:n.selectedOption=0;break;case 38:angular.isNumber(n.selectedOption)?n.selectedOption=0===n.selectedOption?0:n.selectedOption-1:n.selectedOption=c.length-1}c[n.selectedOption].focus()},o.getDropdownElement=function(){return n.dropdownMenu},o.focusToggleElement=function(){n.toggleElement&&n.toggleElement[0].focus()},o.$watch("isOpen",function(c,d){if(s&&n.dropdownMenu){var e=h.positionElements(b,n.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},m=n.dropdownMenu.hasClass("dropdown-menu-right");m?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),n.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,p).then(function(){angular.isDefined(c)&&c!==d&&r(a,{open:!!c})}),c)n.dropdownMenuTemplateUrl&&k(n.dropdownMenuTemplateUrl).then(function(a){l=o.$new(),j(a.trim())(l,function(a){var b=a;n.dropdownMenu.replaceWith(b),n.dropdownMenu=b})}),o.focusToggleElement(),f.open(o);else{if(n.dropdownMenuTemplateUrl){l&&l.$destroy();var t=angular.element('<ul class="dropdown-menu"></ul>');n.dropdownMenu.replaceWith(t),n.dropdownMenu=t}f.close(o),n.selectedOption=null}angular.isFunction(q)&&q(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==o.getAutoClose()&&(o.isOpen=!1)});var u=a.$on("$destroy",function(){o.$destroy()});o.$on("$destroy",u)}]).directive("uibDropdown",function(){return{controller:"UibDropdownController",link:function(a,b,c,d){d.init()}}}).directive("uibDropdownMenu",function(){return{restrict:"AC",require:"?^uibDropdown",link:function(a,b,c,d){if(d&&!angular.isDefined(c.dropdownNested)){b.addClass("dropdown-menu");var e=c.templateUrl;e&&(d.dropdownMenuTemplateUrl=e),d.dropdownMenu||(d.dropdownMenu=b)}}}}).directive("uibKeyboardNav",function(){return{restrict:"A",require:"?^uibDropdown",link:function(a,b,c,d){b.bind("keydown",function(a){if(-1!==[38,40].indexOf(a.which)){a.preventDefault(),a.stopPropagation();var b=d.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(d.selectedOption)?d.selectedOption=d.selectedOption===b.length-1?d.selectedOption:d.selectedOption+1:d.selectedOption=0;break;case 38:angular.isNumber(d.selectedOption)?d.selectedOption=0===d.selectedOption?0:d.selectedOption-1:d.selectedOption=b.length-1}b[d.selectedOption].focus()}})}}}).directive("uibDropdownToggle",function(){return{require:"?^uibDropdown",link:function(a,b,c,d){if(d){b.addClass("dropdown-toggle"),d.toggleElement=b;var e=function(e){e.preventDefault(),b.hasClass("disabled")||c.disabled||a.$apply(function(){d.toggle()})};b.bind("click",e),b.attr({"aria-haspopup":!0,"aria-expanded":!1}),a.$watch(d.isOpen,function(a){b.attr("aria-expanded",!!a)}),a.$on("$destroy",function(){b.unbind("click",e)})}}}}),angular.module("ui.bootstrap.dropdown").value("$dropdownSuppressWarning",!1).service("dropdownService",["$log","$dropdownSuppressWarning","uibDropdownService",function(a,b,c){b||a.warn("dropdownService is now deprecated. Use uibDropdownService instead."),angular.extend(this,c)}]).controller("DropdownController",["$scope","$element","$attrs","$parse","uibDropdownConfig","uibDropdownService","$animate","$uibPosition","$document","$compile","$templateRequest","$log","$dropdownSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l,m){m||l.warn("DropdownController is now deprecated. Use UibDropdownController instead.");var n,o,p=this,q=a.$new(),r=e.openClass,s=angular.noop,t=c.onToggle?d(c.onToggle):angular.noop,u=!1,v=!1;b.addClass("dropdown"),this.init=function(){c.isOpen&&(o=d(c.isOpen),s=o.assign,a.$watch(o,function(a){q.isOpen=!!a})),u=angular.isDefined(c.dropdownAppendToBody),v=angular.isDefined(c.uibKeyboardNav),u&&p.dropdownMenu&&(i.find("body").append(p.dropdownMenu),b.on("$destroy",function(){p.dropdownMenu.remove()}))},this.toggle=function(a){return q.isOpen=arguments.length?!!a:!q.isOpen},this.isOpen=function(){return q.isOpen},q.getToggleElement=function(){return p.toggleElement},q.getAutoClose=function(){return c.autoClose||"always"},q.getElement=function(){return b},q.isKeynavEnabled=function(){return v},q.focusDropdownEntry=function(a){var c=p.dropdownMenu?angular.element(p.dropdownMenu).find("a"):angular.element(b).find("ul").eq(0).find("a");switch(a){case 40:angular.isNumber(p.selectedOption)?p.selectedOption=p.selectedOption===c.length-1?p.selectedOption:p.selectedOption+1:p.selectedOption=0;break;case 38:angular.isNumber(p.selectedOption)?p.selectedOption=0===p.selectedOption?0:p.selectedOption-1:p.selectedOption=c.length-1}c[p.selectedOption].focus()},q.getDropdownElement=function(){return p.dropdownMenu},q.focusToggleElement=function(){p.toggleElement&&p.toggleElement[0].focus()},q.$watch("isOpen",function(c,d){if(u&&p.dropdownMenu){var e=h.positionElements(b,p.dropdownMenu,"bottom-left",!0),i={top:e.top+"px",display:c?"block":"none"},l=p.dropdownMenu.hasClass("dropdown-menu-right");l?(i.left="auto",i.right=window.innerWidth-(e.left+b.prop("offsetWidth"))+"px"):(i.left=e.left+"px",i.right="auto"),p.dropdownMenu.css(i)}if(g[c?"addClass":"removeClass"](b,r).then(function(){angular.isDefined(c)&&c!==d&&t(a,{open:!!c})}),c)p.dropdownMenuTemplateUrl&&k(p.dropdownMenuTemplateUrl).then(function(a){n=q.$new(),j(a.trim())(n,function(a){var b=a;p.dropdownMenu.replaceWith(b),p.dropdownMenu=b})}),q.focusToggleElement(),f.open(q);else{if(p.dropdownMenuTemplateUrl){n&&n.$destroy();var m=angular.element('<ul class="dropdown-menu"></ul>');p.dropdownMenu.replaceWith(m),p.dropdownMenu=m}f.close(q),p.selectedOption=null}angular.isFunction(s)&&s(a,c)}),a.$on("$locationChangeSuccess",function(){"disabled"!==q.getAutoClose()&&(q.isOpen=!1)});var w=a.$on("$destroy",function(){q.$destroy()});q.$on("$destroy",w)}]).directive("dropdown",["$log","$dropdownSuppressWarning",function(a,b){return{controller:"DropdownController",link:function(c,d,e,f){b||a.warn("dropdown is now deprecated. Use uib-dropdown instead."),f.init()}}}]).directive("dropdownMenu",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"AC",require:"?^dropdown",link:function(c,d,e,f){if(f&&!angular.isDefined(e.dropdownNested)){b||a.warn("dropdown-menu is now deprecated. Use uib-dropdown-menu instead."),d.addClass("dropdown-menu");var g=e.templateUrl;g&&(f.dropdownMenuTemplateUrl=g),f.dropdownMenu||(f.dropdownMenu=d)}}}}]).directive("keyboardNav",["$log","$dropdownSuppressWarning",function(a,b){return{restrict:"A",require:"?^dropdown",link:function(c,d,e,f){b||a.warn("keyboard-nav is now deprecated. Use uib-keyboard-nav instead."),d.bind("keydown",function(a){if(-1!==[38,40].indexOf(a.which)){a.preventDefault(),a.stopPropagation();var b=f.dropdownMenu.find("a");switch(a.which){case 40:angular.isNumber(f.selectedOption)?f.selectedOption=f.selectedOption===b.length-1?f.selectedOption:f.selectedOption+1:f.selectedOption=0;break;case 38:angular.isNumber(f.selectedOption)?f.selectedOption=0===f.selectedOption?0:f.selectedOption-1:f.selectedOption=b.length-1}b[f.selectedOption].focus()}})}}}]).directive("dropdownToggle",["$log","$dropdownSuppressWarning",function(a,b){return{require:"?^dropdown",link:function(c,d,e,f){if(b||a.warn("dropdown-toggle is now deprecated. Use uib-dropdown-toggle instead."),f){d.addClass("dropdown-toggle"),f.toggleElement=d;var g=function(a){a.preventDefault(),d.hasClass("disabled")||e.disabled||c.$apply(function(){f.toggle()})};d.bind("click",g),d.attr({"aria-haspopup":!0,"aria-expanded":!1}),c.$watch(f.isOpen,function(a){d.attr("aria-expanded",!!a)}),c.$on("$destroy",function(){d.unbind("click",g)})}}}}]),angular.module("ui.bootstrap.stackedMap",[]).factory("$$stackedMap",function(){return{createNew:function(){var a=[];return{add:function(b,c){a.push({key:b,value:c})},get:function(b){for(var c=0;c<a.length;c++)if(b==a[c].key)return a[c]},keys:function(){for(var b=[],c=0;c<a.length;c++)b.push(a[c].key);return b},top:function(){return a[a.length-1]},remove:function(b){for(var c=-1,d=0;d<a.length;d++)if(b==a[d].key){c=d;break}return a.splice(c,1)[0]},removeTop:function(){return a.splice(a.length-1,1)[0]},length:function(){return a.length}}}}}),angular.module("ui.bootstrap.modal",["ui.bootstrap.stackedMap"]).factory("$$multiMap",function(){return{createNew:function(){var a={};return{entries:function(){return Object.keys(a).map(function(b){return{key:b,value:a[b]}})},get:function(b){return a[b]},hasKey:function(b){return!!a[b]},keys:function(){return Object.keys(a)},put:function(b,c){a[b]||(a[b]=[]),a[b].push(c)},remove:function(b,c){var d=a[b];if(d){var e=d.indexOf(c);-1!==e&&d.splice(e,1),d.length||delete a[b]}}}}}}).directive("uibModalBackdrop",["$animate","$injector","$uibModalStack",function(a,b,c){function d(b,d,f){d.addClass("modal-backdrop"),f.modalInClass&&(e?e(d,{addClass:f.modalInClass}).start():a.addClass(d,f.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(b,c){var g=c();e?e(d,{removeClass:f.modalInClass}).start().then(g):a.removeClass(d,f.modalInClass).then(g)}))}var e=null;return b.has("$animateCss")&&(e=b.get("$animateCss")),{replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,b){return a.addClass(b.backdropClass),d}}}]).directive("uibModalWindow",["$uibModalStack","$q","$animate","$injector",function(a,b,c,d){var e=null;return d.has("$animateCss")&&(e=d.get("$animateCss")),{scope:{index:"@"},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(d,f,g){f.addClass(g.windowClass||""),f.addClass(g.windowTopClass||""),d.size=g.size,d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},f.on("click",d.close),d.$isRendered=!0;var h=b.defer();g.$observe("modalRender",function(a){"true"==a&&h.resolve()}),h.promise.then(function(){var h=null;g.modalInClass&&(h=e?e(f,{addClass:g.modalInClass}).start():c.addClass(f,g.modalInClass),d.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();e?e(f,{removeClass:g.modalInClass}).start().then(d):c.removeClass(f,g.modalInClass).then(d)})),b.when(h).then(function(){var a=f[0].querySelector("[autofocus]");a?a.focus():f[0].focus()});var i=a.getTop();i&&a.modalRendered(i.key)})}}}]).directive("uibModalAnimationClass",function(){return{compile:function(a,b){b.modalAnimation&&a.addClass(b.uibModalAnimationClass)}}}).directive("uibModalTransclude",function(){return{link:function(a,b,c,d,e){e(a.$parent,function(a){b.empty(),b.append(a)})}}}).factory("$uibModalStack",["$animate","$timeout","$document","$compile","$rootScope","$q","$injector","$$multiMap","$$stackedMap",function(a,b,c,d,e,f,g,h,i){function j(){for(var a=-1,b=u.keys(),c=0;c<b.length;c++)u.get(b[c]).value.backdrop&&(a=c);return a}function k(a,b){var d=c.find("body").eq(0),e=u.get(a).value;u.remove(a),n(e.modalDomEl,e.modalScope,function(){var b=e.openedClass||t;v.remove(b,a),d.toggleClass(b,v.hasKey(b)),l(!0)}),m(),b&&b.focus?b.focus():d.focus()}function l(a){var b;u.length()>0&&(b=u.top().value,b.modalDomEl.toggleClass(b.windowTopClass||"",a))}function m(){if(q&&-1==j()){var a=r;n(q,r,function(){a=null}),q=void 0,r=void 0}}function n(b,c,d){function e(){e.done||(e.done=!0,p?p(b,{event:"leave"}).start().then(function(){b.remove()}):a.leave(b),c.$destroy(),d&&d())}var g,h=null,i=function(){return g||(g=f.defer(),h=g.promise),function(){g.resolve()}};return c.$broadcast(w.NOW_CLOSING_EVENT,i),f.when(h).then(e)}function o(a,b,c){return!a.value.modalScope.$broadcast("modal.closing",b,c).defaultPrevented}var p=null;g.has("$animateCss")&&(p=g.get("$animateCss"));var q,r,s,t="modal-open",u=i.createNew(),v=h.createNew(),w={NOW_CLOSING_EVENT:"modal.stack.now-closing"},x=0,y="a[href], area[href], input:not([disabled]), button:not([disabled]),select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable=true]";return e.$watch(j,function(a){r&&(r.index=a)}),c.bind("keydown",function(a){if(a.isDefaultPrevented())return a;var b=u.top();if(b&&b.value.keyboard)switch(a.which){case 27:a.preventDefault(),e.$apply(function(){w.dismiss(b.key,"escape key press")});break;case 9:w.loadFocusElementList(b);var c=!1;a.shiftKey?w.isFocusInFirstItem(a)&&(c=w.focusLastFocusableElement()):w.isFocusInLastItem(a)&&(c=w.focusFirstFocusableElement()),c&&(a.preventDefault(),a.stopPropagation())}}),w.open=function(a,b){var f=c[0].activeElement,g=b.openedClass||t;l(!1),u.add(a,{deferred:b.deferred,renderDeferred:b.renderDeferred,modalScope:b.scope,backdrop:b.backdrop,keyboard:b.keyboard,openedClass:b.openedClass,windowTopClass:b.windowTopClass}),v.put(g,a);var h=c.find("body").eq(0),i=j();if(i>=0&&!q){r=e.$new(!0),r.index=i;var k=angular.element('<div uib-modal-backdrop="modal-backdrop"></div>');k.attr("backdrop-class",b.backdropClass),b.animation&&k.attr("modal-animation","true"),q=d(k)(r),h.append(q)}var m=angular.element('<div uib-modal-window="modal-window"></div>');m.attr({"template-url":b.windowTemplateUrl,"window-class":b.windowClass,"window-top-class":b.windowTopClass,size:b.size,index:u.length()-1,animate:"animate"}).html(b.content),b.animation&&m.attr("modal-animation","true");var n=d(m)(b.scope);u.top().value.modalDomEl=n,u.top().value.modalOpener=f,h.append(n),h.addClass(g),w.clearFocusListCache()},w.close=function(a,b){var c=u.get(a);return c&&o(c,b,!0)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.resolve(b),k(a,c.value.modalOpener),!0):!c},w.dismiss=function(a,b){var c=u.get(a);return c&&o(c,b,!1)?(c.value.modalScope.$$uibDestructionScheduled=!0,c.value.deferred.reject(b),k(a,c.value.modalOpener),!0):!c},w.dismissAll=function(a){for(var b=this.getTop();b&&this.dismiss(b.key,a);)b=this.getTop()},w.getTop=function(){return u.top()},w.modalRendered=function(a){var b=u.get(a);b&&b.value.renderDeferred.resolve()},w.focusFirstFocusableElement=function(){return s.length>0?(s[0].focus(),!0):!1},w.focusLastFocusableElement=function(){return s.length>0?(s[s.length-1].focus(),!0):!1},w.isFocusInFirstItem=function(a){return s.length>0?(a.target||a.srcElement)==s[0]:!1},w.isFocusInLastItem=function(a){return s.length>0?(a.target||a.srcElement)==s[s.length-1]:!1},w.clearFocusListCache=function(){s=[],x=0},w.loadFocusElementList=function(a){if((void 0===s||!s.length)&&a){var b=a.value.modalDomEl;b&&b.length&&(s=b[0].querySelectorAll(y))}},w}]).provider("$uibModal",function(){var a={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$injector","$rootScope","$q","$templateRequest","$controller","$uibModalStack","$modalSuppressWarning","$log",function(b,c,d,e,f,g,h,i){function j(a){return a.template?d.when(a.template):e(angular.isFunction(a.templateUrl)?a.templateUrl():a.templateUrl)}function k(a){var c=[];return angular.forEach(a,function(a){angular.isFunction(a)||angular.isArray(a)?c.push(d.when(b.invoke(a))):angular.isString(a)?c.push(d.when(b.get(a))):c.push(d.when(a))}),c}var l={},m=null;return l.getPromiseChain=function(){return m},l.open=function(b){function e(){return r}var l=d.defer(),n=d.defer(),o=d.defer(),p={result:l.promise,opened:n.promise,rendered:o.promise,close:function(a){return g.close(p,a)},dismiss:function(a){return g.dismiss(p,a)}};if(b=angular.extend({},a.options,b),b.resolve=b.resolve||{},!b.template&&!b.templateUrl)throw new Error("One of template or templateUrl options is required.");var q,r=d.all([j(b)].concat(k(b.resolve)));return q=m=d.all([m]).then(e,e).then(function(a){var d=(b.scope||c).$new();d.$close=p.close,d.$dismiss=p.dismiss,d.$on("$destroy",function(){d.$$uibDestructionScheduled||d.$dismiss("$uibUnscheduledDestruction")});var e,j={},k=1;b.controller&&(j.$scope=d,j.$uibModalInstance=p,Object.defineProperty(j,"$modalInstance",{get:function(){return h||i.warn("$modalInstance is now deprecated. Use $uibModalInstance instead."),p}}),angular.forEach(b.resolve,function(b,c){j[c]=a[k++]}),e=f(b.controller,j),b.controllerAs&&(b.bindToController&&angular.extend(e,d),d[b.controllerAs]=e)),g.open(p,{scope:d,deferred:l,renderDeferred:o,content:a[0],animation:b.animation,backdrop:b.backdrop,keyboard:b.keyboard,backdropClass:b.backdropClass,windowTopClass:b.windowTopClass,windowClass:b.windowClass,windowTemplateUrl:b.windowTemplateUrl,size:b.size,openedClass:b.openedClass}),n.resolve(!0)},function(a){n.reject(a),l.reject(a)})["finally"](function(){m===q&&(m=null)}),p},l}]};return a}),angular.module("ui.bootstrap.modal").value("$modalSuppressWarning",!1).directive("modalBackdrop",["$animate","$injector","$modalStack","$log","$modalSuppressWarning",function(a,b,c,d,e){function f(b,f,h){e||d.warn("modal-backdrop is now deprecated. Use uib-modal-backdrop instead."),f.addClass("modal-backdrop"),h.modalInClass&&(g?g(f,{addClass:h.modalInClass}).start():a.addClass(f,h.modalInClass),b.$on(c.NOW_CLOSING_EVENT,function(b,c){var d=c();g?g(f,{removeClass:h.modalInClass}).start().then(d):a.removeClass(f,h.modalInClass).then(d)}))}var g=null;return b.has("$animateCss")&&(g=b.get("$animateCss")),{replace:!0,templateUrl:"template/modal/backdrop.html",compile:function(a,b){return a.addClass(b.backdropClass),f}}}]).directive("modalWindow",["$modalStack","$q","$animate","$injector","$log","$modalSuppressWarning",function(a,b,c,d,e,f){var g=null;return d.has("$animateCss")&&(g=d.get("$animateCss")),{scope:{index:"@"},replace:!0,transclude:!0,templateUrl:function(a,b){return b.templateUrl||"template/modal/window.html"},link:function(d,h,i){f||e.warn("modal-window is now deprecated. Use uib-modal-window instead."),h.addClass(i.windowClass||""),h.addClass(i.windowTopClass||""),d.size=i.size,d.close=function(b){var c=a.getTop();c&&c.value.backdrop&&"static"!==c.value.backdrop&&b.target===b.currentTarget&&(b.preventDefault(),b.stopPropagation(),a.dismiss(c.key,"backdrop click"))},h.on("click",d.close),d.$isRendered=!0;var j=b.defer();i.$observe("modalRender",function(a){"true"==a&&j.resolve()}),j.promise.then(function(){var e=null;i.modalInClass&&(e=g?g(h,{addClass:i.modalInClass}).start():c.addClass(h,i.modalInClass),d.$on(a.NOW_CLOSING_EVENT,function(a,b){var d=b();g?g(h,{removeClass:i.modalInClass}).start().then(d):c.removeClass(h,i.modalInClass).then(d)})),b.when(e).then(function(){var a=h[0].querySelector("[autofocus]");a?a.focus():h[0].focus()});var f=a.getTop();f&&a.modalRendered(f.key)})}}}]).directive("modalAnimationClass",["$log","$modalSuppressWarning",function(a,b){return{compile:function(c,d){b||a.warn("modal-animation-class is now deprecated. Use uib-modal-animation-class instead."),d.modalAnimation&&c.addClass(d.modalAnimationClass)}}}]).directive("modalTransclude",["$log","$modalSuppressWarning",function(a,b){return{link:function(c,d,e,f,g){
b||a.warn("modal-transclude is now deprecated. Use uib-modal-transclude instead."),g(c.$parent,function(a){d.empty(),d.append(a)})}}}]).service("$modalStack",["$animate","$timeout","$document","$compile","$rootScope","$q","$injector","$$multiMap","$$stackedMap","$uibModalStack","$log","$modalSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k,l){l||k.warn("$modalStack is now deprecated. Use $uibModalStack instead."),angular.extend(this,j)}]).provider("$modal",["$uibModalProvider",function(a){angular.extend(this,a),this.$get=["$injector","$log","$modalSuppressWarning",function(b,c,d){return d||c.warn("$modal is now deprecated. Use $uibModal instead."),b.invoke(a.$get)}]}]),angular.module("ui.bootstrap.pagination",[]).controller("UibPaginationController",["$scope","$attrs","$parse",function(a,b,c){var d=this,e={$setViewValue:angular.noop},f=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(g,h){e=g,this.config=h,e.$render=function(){d.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){d.itemsPerPage=parseInt(b,10),a.totalPages=d.calculateTotalPages()}):this.itemsPerPage=h.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=d.calculateTotalPages()}),a.$watch("totalPages",function(b){f(a.$parent,b),a.page>b?a.selectPage(b):e.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(e.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),e.$setViewValue(b),e.$render())},a.getText=function(b){return a[b+"Text"]||d.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).constant("uibPaginationConfig",{itemsPerPage:10,boundaryLinks:!1,directionLinks:!0,firstText:"First",previousText:"Previous",nextText:"Next",lastText:"Last",rotate:!0}).directive("uibPagination",["$parse","uibPaginationConfig",function(a,b){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["uibPagination","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(c,d,e,f){function g(a,b,c){return{number:a,text:b,active:c}}function h(a,b){var c=[],d=1,e=b,f=angular.isDefined(k)&&b>k;f&&(l?(d=Math.max(a-Math.floor(k/2),1),e=d+k-1,e>b&&(e=b,d=e-k+1)):(d=(Math.ceil(a/k)-1)*k+1,e=Math.min(d+k-1,b)));for(var h=d;e>=h;h++){var i=g(h,h,h===a);c.push(i)}if(f&&!l){if(d>1){var j=g(d-1,"...",!1);c.unshift(j)}if(b>e){var m=g(e+1,"...",!1);c.push(m)}}return c}var i=f[0],j=f[1];if(j){var k=angular.isDefined(e.maxSize)?c.$parent.$eval(e.maxSize):b.maxSize,l=angular.isDefined(e.rotate)?c.$parent.$eval(e.rotate):b.rotate;c.boundaryLinks=angular.isDefined(e.boundaryLinks)?c.$parent.$eval(e.boundaryLinks):b.boundaryLinks,c.directionLinks=angular.isDefined(e.directionLinks)?c.$parent.$eval(e.directionLinks):b.directionLinks,i.init(j,b),e.maxSize&&c.$parent.$watch(a(e.maxSize),function(a){k=parseInt(a,10),i.render()});var m=i.render;i.render=function(){m(),c.page>0&&c.page<=c.totalPages&&(c.pages=h(c.page,c.totalPages))}}}}}]).constant("uibPagerConfig",{itemsPerPage:10,previousText:"« Previous",nextText:"Next »",align:!0}).directive("uibPager",["uibPagerConfig",function(a){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["uibPager","?ngModel"],controller:"UibPaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(b,c,d,e){var f=e[0],g=e[1];g&&(b.align=angular.isDefined(d.align)?b.$parent.$eval(d.align):a.align,f.init(g,a))}}}]),angular.module("ui.bootstrap.pagination").value("$paginationSuppressWarning",!1).controller("PaginationController",["$scope","$attrs","$parse","$log","$paginationSuppressWarning",function(a,b,c,d,e){e||d.warn("PaginationController is now deprecated. Use UibPaginationController instead.");var f=this,g={$setViewValue:angular.noop},h=b.numPages?c(b.numPages).assign:angular.noop;this.init=function(d,e){g=d,this.config=e,g.$render=function(){f.render()},b.itemsPerPage?a.$parent.$watch(c(b.itemsPerPage),function(b){f.itemsPerPage=parseInt(b,10),a.totalPages=f.calculateTotalPages()}):this.itemsPerPage=e.itemsPerPage,a.$watch("totalItems",function(){a.totalPages=f.calculateTotalPages()}),a.$watch("totalPages",function(b){h(a.$parent,b),a.page>b?a.selectPage(b):g.$render()})},this.calculateTotalPages=function(){var b=this.itemsPerPage<1?1:Math.ceil(a.totalItems/this.itemsPerPage);return Math.max(b||0,1)},this.render=function(){a.page=parseInt(g.$viewValue,10)||1},a.selectPage=function(b,c){c&&c.preventDefault();var d=!a.ngDisabled||!c;d&&a.page!==b&&b>0&&b<=a.totalPages&&(c&&c.target&&c.target.blur(),g.$setViewValue(b),g.$render())},a.getText=function(b){return a[b+"Text"]||f.config[b+"Text"]},a.noPrevious=function(){return 1===a.page},a.noNext=function(){return a.page===a.totalPages}}]).directive("pagination",["$parse","uibPaginationConfig","$log","$paginationSuppressWarning",function(a,b,c,d){return{restrict:"EA",scope:{totalItems:"=",firstText:"@",previousText:"@",nextText:"@",lastText:"@",ngDisabled:"="},require:["pagination","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pagination.html"},replace:!0,link:function(e,f,g,h){function i(a,b,c){return{number:a,text:b,active:c}}function j(a,b){var c=[],d=1,e=b,f=angular.isDefined(m)&&b>m;f&&(n?(d=Math.max(a-Math.floor(m/2),1),e=d+m-1,e>b&&(e=b,d=e-m+1)):(d=(Math.ceil(a/m)-1)*m+1,e=Math.min(d+m-1,b)));for(var g=d;e>=g;g++){var h=i(g,g,g===a);c.push(h)}if(f&&!n){if(d>1){var j=i(d-1,"...",!1);c.unshift(j)}if(b>e){var k=i(e+1,"...",!1);c.push(k)}}return c}d||c.warn("pagination is now deprecated. Use uib-pagination instead.");var k=h[0],l=h[1];if(l){var m=angular.isDefined(g.maxSize)?e.$parent.$eval(g.maxSize):b.maxSize,n=angular.isDefined(g.rotate)?e.$parent.$eval(g.rotate):b.rotate;e.boundaryLinks=angular.isDefined(g.boundaryLinks)?e.$parent.$eval(g.boundaryLinks):b.boundaryLinks,e.directionLinks=angular.isDefined(g.directionLinks)?e.$parent.$eval(g.directionLinks):b.directionLinks,k.init(l,b),g.maxSize&&e.$parent.$watch(a(g.maxSize),function(a){m=parseInt(a,10),k.render()});var o=k.render;k.render=function(){o(),e.page>0&&e.page<=e.totalPages&&(e.pages=j(e.page,e.totalPages))}}}}}]).directive("pager",["uibPagerConfig","$log","$paginationSuppressWarning",function(a,b,c){return{restrict:"EA",scope:{totalItems:"=",previousText:"@",nextText:"@",ngDisabled:"="},require:["pager","?ngModel"],controller:"PaginationController",controllerAs:"pagination",templateUrl:function(a,b){return b.templateUrl||"template/pagination/pager.html"},replace:!0,link:function(d,e,f,g){c||b.warn("pager is now deprecated. Use uib-pager instead.");var h=g[0],i=g[1];i&&(d.align=angular.isDefined(f.align)?d.$parent.$eval(f.align):a.align,h.init(i,a))}}}]),angular.module("ui.bootstrap.tooltip",["ui.bootstrap.position","ui.bootstrap.stackedMap"]).provider("$uibTooltip",function(){function a(a){var b=/[A-Z]/g,c="-";return a.replace(b,function(a,b){return(b?c:"")+a.toLowerCase()})}var b={placement:"top",animation:!0,popupDelay:0,popupCloseDelay:0,useContentExp:!1},c={mouseenter:"mouseleave",click:"click",focus:"blur",none:""},d={};this.options=function(a){angular.extend(d,a)},this.setTriggers=function(a){angular.extend(c,a)},this.$get=["$window","$compile","$timeout","$document","$uibPosition","$interpolate","$rootScope","$parse","$$stackedMap",function(e,f,g,h,i,j,k,l,m){var n=m.createNew();return h.on("keypress",function(a){if(27===a.which){var b=n.top();b&&(b.value.close(),n.removeTop(),b=null)}}),function(e,k,m,o){function p(a){var b=(a||o.trigger||m).split(" "),d=b.map(function(a){return c[a]||a});return{show:b,hide:d}}o=angular.extend({},b,d,o);var q=a(e),r=j.startSymbol(),s=j.endSymbol(),t="<div "+q+'-popup title="'+r+"title"+s+'" '+(o.useContentExp?'content-exp="contentExp()" ':'content="'+r+"content"+s+'" ')+'placement="'+r+"placement"+s+'" popup-class="'+r+"popupClass"+s+'" animation="animation" is-open="isOpen"origin-scope="origScope" style="visibility: hidden; display: block; top: -9999px; left: -9999px;"></div>';return{compile:function(a,b){var c=f(t);return function(a,b,d,f){function j(){L.isOpen?q():m()}function m(){(!K||a.$eval(d[k+"Enable"]))&&(u(),x(),L.popupDelay?F||(F=g(r,L.popupDelay,!1)):r())}function q(){s(),L.popupCloseDelay?G||(G=g(t,L.popupCloseDelay,!1)):t()}function r(){return s(),u(),L.content?(v(),void L.$evalAsync(function(){L.isOpen=!0,y(!0),Q()})):angular.noop}function s(){F&&(g.cancel(F),F=null),H&&(g.cancel(H),H=null)}function t(){s(),u(),L&&L.$evalAsync(function(){L.isOpen=!1,y(!1),L.animation?E||(E=g(w,150,!1)):w()})}function u(){G&&(g.cancel(G),G=null),E&&(g.cancel(E),E=null)}function v(){C||(D=L.$new(),C=c(D,function(a){I?h.find("body").append(a):b.after(a)}),z())}function w(){A(),E=null,C&&(C.remove(),C=null),D&&(D.$destroy(),D=null)}function x(){L.title=d[k+"Title"],O?L.content=O(a):L.content=d[e],L.popupClass=d[k+"Class"],L.placement=angular.isDefined(d[k+"Placement"])?d[k+"Placement"]:o.placement;var b=parseInt(d[k+"PopupDelay"],10),c=parseInt(d[k+"PopupCloseDelay"],10);L.popupDelay=isNaN(b)?o.popupDelay:b,L.popupCloseDelay=isNaN(c)?o.popupCloseDelay:c}function y(b){N&&angular.isFunction(N.assign)&&N.assign(a,b)}function z(){P.length=0,O?(P.push(a.$watch(O,function(a){L.content=a,!a&&L.isOpen&&t()})),P.push(D.$watch(function(){M||(M=!0,D.$$postDigest(function(){M=!1,L&&L.isOpen&&Q()}))}))):P.push(d.$observe(e,function(a){L.content=a,!a&&L.isOpen?t():Q()})),P.push(d.$observe(k+"Title",function(a){L.title=a,L.isOpen&&Q()})),P.push(d.$observe(k+"Placement",function(a){L.placement=a?a:o.placement,L.isOpen&&Q()}))}function A(){P.length&&(angular.forEach(P,function(a){a()}),P.length=0)}function B(){var a=d[k+"Trigger"];R(),J=p(a),"none"!==J.show&&J.show.forEach(function(a,c){a===J.hide[c]?b[0].addEventListener(a,j):a&&(b[0].addEventListener(a,m),J.hide[c].split(" ").forEach(function(a){b[0].addEventListener(a,q)})),b.on("keypress",function(a){27===a.which&&q()})})}var C,D,E,F,G,H,I=angular.isDefined(o.appendToBody)?o.appendToBody:!1,J=p(void 0),K=angular.isDefined(d[k+"Enable"]),L=a.$new(!0),M=!1,N=angular.isDefined(d[k+"IsOpen"])?l(d[k+"IsOpen"]):!1,O=o.useContentExp?l(d[e]):!1,P=[],Q=function(){C&&C.html()&&(H||(H=g(function(){C.css({top:0,left:0});var a=i.positionElements(b,C,L.placement,I);a.top+="px",a.left+="px",a.visibility="visible",C.css(a),H=null},0,!1)))};L.origScope=a,L.isOpen=!1,n.add(L,{close:t}),L.contentExp=function(){return L.content},d.$observe("disabled",function(a){a&&s(),a&&L.isOpen&&t()}),N&&a.$watch(N,function(a){L&&!a===L.isOpen&&j()});var R=function(){J.show.forEach(function(a){b.unbind(a,m)}),J.hide.forEach(function(a){a.split(" ").forEach(function(a){b[0].removeEventListener(a,q)})})};B();var S=a.$eval(d[k+"Animation"]);L.animation=angular.isDefined(S)?!!S:o.animation;var T=a.$eval(d[k+"AppendToBody"]);I=angular.isDefined(T)?T:I,I&&a.$on("$locationChangeSuccess",function(){L.isOpen&&t()}),a.$on("$destroy",function(){s(),u(),R(),w(),n.remove(L),L=null})}}}}}]}).directive("uibTooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest",function(a,b,c,d){return{link:function(e,f,g){var h,i,j,k=e.$eval(g.tooltipTemplateTranscludeScope),l=0,m=function(){i&&(i.remove(),i=null),h&&(h.$destroy(),h=null),j&&(a.leave(j).then(function(){i=null}),i=j,j=null)};e.$watch(b.parseAsResourceUrl(g.uibTooltipTemplateTransclude),function(b){var g=++l;b?(d(b,!0).then(function(d){if(g===l){var e=k.$new(),i=d,n=c(i)(e,function(b){m(),a.enter(b,f)});h=e,j=n,h.$emit("$includeContentLoaded",b)}},function(){g===l&&(m(),e.$emit("$includeContentError",b))}),e.$emit("$includeContentRequested",b)):m()}),e.$on("$destroy",m)}}}]).directive("uibTooltipClasses",function(){return{restrict:"A",link:function(a,b,c){a.placement&&b.addClass(a.placement),a.popupClass&&b.addClass(a.popupClass),a.animation()&&b.addClass(c.tooltipAnimationClass)}}}).directive("uibTooltipPopup",function(){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltip",["$uibTooltip",function(a){return a("uibTooltip","tooltip","mouseenter")}]).directive("uibTooltipTemplatePopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipTemplate",["$uibTooltip",function(a){return a("uibTooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("uibTooltipHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(a,b){b.addClass("tooltip")}}}).directive("uibTooltipHtml",["$uibTooltip",function(a){return a("uibTooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.tooltip").value("$tooltipSuppressWarning",!1).provider("$tooltip",["$uibTooltipProvider",function(a){angular.extend(this,a),this.$get=["$log","$tooltipSuppressWarning","$injector",function(b,c,d){return c||b.warn("$tooltip is now deprecated. Use $uibTooltip instead."),d.invoke(a.$get)}]}]).directive("tooltipTemplateTransclude",["$animate","$sce","$compile","$templateRequest","$log","$tooltipSuppressWarning",function(a,b,c,d,e,f){return{link:function(g,h,i){f||e.warn("tooltip-template-transclude is now deprecated. Use uib-tooltip-template-transclude instead.");var j,k,l,m=g.$eval(i.tooltipTemplateTranscludeScope),n=0,o=function(){k&&(k.remove(),k=null),j&&(j.$destroy(),j=null),l&&(a.leave(l).then(function(){k=null}),k=l,l=null)};g.$watch(b.parseAsResourceUrl(i.tooltipTemplateTransclude),function(b){var e=++n;b?(d(b,!0).then(function(d){if(e===n){var f=m.$new(),g=d,i=c(g)(f,function(b){o(),a.enter(b,h)});j=f,l=i,j.$emit("$includeContentLoaded",b)}},function(){e===n&&(o(),g.$emit("$includeContentError",b))}),g.$emit("$includeContentRequested",b)):o()}),g.$on("$destroy",o)}}}]).directive("tooltipClasses",["$log","$tooltipSuppressWarning",function(a,b){return{restrict:"A",link:function(c,d,e){b||a.warn("tooltip-classes is now deprecated. Use uib-tooltip-classes instead."),c.placement&&d.addClass(c.placement),c.popupClass&&d.addClass(c.popupClass),c.animation()&&d.addClass(e.tooltipAnimationClass)}}}]).directive("tooltipPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-popup.html",link:function(c,d){b||a.warn("tooltip-popup is now deprecated. Use uib-tooltip-popup instead."),d.addClass("tooltip")}}}]).directive("tooltip",["$tooltip",function(a){return a("tooltip","tooltip","mouseenter")}]).directive("tooltipTemplatePopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/tooltip/tooltip-template-popup.html",link:function(c,d){b||a.warn("tooltip-template-popup is now deprecated. Use uib-tooltip-template-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipTemplate",["$tooltip",function(a){return a("tooltipTemplate","tooltip","mouseenter",{useContentExp:!0})}]).directive("tooltipHtmlPopup",["$log","$tooltipSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/tooltip/tooltip-html-popup.html",link:function(c,d){b||a.warn("tooltip-html-popup is now deprecated. Use uib-tooltip-html-popup instead."),d.addClass("tooltip")}}}]).directive("tooltipHtml",["$tooltip",function(a){return a("tooltipHtml","tooltip","mouseenter",{useContentExp:!0})}]),angular.module("ui.bootstrap.popover",["ui.bootstrap.tooltip"]).directive("uibPopoverTemplatePopup",function(){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverTemplate",["$uibTooltip",function(a){return a("uibPopoverTemplate","popover","click",{useContentExp:!0})}]).directive("uibPopoverHtmlPopup",function(){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopoverHtml",["$uibTooltip",function(a){return a("uibPopoverHtml","popover","click",{useContentExp:!0})}]).directive("uibPopoverPopup",function(){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(a,b){b.addClass("popover")}}}).directive("uibPopover",["$uibTooltip",function(a){return a("uibPopover","popover","click")}]),angular.module("ui.bootstrap.popover").value("$popoverSuppressWarning",!1).directive("popoverTemplatePopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",contentExp:"&",placement:"@",popupClass:"@",animation:"&",isOpen:"&",originScope:"&"},templateUrl:"template/popover/popover-template.html",link:function(c,d){b||a.warn("popover-template-popup is now deprecated. Use uib-popover-template-popup instead."),d.addClass("popover")}}}]).directive("popoverTemplate",["$tooltip",function(a){return a("popoverTemplate","popover","click",{useContentExp:!0})}]).directive("popoverHtmlPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{contentExp:"&",title:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover-html.html",link:function(c,d){b||a.warn("popover-html-popup is now deprecated. Use uib-popover-html-popup instead."),d.addClass("popover")}}}]).directive("popoverHtml",["$tooltip",function(a){return a("popoverHtml","popover","click",{useContentExp:!0})}]).directive("popoverPopup",["$log","$popoverSuppressWarning",function(a,b){return{replace:!0,scope:{title:"@",content:"@",placement:"@",popupClass:"@",animation:"&",isOpen:"&"},templateUrl:"template/popover/popover.html",link:function(c,d){b||a.warn("popover-popup is now deprecated. Use uib-popover-popup instead."),d.addClass("popover")}}}]).directive("popover",["$tooltip",function(a){return a("popover","popover","click")}]),angular.module("ui.bootstrap.progressbar",[]).constant("uibProgressConfig",{animate:!0,max:100}).controller("UibProgressController",["$scope","$attrs","uibProgressConfig",function(a,b,c){var d=this,e=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,f){e||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=f&&angular.isDefined(f.title)?f.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){var a=d.bars.reduce(function(a,b){return b.percent=+(100*b.value/b.max).toFixed(2),a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,d.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1),this.bars.forEach(function(a){a.recalculatePercentage()})},a.$watch("max",function(b){d.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("uibProgress",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",require:"uibProgress",scope:{max:"=?"},templateUrl:"template/progressbar/progress.html"}}).directive("uibBar",function(){return{replace:!0,transclude:!0,require:"^uibProgress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(a,b,c,d){d.addBar(a,b,c)}}}).directive("uibProgressbar",function(){return{replace:!0,transclude:!0,controller:"UibProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(a,b,c,d){d.addBar(a,angular.element(b.children()[0]),{title:c.title})}}}),angular.module("ui.bootstrap.progressbar").value("$progressSuppressWarning",!1).controller("ProgressController",["$scope","$attrs","uibProgressConfig","$log","$progressSuppressWarning",function(a,b,c,d,e){e||d.warn("ProgressController is now deprecated. Use UibProgressController instead.");var f=this,g=angular.isDefined(b.animate)?a.$parent.$eval(b.animate):c.animate;this.bars=[],a.max=angular.isDefined(a.max)?a.max:c.max,this.addBar=function(b,c,d){g||c.css({transition:"none"}),this.bars.push(b),b.max=a.max,b.title=d&&angular.isDefined(d.title)?d.title:"progressbar",b.$watch("value",function(a){b.recalculatePercentage()}),b.recalculatePercentage=function(){b.percent=+(100*b.value/b.max).toFixed(2);var a=f.bars.reduce(function(a,b){return a+b.percent},0);a>100&&(b.percent-=a-100)},b.$on("$destroy",function(){c=null,f.removeBar(b)})},this.removeBar=function(a){this.bars.splice(this.bars.indexOf(a),1)},a.$watch("max",function(b){f.bars.forEach(function(b){b.max=a.max,b.recalculatePercentage()})})}]).directive("progress",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",require:"progress",scope:{max:"=?",title:"@?"},templateUrl:"template/progressbar/progress.html",link:function(){b||a.warn("progress is now deprecated. Use uib-progress instead.")}}}]).directive("bar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,require:"^progress",scope:{value:"=",type:"@"},templateUrl:"template/progressbar/bar.html",link:function(c,d,e,f){b||a.warn("bar is now deprecated. Use uib-bar instead."),f.addBar(c,d)}}}]).directive("progressbar",["$log","$progressSuppressWarning",function(a,b){return{replace:!0,transclude:!0,controller:"ProgressController",scope:{value:"=",max:"=?",type:"@"},templateUrl:"template/progressbar/progressbar.html",link:function(c,d,e,f){b||a.warn("progressbar is now deprecated. Use uib-progressbar instead."),f.addBar(c,angular.element(d.children()[0]),{title:e.title})}}}]),angular.module("ui.bootstrap.rating",[]).constant("uibRatingConfig",{max:5,stateOn:null,stateOff:null,titles:["one","two","three","four","five"]}).controller("UibRatingController",["$scope","$attrs","uibRatingConfig",function(a,b,c){var d={$setViewValue:angular.noop};this.init=function(e){d=e,d.$render=this.render,d.$formatters.push(function(a){return angular.isNumber(a)&&a<<0!==a&&(a=Math.round(a)),a}),this.stateOn=angular.isDefined(b.stateOn)?a.$parent.$eval(b.stateOn):c.stateOn,this.stateOff=angular.isDefined(b.stateOff)?a.$parent.$eval(b.stateOff):c.stateOff;var f=angular.isDefined(b.titles)?a.$parent.$eval(b.titles):c.titles;this.titles=angular.isArray(f)&&f.length>0?f:c.titles;var g=angular.isDefined(b.ratingStates)?a.$parent.$eval(b.ratingStates):new Array(angular.isDefined(b.max)?a.$parent.$eval(b.max):c.max);a.range=this.buildTemplateObjects(g)},this.buildTemplateObjects=function(a){for(var b=0,c=a.length;c>b;b++)a[b]=angular.extend({index:b},{stateOn:this.stateOn,stateOff:this.stateOff,title:this.getTitle(b)},a[b]);return a},this.getTitle=function(a){return a>=this.titles.length?a+1:this.titles[a]},a.rate=function(b){!a.readonly&&b>=0&&b<=a.range.length&&(d.$setViewValue(d.$viewValue===b?0:b),d.$render())},a.enter=function(b){a.readonly||(a.value=b),a.onHover({value:b})},a.reset=function(){a.value=d.$viewValue,a.onLeave()},a.onKeydown=function(b){/(37|38|39|40)/.test(b.which)&&(b.preventDefault(),b.stopPropagation(),a.rate(a.value+(38===b.which||39===b.which?1:-1)))},this.render=function(){a.value=d.$viewValue}}]).directive("uibRating",function(){return{require:["uibRating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"UibRatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(a,b,c,d){var e=d[0],f=d[1];e.init(f)}}}),angular.module("ui.bootstrap.rating").value("$ratingSuppressWarning",!1).controller("RatingController",["$scope","$attrs","$controller","$log","$ratingSuppressWarning",function(a,b,c,d,e){e||d.warn("RatingController is now deprecated. Use UibRatingController instead."),angular.extend(this,c("UibRatingController",{$scope:a,$attrs:b}))}]).directive("rating",["$log","$ratingSuppressWarning",function(a,b){return{require:["rating","ngModel"],scope:{readonly:"=?",onHover:"&",onLeave:"&"},controller:"RatingController",templateUrl:"template/rating/rating.html",replace:!0,link:function(c,d,e,f){b||a.warn("rating is now deprecated. Use uib-rating instead.");var g=f[0],h=f[1];g.init(h)}}}]),angular.module("ui.bootstrap.tabs",[]).controller("UibTabsetController",["$scope",function(a){var b=this,c=b.tabs=a.tabs=[];b.select=function(a){angular.forEach(c,function(b){b.active&&b!==a&&(b.active=!1,b.onDeselect(),a.selectCalled=!1)}),a.active=!0,a.selectCalled||(a.onSelect(),a.selectCalled=!0)},b.addTab=function(a){c.push(a),1===c.length&&a.active!==!1?a.active=!0:a.active?b.select(a):a.active=!1},b.removeTab=function(a){var e=c.indexOf(a);if(a.active&&c.length>1&&!d){var f=e==c.length-1?e-1:e+1;b.select(c[f])}c.splice(e,1)};var d;a.$on("$destroy",function(){d=!0})}]).directive("uibTabset",function(){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"UibTabsetController",templateUrl:"template/tabs/tabset.html",link:function(a,b,c){a.vertical=angular.isDefined(c.vertical)?a.$parent.$eval(c.vertical):!1,a.justified=angular.isDefined(c.justified)?a.$parent.$eval(c.justified):!1}}}).directive("uibTab",["$parse",function(a){return{require:"^uibTabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(b,c,d,e,f){b.$watch("active",function(a){a&&e.select(b)}),b.disabled=!1,d.disable&&b.$parent.$watch(a(d.disable),function(a){b.disabled=!!a}),b.select=function(){b.disabled||(b.active=!0)},e.addTab(b),b.$on("$destroy",function(){e.removeTab(b)}),b.$transcludeFn=f}}}]).directive("uibTabHeadingTransclude",function(){return{restrict:"A",require:["?^uibTab","?^tab"],link:function(a,b){a.$watch("headingElement",function(a){a&&(b.html(""),b.append(a))})}}}).directive("uibTabContentTransclude",function(){function a(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||a.hasAttribute("uib-tab-heading")||a.hasAttribute("data-uib-tab-heading")||a.hasAttribute("x-uib-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase()||"uib-tab-heading"===a.tagName.toLowerCase()||"data-uib-tab-heading"===a.tagName.toLowerCase()||"x-uib-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:["?^uibTabset","?^tabset"],link:function(b,c,d){var e=b.$eval(d.uibTabContentTransclude);e.$transcludeFn(e.$parent,function(b){angular.forEach(b,function(b){a(b)?e.headingElement=b:c.append(b)})})}}}),angular.module("ui.bootstrap.tabs").value("$tabsSuppressWarning",!1).controller("TabsetController",["$scope","$controller","$log","$tabsSuppressWarning",function(a,b,c,d){d||c.warn("TabsetController is now deprecated. Use UibTabsetController instead."),angular.extend(this,b("UibTabsetController",{$scope:a}))}]).directive("tabset",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"EA",transclude:!0,replace:!0,scope:{type:"@"},controller:"TabsetController",templateUrl:"template/tabs/tabset.html",link:function(c,d,e){b||a.warn("tabset is now deprecated. Use uib-tabset instead."),c.vertical=angular.isDefined(e.vertical)?c.$parent.$eval(e.vertical):!1,c.justified=angular.isDefined(e.justified)?c.$parent.$eval(e.justified):!1}}}]).directive("tab",["$parse","$log","$tabsSuppressWarning",function(a,b,c){return{require:"^tabset",restrict:"EA",replace:!0,templateUrl:"template/tabs/tab.html",transclude:!0,scope:{active:"=?",heading:"@",onSelect:"&select",onDeselect:"&deselect"},controller:function(){},link:function(d,e,f,g,h){c||b.warn("tab is now deprecated. Use uib-tab instead."),d.$watch("active",function(a){a&&g.select(d)}),d.disabled=!1,f.disable&&d.$parent.$watch(a(f.disable),function(a){d.disabled=!!a}),d.select=function(){d.disabled||(d.active=!0)},g.addTab(d),d.$on("$destroy",function(){g.removeTab(d)}),d.$transcludeFn=h}}}]).directive("tabHeadingTransclude",["$log","$tabsSuppressWarning",function(a,b){return{restrict:"A",require:"^tab",link:function(c,d){b||a.warn("tab-heading-transclude is now deprecated. Use uib-tab-heading-transclude instead."),c.$watch("headingElement",function(a){a&&(d.html(""),d.append(a))})}}}]).directive("tabContentTransclude",["$log","$tabsSuppressWarning",function(a,b){function c(a){return a.tagName&&(a.hasAttribute("tab-heading")||a.hasAttribute("data-tab-heading")||a.hasAttribute("x-tab-heading")||"tab-heading"===a.tagName.toLowerCase()||"data-tab-heading"===a.tagName.toLowerCase()||"x-tab-heading"===a.tagName.toLowerCase())}return{restrict:"A",require:"^tabset",link:function(d,e,f){b||a.warn("tab-content-transclude is now deprecated. Use uib-tab-content-transclude instead.");var g=d.$eval(f.tabContentTransclude);g.$transcludeFn(g.$parent,function(a){angular.forEach(a,function(a){c(a)?g.headingElement=a:e.append(a)})})}}}]),angular.module("ui.bootstrap.timepicker",[]).constant("uibTimepickerConfig",{hourStep:1,minuteStep:1,showMeridian:!0,meridians:null,readonlyInput:!1,mousewheel:!0,arrowkeys:!0,showSpinners:!0}).controller("UibTimepickerController",["$scope","$element","$attrs","$parse","$log","$locale","uibTimepickerConfig",function(a,b,c,d,e,f,g){function h(){var b=parseInt(a.hours,10),c=a.showMeridian?b>0&&13>b:b>=0&&24>b;return c?(a.showMeridian&&(12===b&&(b=0),a.meridian===r[1]&&(b+=12)),b):void 0}function i(){var b=parseInt(a.minutes,10);return b>=0&&60>b?b:void 0}function j(a){return angular.isDefined(a)&&a.toString().length<2?"0"+a:a.toString()}function k(a){l(),q.$setViewValue(new Date(p)),m(a)}function l(){q.$setValidity("time",!0),a.invalidHours=!1,a.invalidMinutes=!1}function m(b){var c=p.getHours(),d=p.getMinutes();a.showMeridian&&(c=0===c||12===c?12:c%12),a.hours="h"===b?c:j(c),"m"!==b&&(a.minutes=j(d)),a.meridian=p.getHours()<12?r[0]:r[1]}function n(a,b){var c=new Date(a.getTime()+6e4*b),d=new Date(a);return d.setHours(c.getHours(),c.getMinutes()),d}function o(a){p=n(p,a),k()}var p=new Date,q={$setViewValue:angular.noop},r=angular.isDefined(c.meridians)?a.$parent.$eval(c.meridians):g.meridians||f.DATETIME_FORMATS.AMPMS;a.tabindex=angular.isDefined(c.tabindex)?c.tabindex:0,b.removeAttr("tabindex"),this.init=function(b,d){q=b,q.$render=this.render,q.$formatters.unshift(function(a){return a?new Date(a):null});var e=d.eq(0),f=d.eq(1),h=angular.isDefined(c.mousewheel)?a.$parent.$eval(c.mousewheel):g.mousewheel;h&&this.setupMousewheelEvents(e,f);var i=angular.isDefined(c.arrowkeys)?a.$parent.$eval(c.arrowkeys):g.arrowkeys;i&&this.setupArrowkeyEvents(e,f),a.readonlyInput=angular.isDefined(c.readonlyInput)?a.$parent.$eval(c.readonlyInput):g.readonlyInput,this.setupInputEvents(e,f)};var s=g.hourStep;c.hourStep&&a.$parent.$watch(d(c.hourStep),function(a){s=parseInt(a,10)});var t=g.minuteStep;c.minuteStep&&a.$parent.$watch(d(c.minuteStep),function(a){t=parseInt(a,10)});var u;a.$parent.$watch(d(c.min),function(a){var b=new Date(a);u=isNaN(b)?void 0:b});var v;a.$parent.$watch(d(c.max),function(a){var b=new Date(a);v=isNaN(b)?void 0:b}),a.noIncrementHours=function(){var a=n(p,60*s);
return a>v||p>a&&u>a},a.noDecrementHours=function(){var a=n(p,60*-s);return u>a||a>p&&a>v},a.noIncrementMinutes=function(){var a=n(p,t);return a>v||p>a&&u>a},a.noDecrementMinutes=function(){var a=n(p,-t);return u>a||a>p&&a>v},a.noToggleMeridian=function(){return p.getHours()<13?n(p,720)>v:n(p,-720)<u},a.showMeridian=g.showMeridian,c.showMeridian&&a.$parent.$watch(d(c.showMeridian),function(b){if(a.showMeridian=!!b,q.$error.time){var c=h(),d=i();angular.isDefined(c)&&angular.isDefined(d)&&(p.setHours(c),k())}else m()}),this.setupMousewheelEvents=function(b,c){var d=function(a){a.originalEvent&&(a=a.originalEvent);var b=a.wheelDelta?a.wheelDelta:-a.deltaY;return a.detail||b>0};b.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementHours():a.decrementHours()),b.preventDefault()}),c.bind("mousewheel wheel",function(b){a.$apply(d(b)?a.incrementMinutes():a.decrementMinutes()),b.preventDefault()})},this.setupArrowkeyEvents=function(b,c){b.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementHours(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementHours(),a.$apply())}),c.bind("keydown",function(b){38===b.which?(b.preventDefault(),a.incrementMinutes(),a.$apply()):40===b.which&&(b.preventDefault(),a.decrementMinutes(),a.$apply())})},this.setupInputEvents=function(b,c){if(a.readonlyInput)return a.updateHours=angular.noop,void(a.updateMinutes=angular.noop);var d=function(b,c){q.$setViewValue(null),q.$setValidity("time",!1),angular.isDefined(b)&&(a.invalidHours=b),angular.isDefined(c)&&(a.invalidMinutes=c)};a.updateHours=function(){var a=h(),b=i();angular.isDefined(a)&&angular.isDefined(b)?(p.setHours(a),u>p||p>v?d(!0):k("h")):d(!0)},b.bind("blur",function(b){!a.invalidHours&&a.hours<10&&a.$apply(function(){a.hours=j(a.hours)})}),a.updateMinutes=function(){var a=i(),b=h();angular.isDefined(a)&&angular.isDefined(b)?(p.setMinutes(a),u>p||p>v?d(void 0,!0):k("m")):d(void 0,!0)},c.bind("blur",function(b){!a.invalidMinutes&&a.minutes<10&&a.$apply(function(){a.minutes=j(a.minutes)})})},this.render=function(){var b=q.$viewValue;isNaN(b)?(q.$setValidity("time",!1),e.error('Timepicker directive: "ng-model" value must be a Date object, a number of milliseconds since 01.01.1970 or a string representing an RFC2822 or ISO 8601 date.')):(b&&(p=b),u>p||p>v?(q.$setValidity("time",!1),a.invalidHours=!0,a.invalidMinutes=!0):l(),m())},a.showSpinners=angular.isDefined(c.showSpinners)?a.$parent.$eval(c.showSpinners):g.showSpinners,a.incrementHours=function(){a.noIncrementHours()||o(60*s)},a.decrementHours=function(){a.noDecrementHours()||o(60*-s)},a.incrementMinutes=function(){a.noIncrementMinutes()||o(t)},a.decrementMinutes=function(){a.noDecrementMinutes()||o(-t)},a.toggleMeridian=function(){a.noToggleMeridian()||o(720*(p.getHours()<12?1:-1))}}]).directive("uibTimepicker",function(){return{restrict:"EA",require:["uibTimepicker","?^ngModel"],controller:"UibTimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(a,b,c,d){var e=d[0],f=d[1];f&&e.init(f,b.find("input"))}}}),angular.module("ui.bootstrap.timepicker").value("$timepickerSuppressWarning",!1).controller("TimepickerController",["$scope","$element","$attrs","$controller","$log","$timepickerSuppressWarning",function(a,b,c,d,e,f){f||e.warn("TimepickerController is now deprecated. Use UibTimepickerController instead."),angular.extend(this,d("UibTimepickerController",{$scope:a,$element:b,$attrs:c}))}]).directive("timepicker",["$log","$timepickerSuppressWarning",function(a,b){return{restrict:"EA",require:["timepicker","?^ngModel"],controller:"TimepickerController",controllerAs:"timepicker",replace:!0,scope:{},templateUrl:function(a,b){return b.templateUrl||"template/timepicker/timepicker.html"},link:function(c,d,e,f){b||a.warn("timepicker is now deprecated. Use uib-timepicker instead.");var g=f[0],h=f[1];h&&g.init(h,d.find("input"))}}}]),angular.module("ui.bootstrap.typeahead",["ui.bootstrap.position"]).factory("uibTypeaheadParser",["$parse",function(a){var b=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w\d]*))\s+in\s+([\s\S]+?)$/;return{parse:function(c){var d=c.match(b);if(!d)throw new Error('Expected typeahead specification in form of "_modelValue_ (as _label_)? for _item_ in _collection_" but got "'+c+'".');return{itemName:d[3],source:a(d[4]),viewMapper:a(d[2]||d[1]),modelMapper:a(d[1])}}}}]).controller("UibTypeaheadController",["$scope","$element","$attrs","$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","uibTypeaheadParser",function(a,b,c,d,e,f,g,h,i,j,k,l){function m(){K.moveInProgress||(K.moveInProgress=!0,K.$digest()),S&&g.cancel(S),S=g(function(){K.matches.length&&n(),K.moveInProgress=!1},r)}function n(){K.position=C?k.offset(b):k.position(b),K.position.top+=b.prop("offsetHeight")}var o,p,q=[9,13,27,38,40],r=200,s=a.$eval(c.typeaheadMinLength);s||0===s||(s=1);var t,u,v=a.$eval(c.typeaheadWaitMs)||0,w=a.$eval(c.typeaheadEditable)!==!1,x=e(c.typeaheadLoading).assign||angular.noop,y=e(c.typeaheadOnSelect),z=angular.isDefined(c.typeaheadSelectOnBlur)?a.$eval(c.typeaheadSelectOnBlur):!1,A=e(c.typeaheadNoResults).assign||angular.noop,B=c.typeaheadInputFormatter?e(c.typeaheadInputFormatter):void 0,C=c.typeaheadAppendToBody?a.$eval(c.typeaheadAppendToBody):!1,D=c.typeaheadAppendToElementId||!1,E=a.$eval(c.typeaheadFocusFirst)!==!1,F=c.typeaheadSelectOnExact?a.$eval(c.typeaheadSelectOnExact):!1,G=e(c.ngModel),H=e(c.ngModel+"($$$p)"),I=function(b,c){return angular.isFunction(G(a))&&p&&p.$options&&p.$options.getterSetter?H(b,{$$$p:c}):G.assign(b,c)},J=l.parse(c.uibTypeahead),K=a.$new(),L=a.$on("$destroy",function(){K.$destroy()});K.$on("$destroy",L);var M="typeahead-"+K.$id+"-"+Math.floor(1e4*Math.random());b.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":M});var N=angular.element("<div uib-typeahead-popup></div>");N.attr({id:M,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(c.typeaheadTemplateUrl)&&N.attr("template-url",c.typeaheadTemplateUrl),angular.isDefined(c.typeaheadPopupTemplateUrl)&&N.attr("popup-template-url",c.typeaheadPopupTemplateUrl);var O=function(){K.matches=[],K.activeIdx=-1,b.attr("aria-expanded",!1)},P=function(a){return M+"-option-"+a};K.$watch("activeIdx",function(a){0>a?b.removeAttr("aria-activedescendant"):b.attr("aria-activedescendant",P(a))});var Q=function(a,b){return K.matches.length>b&&a?a.toUpperCase()===K.matches[b].label.toUpperCase():!1},R=function(c){var d={$viewValue:c};x(a,!0),A(a,!1),f.when(J.source(a,d)).then(function(e){var f=c===o.$viewValue;if(f&&t)if(e&&e.length>0){K.activeIdx=E?0:-1,A(a,!1),K.matches.length=0;for(var g=0;g<e.length;g++)d[J.itemName]=e[g],K.matches.push({id:P(g),label:J.viewMapper(K,d),model:e[g]});K.query=c,n(),b.attr("aria-expanded",!0),F&&1===K.matches.length&&Q(c,0)&&K.select(0)}else O(),A(a,!0);f&&x(a,!1)},function(){O(),x(a,!1),A(a,!0)})};C&&(angular.element(i).bind("resize",m),h.find("body").bind("scroll",m));var S;K.moveInProgress=!1,K.query=void 0;var T,U=function(a){T=g(function(){R(a)},v)},V=function(){T&&g.cancel(T)};O(),K.select=function(d){var e,f,h={};u=!0,h[J.itemName]=f=K.matches[d].model,e=J.modelMapper(a,h),I(a,e),o.$setValidity("editable",!0),o.$setValidity("parse",!0),y(a,{$item:f,$model:e,$label:J.viewMapper(a,h)}),O(),K.$eval(c.typeaheadFocusOnSelect)!==!1&&g(function(){b[0].focus()},0,!1)},b.bind("keydown",function(a){if(0!==K.matches.length&&-1!==q.indexOf(a.which)){if(-1===K.activeIdx&&(9===a.which||13===a.which))return O(),void K.$digest();a.preventDefault(),40===a.which?(K.activeIdx=(K.activeIdx+1)%K.matches.length,K.$digest()):38===a.which?(K.activeIdx=(K.activeIdx>0?K.activeIdx:K.matches.length)-1,K.$digest()):13===a.which||9===a.which?K.$apply(function(){K.select(K.activeIdx)}):27===a.which&&(a.stopPropagation(),O(),K.$digest())}}),b.bind("blur",function(){z&&K.matches.length&&-1!==K.activeIdx&&!u&&(u=!0,K.$apply(function(){K.select(K.activeIdx)})),t=!1,u=!1});var W=function(a){b[0]!==a.target&&3!==a.which&&0!==K.matches.length&&(O(),j.$$phase||K.$digest())};h.bind("click",W),a.$on("$destroy",function(){h.unbind("click",W),(C||D)&&X.remove(),C&&(angular.element(i).unbind("resize",m),h.find("body").unbind("scroll",m)),N.remove()});var X=d(N)(K);C?h.find("body").append(X):D!==!1?angular.element(h[0].getElementById(D)).append(X):b.after(X),this.init=function(b,c){o=b,p=c,o.$parsers.unshift(function(b){return t=!0,0===s||b&&b.length>=s?v>0?(V(),U(b)):R(b):(x(a,!1),V(),O()),w?b:b?void o.$setValidity("editable",!1):(o.$setValidity("editable",!0),null)}),o.$formatters.push(function(b){var c,d,e={};return w||o.$setValidity("editable",!0),B?(e.$model=b,B(a,e)):(e[J.itemName]=b,c=J.viewMapper(a,e),e[J.itemName]=void 0,d=J.viewMapper(a,e),c!==d?c:b)})}}]).directive("uibTypeahead",function(){return{controller:"UibTypeaheadController",require:["ngModel","^?ngModelOptions","uibTypeahead"],link:function(a,b,c,d){d[2].init(d[0],d[1])}}}).directive("uibTypeaheadPopup",function(){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(a,b,c){a.templateUrl=c.templateUrl,a.isOpen=function(){return a.matches.length>0},a.isActive=function(b){return a.active==b},a.selectActive=function(b){a.active=b},a.selectMatch=function(b){a.select({activeIdx:b})}}}}).directive("uibTypeaheadMatch",["$templateRequest","$compile","$parse",function(a,b,c){return{scope:{index:"=",match:"=",query:"="},link:function(d,e,f){var g=c(f.templateUrl)(d.$parent)||"template/typeahead/typeahead-match.html";a(g).then(function(a){b(a.trim())(d,function(a){e.replaceWith(a)})})}}}]).filter("uibTypeaheadHighlight",["$sce","$injector","$log",function(a,b,c){function d(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function e(a){return/<.*>/g.test(a)}var f;return f=b.has("$sanitize"),function(b,g){return!f&&e(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=g?(""+b).replace(new RegExp(d(g),"gi"),"<strong>$&</strong>"):b,f||(b=a.trustAsHtml(b)),b}}]),angular.module("ui.bootstrap.typeahead").value("$typeaheadSuppressWarning",!1).service("typeaheadParser",["$parse","uibTypeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d){return d||c.warn("typeaheadParser is now deprecated. Use uibTypeaheadParser instead."),b}]).directive("typeahead",["$compile","$parse","$q","$timeout","$document","$window","$rootScope","$uibPosition","typeaheadParser","$log","$typeaheadSuppressWarning",function(a,b,c,d,e,f,g,h,i,j,k){var l=[9,13,27,38,40],m=200;return{require:["ngModel","^?ngModelOptions"],link:function(n,o,p,q){function r(){N.moveInProgress||(N.moveInProgress=!0,N.$digest()),V&&d.cancel(V),V=d(function(){N.matches.length&&s(),N.moveInProgress=!1},m)}function s(){N.position=F?h.offset(o):h.position(o),N.position.top+=o.prop("offsetHeight")}k||j.warn("typeahead is now deprecated. Use uib-typeahead instead.");var t=q[0],u=q[1],v=n.$eval(p.typeaheadMinLength);v||0===v||(v=1);var w,x,y=n.$eval(p.typeaheadWaitMs)||0,z=n.$eval(p.typeaheadEditable)!==!1,A=b(p.typeaheadLoading).assign||angular.noop,B=b(p.typeaheadOnSelect),C=angular.isDefined(p.typeaheadSelectOnBlur)?n.$eval(p.typeaheadSelectOnBlur):!1,D=b(p.typeaheadNoResults).assign||angular.noop,E=p.typeaheadInputFormatter?b(p.typeaheadInputFormatter):void 0,F=p.typeaheadAppendToBody?n.$eval(p.typeaheadAppendToBody):!1,G=p.typeaheadAppendToElementId||!1,H=n.$eval(p.typeaheadFocusFirst)!==!1,I=p.typeaheadSelectOnExact?n.$eval(p.typeaheadSelectOnExact):!1,J=b(p.ngModel),K=b(p.ngModel+"($$$p)"),L=function(a,b){return angular.isFunction(J(n))&&u&&u.$options&&u.$options.getterSetter?K(a,{$$$p:b}):J.assign(a,b)},M=i.parse(p.typeahead),N=n.$new(),O=n.$on("$destroy",function(){N.$destroy()});N.$on("$destroy",O);var P="typeahead-"+N.$id+"-"+Math.floor(1e4*Math.random());o.attr({"aria-autocomplete":"list","aria-expanded":!1,"aria-owns":P});var Q=angular.element("<div typeahead-popup></div>");Q.attr({id:P,matches:"matches",active:"activeIdx",select:"select(activeIdx)","move-in-progress":"moveInProgress",query:"query",position:"position"}),angular.isDefined(p.typeaheadTemplateUrl)&&Q.attr("template-url",p.typeaheadTemplateUrl),angular.isDefined(p.typeaheadPopupTemplateUrl)&&Q.attr("popup-template-url",p.typeaheadPopupTemplateUrl);var R=function(){N.matches=[],N.activeIdx=-1,o.attr("aria-expanded",!1)},S=function(a){return P+"-option-"+a};N.$watch("activeIdx",function(a){0>a?o.removeAttr("aria-activedescendant"):o.attr("aria-activedescendant",S(a))});var T=function(a,b){return N.matches.length>b&&a?a.toUpperCase()===N.matches[b].label.toUpperCase():!1},U=function(a){var b={$viewValue:a};A(n,!0),D(n,!1),c.when(M.source(n,b)).then(function(c){var d=a===t.$viewValue;if(d&&w)if(c&&c.length>0){N.activeIdx=H?0:-1,D(n,!1),N.matches.length=0;for(var e=0;e<c.length;e++)b[M.itemName]=c[e],N.matches.push({id:S(e),label:M.viewMapper(N,b),model:c[e]});N.query=a,s(),o.attr("aria-expanded",!0),I&&1===N.matches.length&&T(a,0)&&N.select(0)}else R(),D(n,!0);d&&A(n,!1)},function(){R(),A(n,!1),D(n,!0)})};F&&(angular.element(f).bind("resize",r),e.find("body").bind("scroll",r));var V;N.moveInProgress=!1,R(),N.query=void 0;var W,X=function(a){W=d(function(){U(a)},y)},Y=function(){W&&d.cancel(W)};t.$parsers.unshift(function(a){return w=!0,0===v||a&&a.length>=v?y>0?(Y(),X(a)):U(a):(A(n,!1),Y(),R()),z?a:a?void t.$setValidity("editable",!1):(t.$setValidity("editable",!0),null)}),t.$formatters.push(function(a){var b,c,d={};return z||t.$setValidity("editable",!0),E?(d.$model=a,E(n,d)):(d[M.itemName]=a,b=M.viewMapper(n,d),d[M.itemName]=void 0,c=M.viewMapper(n,d),b!==c?b:a)}),N.select=function(a){var b,c,e={};x=!0,e[M.itemName]=c=N.matches[a].model,b=M.modelMapper(n,e),L(n,b),t.$setValidity("editable",!0),t.$setValidity("parse",!0),B(n,{$item:c,$model:b,$label:M.viewMapper(n,e)}),R(),N.$eval(p.typeaheadFocusOnSelect)!==!1&&d(function(){o[0].focus()},0,!1)},o.bind("keydown",function(a){if(0!==N.matches.length&&-1!==l.indexOf(a.which)){if(-1===N.activeIdx&&(9===a.which||13===a.which))return R(),void N.$digest();a.preventDefault(),40===a.which?(N.activeIdx=(N.activeIdx+1)%N.matches.length,N.$digest()):38===a.which?(N.activeIdx=(N.activeIdx>0?N.activeIdx:N.matches.length)-1,N.$digest()):13===a.which||9===a.which?N.$apply(function(){N.select(N.activeIdx)}):27===a.which&&(a.stopPropagation(),R(),N.$digest())}}),o.bind("blur",function(){C&&N.matches.length&&-1!==N.activeIdx&&!x&&(x=!0,N.$apply(function(){N.select(N.activeIdx)})),w=!1,x=!1});var Z=function(a){o[0]!==a.target&&3!==a.which&&0!==N.matches.length&&(R(),g.$$phase||N.$digest())};e.bind("click",Z),n.$on("$destroy",function(){e.unbind("click",Z),(F||G)&&$.remove(),F&&(angular.element(f).unbind("resize",r),e.find("body").unbind("scroll",r)),Q.remove()});var $=a(Q)(N);F?e.find("body").append($):G!==!1?angular.element(e[0].getElementById(G)).append($):o.after($)}}}]).directive("typeaheadPopup",["$typeaheadSuppressWarning","$log",function(a,b){return{scope:{matches:"=",query:"=",active:"=",position:"&",moveInProgress:"=",select:"&"},replace:!0,templateUrl:function(a,b){return b.popupTemplateUrl||"template/typeahead/typeahead-popup.html"},link:function(c,d,e){a||b.warn("typeahead-popup is now deprecated. Use uib-typeahead-popup instead."),c.templateUrl=e.templateUrl,c.isOpen=function(){return c.matches.length>0},c.isActive=function(a){return c.active==a},c.selectActive=function(a){c.active=a},c.selectMatch=function(a){c.select({activeIdx:a})}}}}]).directive("typeaheadMatch",["$templateRequest","$compile","$parse","$typeaheadSuppressWarning","$log",function(a,b,c,d,e){return{restrict:"EA",scope:{index:"=",match:"=",query:"="},link:function(f,g,h){d||e.warn("typeahead-match is now deprecated. Use uib-typeahead-match instead.");var i=c(h.templateUrl)(f.$parent)||"template/typeahead/typeahead-match.html";a(i).then(function(a){b(a.trim())(f,function(a){g.replaceWith(a)})})}}}]).filter("typeaheadHighlight",["$sce","$injector","$log","$typeaheadSuppressWarning",function(a,b,c,d){function e(a){return a.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}function f(a){return/<.*>/g.test(a)}var g;return g=b.has("$sanitize"),function(b,h){return d||c.warn("typeaheadHighlight is now deprecated. Use uibTypeaheadHighlight instead."),!g&&f(b)&&c.warn("Unsafe use of typeahead please use ngSanitize"),b=h?(""+b).replace(new RegExp(e(h),"gi"),"<strong>$&</strong>"):b,g||(b=a.trustAsHtml(b)),b}}]),angular.module("template/accordion/accordion-group.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion-group.html",'<div class="panel {{panelClass || \'panel-default\'}}">\n  <div class="panel-heading" ng-keypress="toggleOpen($event)">\n    <h4 class="panel-title">\n      <a href tabindex="0" class="accordion-toggle" ng-click="toggleOpen()" uib-accordion-transclude="heading"><span ng-class="{\'text-muted\': isDisabled}">{{heading}}</span></a>\n    </h4>\n  </div>\n  <div class="panel-collapse collapse" uib-collapse="!isOpen">\n	  <div class="panel-body" ng-transclude></div>\n  </div>\n</div>\n')}]),angular.module("template/accordion/accordion.html",[]).run(["$templateCache",function(a){a.put("template/accordion/accordion.html",'<div class="panel-group" ng-transclude></div>')}]),angular.module("template/alert/alert.html",[]).run(["$templateCache",function(a){a.put("template/alert/alert.html",'<div class="alert" ng-class="[\'alert-\' + (type || \'warning\'), closeable ? \'alert-dismissible\' : null]" role="alert">\n    <button ng-show="closeable" type="button" class="close" ng-click="close({$event: $event})">\n        <span aria-hidden="true">&times;</span>\n        <span class="sr-only">Close</span>\n    </button>\n    <div ng-transclude></div>\n</div>\n')}]),angular.module("template/carousel/carousel.html",[]).run(["$templateCache",function(a){a.put("template/carousel/carousel.html",'<div ng-mouseenter="pause()" ng-mouseleave="play()" class="carousel" ng-swipe-right="prev()" ng-swipe-left="next()">\n  <div class="carousel-inner" ng-transclude></div>\n  <a role="button" href class="left carousel-control" ng-click="prev()" ng-show="slides.length > 1">\n    <span aria-hidden="true" class="glyphicon glyphicon-chevron-left"></span>\n    <span class="sr-only">previous</span>\n  </a>\n  <a role="button" href class="right carousel-control" ng-click="next()" ng-show="slides.length > 1">\n    <span aria-hidden="true" class="glyphicon glyphicon-chevron-right"></span>\n    <span class="sr-only">next</span>\n  </a>\n  <ol class="carousel-indicators" ng-show="slides.length > 1">\n    <li ng-repeat="slide in slides | orderBy:indexOfSlide track by $index" ng-class="{ active: isActive(slide) }" ng-click="select(slide)">\n      <span class="sr-only">slide {{ $index + 1 }} of {{ slides.length }}<span ng-if="isActive(slide)">, currently active</span></span>\n    </li>\n  </ol>\n</div>')}]),angular.module("template/carousel/slide.html",[]).run(["$templateCache",function(a){a.put("template/carousel/slide.html",'<div ng-class="{\n    \'active\': active\n  }" class="item text-center" ng-transclude></div>\n')}]),angular.module("template/datepicker/datepicker.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/datepicker.html",'<div ng-switch="datepickerMode" role="application" ng-keydown="keydown($event)">\n  <uib-daypicker ng-switch-when="day" tabindex="0"></uib-daypicker>\n  <uib-monthpicker ng-switch-when="month" tabindex="0"></uib-monthpicker>\n  <uib-yearpicker ng-switch-when="year" tabindex="0"></uib-yearpicker>\n</div>')}]),angular.module("template/datepicker/day.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/day.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="{{::5 + showWeeks}}"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n    <tr>\n      <th ng-if="showWeeks" class="text-center"></th>\n      <th ng-repeat="label in ::labels track by $index" class="text-center"><small aria-label="{{::label.full}}">{{::label.abbr}}</small></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td>\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n        <button type="button" style="min-width:100%;" class="btn btn-default btn-sm" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-muted\': dt.secondary, \'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/month.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/month.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n        <button type="button" style="min-width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/datepicker/popup.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/popup.html",'<ul class="dropdown-menu" dropdown-nested ng-if="isOpen" style="display: block" ng-style="{top: position.top+\'px\', left: position.left+\'px\'}" ng-keydown="keydown($event)" ng-click="$event.stopPropagation()">\n	<li ng-transclude></li>\n	<li ng-if="showButtonBar" style="padding:10px 9px 2px">\n		<span class="btn-group pull-left">\n			<button type="button" class="btn btn-sm btn-info" ng-click="select(\'today\')" ng-disabled="isDisabled(\'today\')">{{ getText(\'current\') }}</button>\n			<button type="button" class="btn btn-sm btn-danger" ng-click="select(null)">{{ getText(\'clear\') }}</button>\n		</span>\n		<button type="button" class="btn btn-sm btn-success pull-right" ng-click="close()">{{ getText(\'close\') }}</button>\n	</li>\n</ul>\n')}]),angular.module("template/datepicker/year.html",[]).run(["$templateCache",function(a){a.put("template/datepicker/year.html",'<table role="grid" aria-labelledby="{{::uniqueId}}-title" aria-activedescendant="{{activeDateId}}">\n  <thead>\n    <tr>\n      <th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i></button></th>\n      <th colspan="3"><button id="{{::uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></button></th>\n      <th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i></button></th>\n    </tr>\n  </thead>\n  <tbody>\n    <tr ng-repeat="row in rows track by $index">\n      <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{::dt.uid}}" ng-class="::dt.customClass">\n        <button type="button" style="min-width:100%;" class="btn btn-default" ng-class="{\'btn-info\': dt.selected, active: isActive(dt)}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="::{\'text-info\': dt.current}">{{::dt.label}}</span></button>\n      </td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/modal/backdrop.html",[]).run(["$templateCache",function(a){a.put("template/modal/backdrop.html",'<div uib-modal-animation-class="fade"\n     modal-in-class="in"\n     ng-style="{\'z-index\': 1040 + (index && 1 || 0) + index*10}"\n></div>\n')}]),angular.module("template/modal/window.html",[]).run(["$templateCache",function(a){a.put("template/modal/window.html",'<div modal-render="{{$isRendered}}" tabindex="-1" role="dialog" class="modal"\n    uib-modal-animation-class="fade"\n    modal-in-class="in"\n    ng-style="{\'z-index\': 1050 + index*10, display: \'block\'}">\n    <div class="modal-dialog" ng-class="size ? \'modal-\' + size : \'\'"><div class="modal-content" uib-modal-transclude></div></div>\n</div>\n')}]),angular.module("template/pagination/pager.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pager.html",'<ul class="pager">\n  <li ng-class="{disabled: noPrevious()||ngDisabled, previous: align}"><a href ng-click="selectPage(page - 1, $event)">{{::getText(\'previous\')}}</a></li>\n  <li ng-class="{disabled: noNext()||ngDisabled, next: align}"><a href ng-click="selectPage(page + 1, $event)">{{::getText(\'next\')}}</a></li>\n</ul>\n')}]),angular.module("template/pagination/pagination.html",[]).run(["$templateCache",function(a){a.put("template/pagination/pagination.html",'<ul class="pagination">\n  <li ng-if="::boundaryLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-first"><a href ng-click="selectPage(1, $event)">{{::getText(\'first\')}}</a></li>\n  <li ng-if="::directionLinks" ng-class="{disabled: noPrevious()||ngDisabled}" class="pagination-prev"><a href ng-click="selectPage(page - 1, $event)">{{::getText(\'previous\')}}</a></li>\n  <li ng-repeat="page in pages track by $index" ng-class="{active: page.active,disabled: ngDisabled&&!page.active}" class="pagination-page"><a href ng-click="selectPage(page.number, $event)">{{page.text}}</a></li>\n  <li ng-if="::directionLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-next"><a href ng-click="selectPage(page + 1, $event)">{{::getText(\'next\')}}</a></li>\n  <li ng-if="::boundaryLinks" ng-class="{disabled: noNext()||ngDisabled}" class="pagination-last"><a href ng-click="selectPage(totalPages, $event)">{{::getText(\'last\')}}</a></li>\n</ul>\n')}]),angular.module("template/tooltip/tooltip-html-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-html-popup.html",'<div\n  tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" ng-bind-html="contentExp()"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-popup.html",'<div\n  tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner" ng-bind="content"></div>\n</div>\n')}]),angular.module("template/tooltip/tooltip-template-popup.html",[]).run(["$templateCache",function(a){a.put("template/tooltip/tooltip-template-popup.html",'<div\n  tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="tooltip-arrow"></div>\n  <div class="tooltip-inner"\n    uib-tooltip-template-transclude="contentExp()"\n    tooltip-template-transclude-scope="originScope()"></div>\n</div>\n')}]),angular.module("template/popover/popover-html.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-html.html",'<div tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="arrow"></div>\n\n  <div class="popover-inner">\n      <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n      <div class="popover-content" ng-bind-html="contentExp()"></div>\n  </div>\n</div>\n')}]),angular.module("template/popover/popover-template.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover-template.html",'<div tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="arrow"></div>\n\n  <div class="popover-inner">\n      <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n      <div class="popover-content"\n        uib-tooltip-template-transclude="contentExp()"\n        tooltip-template-transclude-scope="originScope()"></div>\n  </div>\n</div>\n')}]),angular.module("template/popover/popover.html",[]).run(["$templateCache",function(a){a.put("template/popover/popover.html",'<div tooltip-animation-class="fade"\n  uib-tooltip-classes\n  ng-class="{ in: isOpen() }">\n  <div class="arrow"></div>\n\n  <div class="popover-inner">\n      <h3 class="popover-title" ng-bind="title" ng-if="title"></h3>\n      <div class="popover-content" ng-bind="content"></div>\n  </div>\n</div>\n')}]),angular.module("template/progressbar/bar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/bar.html",'<div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>\n')}]),angular.module("template/progressbar/progress.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progress.html",'<div class="progress" ng-transclude aria-labelledby="{{::title}}"></div>')}]),angular.module("template/progressbar/progressbar.html",[]).run(["$templateCache",function(a){a.put("template/progressbar/progressbar.html",'<div class="progress">\n  <div class="progress-bar" ng-class="type && \'progress-bar-\' + type" role="progressbar" aria-valuenow="{{value}}" aria-valuemin="0" aria-valuemax="{{max}}" ng-style="{width: (percent < 100 ? percent : 100) + \'%\'}" aria-valuetext="{{percent | number:0}}%" aria-labelledby="{{::title}}" style="min-width: 0;" ng-transclude></div>\n</div>\n')}]),angular.module("template/rating/rating.html",[]).run(["$templateCache",function(a){a.put("template/rating/rating.html",'<span ng-mouseleave="reset()" ng-keydown="onKeydown($event)" tabindex="0" role="slider" aria-valuemin="0" aria-valuemax="{{range.length}}" aria-valuenow="{{value}}">\n    <span ng-repeat-start="r in range track by $index" class="sr-only">({{ $index < value ? \'*\' : \' \' }})</span>\n    <i ng-repeat-end ng-mouseenter="enter($index + 1)" ng-click="rate($index + 1)" class="glyphicon" ng-class="$index < value && (r.stateOn || \'glyphicon-star\') || (r.stateOff || \'glyphicon-star-empty\')" ng-attr-title="{{r.title}}" aria-valuetext="{{r.title}}"></i>\n</span>\n');
}]),angular.module("template/tabs/tab.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tab.html",'<li ng-class="{active: active, disabled: disabled}">\n  <a href ng-click="select()" uib-tab-heading-transclude>{{heading}}</a>\n</li>\n')}]),angular.module("template/tabs/tabset.html",[]).run(["$templateCache",function(a){a.put("template/tabs/tabset.html",'<div>\n  <ul class="nav nav-{{type || \'tabs\'}}" ng-class="{\'nav-stacked\': vertical, \'nav-justified\': justified}" ng-transclude></ul>\n  <div class="tab-content">\n    <div class="tab-pane" \n         ng-repeat="tab in tabs" \n         ng-class="{active: tab.active}"\n         uib-tab-content-transclude="tab">\n    </div>\n  </div>\n</div>\n')}]),angular.module("template/timepicker/timepicker.html",[]).run(["$templateCache",function(a){a.put("template/timepicker/timepicker.html",'<table>\n  <tbody>\n    <tr class="text-center" ng-show="::showSpinners">\n      <td><a ng-click="incrementHours()" ng-class="{disabled: noIncrementHours()}" class="btn btn-link" ng-disabled="noIncrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n      <td>&nbsp;</td>\n      <td><a ng-click="incrementMinutes()" ng-class="{disabled: noIncrementMinutes()}" class="btn btn-link" ng-disabled="noIncrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-up"></span></a></td>\n      <td ng-show="showMeridian"></td>\n    </tr>\n    <tr>\n      <td class="form-group" ng-class="{\'has-error\': invalidHours}">\n        <input style="width:50px;" type="text" ng-model="hours" ng-change="updateHours()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">\n      </td>\n      <td>:</td>\n      <td class="form-group" ng-class="{\'has-error\': invalidMinutes}">\n        <input style="width:50px;" type="text" ng-model="minutes" ng-change="updateMinutes()" class="form-control text-center" ng-readonly="::readonlyInput" maxlength="2" tabindex="{{::tabindex}}">\n      </td>\n      <td ng-show="showMeridian"><button type="button" ng-class="{disabled: noToggleMeridian()}" class="btn btn-default text-center" ng-click="toggleMeridian()" ng-disabled="noToggleMeridian()" tabindex="{{::tabindex}}">{{meridian}}</button></td>\n    </tr>\n    <tr class="text-center" ng-show="::showSpinners">\n      <td><a ng-click="decrementHours()" ng-class="{disabled: noDecrementHours()}" class="btn btn-link" ng-disabled="noDecrementHours()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n      <td>&nbsp;</td>\n      <td><a ng-click="decrementMinutes()" ng-class="{disabled: noDecrementMinutes()}" class="btn btn-link" ng-disabled="noDecrementMinutes()" tabindex="{{::tabindex}}"><span class="glyphicon glyphicon-chevron-down"></span></a></td>\n      <td ng-show="showMeridian"></td>\n    </tr>\n  </tbody>\n</table>\n')}]),angular.module("template/typeahead/typeahead-match.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-match.html",'<a href tabindex="-1" ng-bind-html="match.label | uibTypeaheadHighlight:query"></a>\n')}]),angular.module("template/typeahead/typeahead-popup.html",[]).run(["$templateCache",function(a){a.put("template/typeahead/typeahead-popup.html",'<ul class="dropdown-menu" ng-show="isOpen() && !moveInProgress" ng-style="{top: position().top+\'px\', left: position().left+\'px\'}" style="display: block;" role="listbox" aria-hidden="{{!isOpen()}}">\n    <li ng-repeat="match in matches track by $index" ng-class="{active: isActive($index) }" ng-mouseenter="selectActive($index)" ng-click="selectMatch($index)" role="option" id="{{::match.id}}">\n        <div uib-typeahead-match index="$index" match="match" query="query" template-url="templateUrl"></div>\n    </li>\n</ul>\n')}]),!angular.$$csp()&&angular.element(document).find("head").prepend('<style type="text/css">.ng-animate.item:not(.left):not(.right){-webkit-transition:0s ease-in-out left;transition:0s ease-in-out left}</style>');;(function ()
{
    'use strict';

    imageOnLoadDirective.$inject = ["$log"];
    wipImageZoomDirective.$inject = ["$timeout"];
    angular
        .module('wipImageZoom', ['ngSanitize', 'ngTouch'])
        .provider('wipImageZoomConfig', wipImageZoomConfig)
        .directive('imageOnLoad', imageOnLoadDirective)
        .directive('wipImageZoom', wipImageZoomDirective)
        .directive('wipImageZoomTracker', wipImageZoomTrackerDirective)
        .directive('wipImageZoomLens', wipImageZoomLensDirective)
        .directive('wipImageZoomMask', wipImageZoomMaskDirective)
        .directive('wipImageZoomImage', wipImageZoomImageDirective)
        .directive('wipImageZoomThumbs', wipImageZoomThumbsDirective);


    function wipImageZoomConfig()
    {
        this.defaults = {
            zoomEnable          : true,
            defaultIndex        : 0, // Order of the default selected Image
            /* You should give images in array with object properties
             [{
             thumb : 'assets/images/1-thumb.jpg',
             medium: 'assets/images/1-medium.jpg',
             large : 'assets/images/1-large.jpg'
             }] */
            images              : [],
            style               : 'inner', // inner or box
            boxPos              : 'right-top', // e.g., right-top, right-middle, right-bottom, top-center, top-left, top-right ...
            boxW                : 400, // Box width
            boxH                : 400, // Box height
            method              : 'lens', // fallow 'lens' or 'pointer'
            cursor              : 'crosshair', // 'none', 'default', 'crosshair', 'pointer', 'move'
            lens                : true, // Lens toggle
            zoomLevel           : 3, // 0: not scales, uses the original large image size, use 1 and above to adjust.
            immersiveMode       : '769', // false or 0 for disable, always, max width(px) for trigger
            immersiveModeOptions: {}, // can extend immersed mode options
            immersiveModeMessage: 'Click to Zoom', // Immersive mode message
            prevThumbButton     : '&#9665;', // Prev thumb button (html)
            nextThumbButton     : '&#9655;', // Next thumb button (html)
            thumbsPos           : 'bottom', // Thumbs position: 'top', 'bottom'
            thumbCol            : 3, // Thumb column count
            thumbColPadding     : 4 // Padding between thumbs
        };

        this.setDefaults = function (defaults)
        {
            this.defaults = angular.extend(this.defaults, defaults);
        };

        this.$get = function ()
        {
            return this;
        };

    }

    function wipImageZoomDirective($timeout)
    {
        return {
            restrict    : 'EA',
            template    : '<div class="wip-image-zoom {{vm.options.style}}-style {{vm.options.thumbsPos}}-thumbs"\n     ng-class="{\n     \'active\':vm.zoomActive, \n     \'immersive-mode\':vm.immersiveModeActive && !immersive,\n     \'zoom-disabled\':!vm.options.zoomEnable,\n     \'box-style\':vm.options.style == \'box\' ,\n     \'inner-style\':vm.options.style == \'inner\'}">\n\n    <wip-image-zoom-thumbs ng-if="vm.options.thumbsPos === \'top\' && vm.images.length > 1"></wip-image-zoom-thumbs>\n\n    <div ng-hide="!vm.options.zoomEnable && immersive" class="main-image-wrapper" ng-class="{\'loading\':vm.largeImageLoading}">\n        <div class="image-zoom-tracker" wip-image-zoom-tracker></div>\n        <div class="image-zoom-lens" wip-image-zoom-lens></div>\n        <img class="main-image" ng-src="{{vm.mainImage.medium}}" alt="{{vm.attrs.alt}}" image-on-load="vm.initZoom()">\n        <div class="zoom-mask"\n             ng-class="vm.options.style == \'box\'? vm.options.boxPos : \'\'"\n             wip-image-zoom-mask>\n            <img wip-image-zoom-image class="zoom-image main-image-large" image-on-load="vm.largeImageLoaded()"\n                 ng-src="{{vm.mainImage.large}}">\n        </div>\n        <div ng-if="vm.immersiveModeActive && !immersive && vm.options.immersiveModeMessage !== \'\'"\n             class="immersive-mode-message" ng-bind="vm.options.immersiveModeMessage"></div>\n    </div>\n\n    <div class="immersive-no-zoom-image-wrapper" ng-show="!vm.options.zoomEnable && immersive">\n        <img class="main-image-large" ng-src="{{vm.mainImage.large}}">\n    </div>\n\n    <wip-image-zoom-thumbs\n            ng-if="vm.options.thumbsPos === \'bottom\' && vm.images.length > 1"></wip-image-zoom-thumbs>\n</div>',
            replace     : true,
            scope       : {
                selectedModel: '=?',
                selectedIndex: '=?',
                wipImageZoom : '=',
                immersive    : '=?'
            },
            controllerAs: 'vm',
            link        : function (scope, element, attrs, ctrl)
            {
                ctrl.el = element;
                ctrl.attrs = attrs;
                ctrl.init();
            },
            controller  : ["$scope", "$document", "$window", "$compile", "wipImageZoomConfig", function ($scope, $document, $window, $compile, wipImageZoomConfig)
            {
                var vm = this,
                    evPosX, evPosY, trackerW, trackerH, trackerL, trackerT, maskW, maskH, zoomImgW, zoomImgH, lensW,
                    lensH, lensPosX, lensPosY, zoomLevelRatio,
                    defaultOpts = angular.copy(wipImageZoomConfig.defaults),
                    updateTimeout = true, unWatchSelectedIndex, unWatchSelectedModel;

                vm.el = {};
                vm.zoomTracker = {};
                vm.zoomLens = {};
                vm.zoomImageEl = {};
                vm.thumbsWrapper = {};
                vm.thumbsEl = {};
                vm.mainImage = {};
                vm.options = {};
                vm.images = [];
                vm.zoomActive = false;
                vm.largeImageLoading = true;

                vm.prevThumbActive = false;
                vm.nextThumbActive = false;
                vm.thumbWidth = 0;
                vm.thumbsWrapperWidth = 0;
                vm.thumbsWidth = 0;
                vm.thumbsPos = 0;
                vm.immersiveModeActive = false;

                vm.init = init;
                vm.initZoom = initZoom;
                vm.initThumbs = initThumbs;
                vm.largeImageLoaded = largeImageLoaded;

                vm.updateMainImage = updateMainImage;
                vm.nextThumb = nextThumb;
                vm.prevThumb = prevThumb;
                vm.disableImmersiveMode = disableImmersiveMode;

                function init()
                {
                    vm.options = !$scope.wipImageZoom ? defaultOpts : angular.extend(defaultOpts, $scope.wipImageZoom);

                    setImages();

                    $scope.selectedIndex = vm.options.defaultIndex;
                    $scope.selectedModel = vm.mainImage;

                    registerWatchers();
                }

                function setImages()
                {
                    if ( vm.options.images.length <= 0 )
                    {
                        vm.options.images = [
                            {
                                thumb : vm.attrs.src,
                                medium: vm.attrs.src,
                                large : vm.attrs.src
                            }
                        ];
                    }

                    vm.images = vm.options.images;
                    vm.mainImage = vm.images[vm.options.defaultIndex];
                }

                function update()
                {
                    // Debounce for update
                    if ( updateTimeout )
                    {
                        $timeout.cancel(updateTimeout);
                    }

                    updateTimeout = $timeout(function ()
                    {
                        initThumbs();
                        initZoom();
                        updateThumbsPos();
                    }, 400);
                }

                function initZoom()
                {
                    if ( !vm.options.zoomEnable )
                    {
                        return;
                    }

                    initSizes();

                    vm.zoomTracker.style.cursor = vm.options.cursor;

                    if ( vm.options.lens )
                    {
                        vm.zoomLens.style.display = 'block';
                    }
                    else
                    {
                        vm.zoomLens.style.display = 'none';
                    }

                    // Reset Event Listeners
                    removeEventListeners();

                    vm.immersiveModeActive = vm.options.immersiveMode && vm.options.immersiveMode > $window.innerWidth || vm.options.immersiveMode === 'always';

                    if ( vm.immersiveModeActive && !$scope.immersive )
                    {
                        vm.zoomTracker.addEventListener('mousedown', enableImmersiveMode);
                    }

                    if ( !vm.immersiveModeActive || $scope.immersive )
                    {
                        addEventListeners();
                    }

                }

                function addEventListeners()
                {
                    vm.zoomTracker.addEventListener('mousemove', zoomStateEnable);
                    vm.zoomTracker.addEventListener('touchstart', zoomStateEnable);

                    vm.zoomTracker.addEventListener('mouseleave', zoomStateDisable);
                    vm.zoomTracker.addEventListener('touchend', zoomStateDisable);

                    vm.zoomTracker.addEventListener('mousemove', setZoomImagePosition);
                    vm.zoomTracker.addEventListener('touchmove', setZoomImagePosition);
                }

                function removeEventListeners()
                {
                    vm.zoomTracker.removeEventListener('mousedown', enableImmersiveMode);

                    vm.zoomTracker.removeEventListener('mousemove', zoomStateEnable);
                    vm.zoomTracker.removeEventListener('touchstart', zoomStateEnable);

                    vm.zoomTracker.removeEventListener('mouseleave', zoomStateDisable);
                    vm.zoomTracker.removeEventListener('touchend', zoomStateDisable);

                    vm.zoomTracker.removeEventListener('mousemove', setZoomImagePosition);
                    vm.zoomTracker.removeEventListener('touchmove', setZoomImagePosition);
                }

                function disableImmersiveMode()
                {
                    $document.find('html').removeClass('wip-image-zoom-immersive-mode-enabled');
                    removeEventListeners();
                    vm.immersedEl.remove();
                    update();
                }

                function enableImmersiveMode(ev)
                {
                    ev.preventDefault();
                    ev.stopPropagation();
                    $scope.$apply(function ()
                    {
                        $document.find('html').addClass('wip-image-zoom-immersive-mode-enabled');
                        var body = $document.find('body').eq(0);
                        vm.immersedImageOpt = angular.extend(angular.copy(vm.options), vm.options.immersiveModeOptions);
                        vm.immersedImageOpt.defaultIndex = $scope.selectedIndex;
                        vm.immersedImageOpt.style = 'inner';
                        vm.immersedEl = $compile('<div class="immersive-wip-image-zoom">\n    <div class="disable-immersive-mode-button" ng-click="vm.disableImmersiveMode()">&#10006;</div>\n    <img src="" wip-image-zoom="vm.immersedImageOpt" immersive="true" selected-index="selectedIndex">\n</div>\n')($scope);
                        body.append(vm.immersedEl);
                        update();
                    });
                }

                function initThumbs()
                {
                    if ( vm.images.length <= 1 )
                    {
                        return;
                    }

                    vm.thumbsWrapperWidth = vm.thumbsWrapper.clientWidth;
                    vm.thumbWidth = Math.round((vm.thumbsWrapperWidth + vm.options.thumbColPadding) / vm.options.thumbCol);
                    vm.thumbsWidth = vm.thumbWidth * vm.images.length;
                    vm.maxPosX = vm.images.length - vm.options.thumbCol;

                    // Set Thumbnail width
                    $scope.$evalAsync(function ()
                    {
                        if ( vm.options.thumbsPos === 'top' )
                        {
                            vm.thumbsEl.style.paddingBottom = vm.options.thumbColPadding + 'px';
                            vm.thumbsEl.style.paddingTop = 0;
                        }
                        else
                        {
                            vm.thumbsEl.style.paddingTop = vm.options.thumbColPadding + 'px';
                            vm.thumbsEl.style.paddingBottom = 0;
                        }

                        for ( var i = 0; i < vm.thumbsEl.children.length; i++ )
                        {
                            var thumb = vm.thumbsEl.children[i];
                            thumb.style.width = vm.thumbWidth + 'px';
                            thumb.style.paddingRight = vm.options.thumbColPadding + 'px';
                        }
                    });
                }

                function nextThumb()
                {
                    scrollThumbs(vm.thumbsPos + 1);
                }

                function prevThumb()
                {
                    scrollThumbs(vm.thumbsPos - 1);
                }

                function scrollThumbs(newPosX)
                {
                    newPosX = newPosX < 0 ? 0 : newPosX;
                    newPosX = newPosX > vm.maxPosX ? vm.maxPosX : newPosX;
                    vm.thumbsPos = newPosX;
                    var scrollX = vm.thumbsPos * vm.thumbWidth * -1;
                    vm.thumbsEl.style.transform = 'translate3d(' + scrollX + 'px, 0px, 0)';
                }

                function initSizes()
                {
                    var trackerPos = vm.zoomTracker.getBoundingClientRect();
                    trackerW = trackerPos.width;
                    trackerH = trackerPos.height;
                    // Box Style
                    if ( vm.options.style === 'box' && !$scope.immersive )
                    {
                        maskW = vm.options.boxW;
                        maskH = vm.options.boxH;
                        vm.zoomMaskEl.style.width = maskW + 'px';
                        vm.zoomMaskEl.style.height = maskH + 'px';
                    }
                    // Inner Style
                    else
                    {
                        maskW = trackerW;
                        maskH = trackerH;
                        vm.zoomMaskEl.style.width = '100%';
                        vm.zoomMaskEl.style.height = '100%';
                    }

                    vm.zoomImageEl.style.width = '';
                    vm.zoomImageEl.style.height = '';

                    if ( vm.options.zoomLevel > 1 )
                    {
                        vm.zoomImageEl.style.width = trackerW * vm.options.zoomLevel + 'px';
                        vm.zoomImageEl.style.height = trackerH * vm.options.zoomLevel + 'px';
                    }
                    else
                    {
                        if ( vm.zoomImageEl.offsetWidth <= maskW || vm.zoomImageEl.offsetHeight <= maskH )
                        {
                            //landscape
                            if ( vm.zoomImageEl.offsetWidth / vm.zoomImageEl.offsetHeight > 1 )
                            {
                                vm.zoomImageEl.style.height = maskH * 1.5 + 'px';
                                vm.zoomImageEl.style.width = '';
                            }
                            // portrait
                            else
                            {
                                vm.zoomImageEl.style.width = maskW * 1.5 + 'px';
                                vm.zoomImageEl.style.height = '';
                            }
                        }
                    }

                    zoomImgW = vm.zoomImageEl.offsetWidth;
                    zoomImgH = vm.zoomImageEl.offsetHeight;
                    setLensSize();

                }

                function setZoomImagePosition(e)
                {
                    e.preventDefault();
                    var te = e.type === 'touchmove' && e.touches && e.touches[0];

                    evPosX = te && te.pageX || e.pageX;
                    evPosY = te && te.pageY || e.pageY;

                    setLensPosition();

                    if ( vm.options.method === 'lens' )
                    {
                        trackLens();
                    }
                    // pointer
                    else
                    {
                        trackPointer();
                    }

                }

                function trackLens()
                {
                    var posX = [(zoomImgW - maskW + lensW * 1 / zoomLevelRatio) * [(lensPosX / trackerW)]];
                    var posY = [(zoomImgH - maskH + lensH * 1 / zoomLevelRatio) * [lensPosY / trackerH]];
                    vm.zoomImageEl.style.transform = 'translate3d(' + posX * -1 + 'px,' + posY * -1 + 'px,0)';
                }

                function trackPointer()
                {
                    var posX = [(zoomImgW - maskW) * [(evPosX - trackerL) / trackerW]];
                    var posY = [(zoomImgH - maskH) * [(evPosY - trackerT) / trackerH]];

                    // Touch Fixes
                    posX = evPosX < trackerL ? 0 : posX;
                    posY = evPosY < trackerT ? 0 : posY;
                    posX = evPosX > trackerL + trackerW ? (zoomImgW - maskW) : posX;
                    posY = evPosY > trackerT + trackerH ? (zoomImgH - maskH) : posY;

                    vm.zoomImageEl.style.transform = 'translate3d(' + posX * -1 + 'px,' + posY * -1 + 'px,0)';
                }

                function setLensSize()
                {
                    zoomLevelRatio = trackerW / zoomImgW;
                    lensW = maskW * zoomLevelRatio;
                    lensH = maskH * zoomLevelRatio;
                    vm.zoomLens.style.width = lensW + 'px';
                    vm.zoomLens.style.height = lensH + 'px';
                }

                function setLensPosition()
                {
                    function getWindow(elem)
                    {
                        return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
                    }

                    function isWindow(obj)
                    {
                        return obj != null && obj === obj.window;
                    }

                    var doc = vm.zoomTracker && vm.zoomTracker.ownerDocument;
                    var win = getWindow(doc);
                    var docElem = doc.documentElement;

                    var trackerPos = vm.zoomTracker.getBoundingClientRect();
                    var trackerT = trackerPos.top + win.pageYOffset - docElem.clientTop;
                    var trackerL = trackerPos.left + win.pageXOffset - docElem.clientLeft;

                    lensPosX = (evPosX - trackerL) - lensW * 0.5;
                    lensPosY = (evPosY - trackerT) - lensH * 0.5;

                    lensPosX = lensPosX > (trackerW - lensW) ? trackerW - lensW : lensPosX;
                    lensPosX = lensPosX < 0 ? 0 : lensPosX;

                    lensPosY = lensPosY > (trackerH - lensH) ? trackerH - lensH : lensPosY;
                    lensPosY = lensPosY < 0 ? 0 : lensPosY;

                    vm.zoomLens.style.transform = 'translate3d(' + lensPosX + 'px,' + lensPosY + 'px,0)';
                }

                function updateThumbsPos()
                {
                    if ( vm.images.length <= 1 || vm.images.length < vm.options.thumbCol )
                    {
                        return;
                    }

                    var selectedIndex = getSelectedIndex();
                    var isInView = vm.thumbsPos + vm.options.thumbCol > selectedIndex && vm.thumbsPos < selectedIndex;
                    if ( isInView )
                    {
                        scrollThumbs(vm.thumbsPos);
                        return;
                    }
                    scrollThumbs(selectedIndex);
                }

                function getSelectedIndex()
                {
                    for ( var i = 0; i < vm.images.length; i++ )
                    {
                        if ( vm.images[i].medium === vm.mainImage.medium )
                        {
                            return i;
                        }
                    }
                }

                function zoomStateEnable()
                {
                    $scope.$evalAsync(function ()
                    {
                        vm.zoomActive = true;
                    });
                }

                function zoomStateDisable()
                {
                    $scope.$evalAsync(function ()
                    {
                        vm.zoomActive = false;
                    });
                }


                function watchSelectedModel(newVal, oldVal)
                {
                    if ( angular.isDefined(newVal) && newVal !== oldVal )
                    {
                        vm.mainImage = newVal;
                        updateThumbsPos();
                    }
                }


                function watchSelectedIndex(newVal, oldVal)
                {
                    if ( angular.isDefined(newVal) && newVal !== oldVal )
                    {
                        vm.mainImage = vm.images[newVal];
                        updateThumbsPos();
                    }
                }

                function updateMainImage(image)
                {

                    vm.largeImageLoading = true;
                    vm.mainImage = image;

                    // Pause Watchers
                    deRegisterWatchers();

                    $scope.selectedModel = angular.copy(vm.mainImage);
                    $scope.selectedIndex = vm.images.indexOf(vm.mainImage);

                    // Resume watchers
                    registerWatchers();
                }

                function registerWatchers()
                {
                    unWatchSelectedIndex = $scope.$watch('selectedIndex', watchSelectedIndex, true);
                    unWatchSelectedModel = $scope.$watch('selectedModel', watchSelectedModel, true);
                }

                function deRegisterWatchers()
                {
                    unWatchSelectedModel();
                    unWatchSelectedIndex();
                }

                function largeImageLoaded()
                {
                    vm.largeImageLoading = false;
                    initSizes();
                }

                angular.element(window).on('resize', function ()
                {
                    update();
                });

                if ( $window.Ps )
                {
                    angular.element(document).on('ps-scroll-y', function ()
                    {
                        initSizes();
                    });
                }

                $scope.$watch(function ()
                {
                    return {
                        left: vm.zoomTracker.getBoundingClientRect().left + $window.scrollX,
                        top : vm.zoomTracker.getBoundingClientRect().top + $window.scrollY
                    };
                }, function (newVal, oldVal)
                {
                    if ( angular.isDefined(newVal) && newVal !== oldVal )
                    {
                        update();
                    }
                }, true);

                $scope.$watch('wipImageZoom', function (newVal, oldVal)
                {
                    if ( angular.isDefined(newVal) && newVal !== oldVal )
                    {
                        init();
                        update();
                    }
                }, true);
            }]
        };
    }

    function wipImageZoomLensDirective()
    {
        return {
            restrict: 'EA',
            require : '^wipImageZoom',
            link    : function (scope, element, attrs, ctrl)
            {
                ctrl.zoomLens = element[0];
            }
        };
    }

    function wipImageZoomTrackerDirective()
    {
        return {
            restrict: 'EA',
            require : '^wipImageZoom',
            link    : function (scope, element, attrs, ctrl)
            {
                ctrl.zoomTracker = element[0];
            }
        };
    }

    function wipImageZoomMaskDirective()
    {
        return {
            restrict: 'EA',
            require : '^wipImageZoom',
            link    : function (scope, element, attrs, ctrl)
            {
                ctrl.zoomMaskEl = element[0];
            }
        };
    }

    function wipImageZoomImageDirective()
    {
        return {
            restrict: 'EA',
            require : '^wipImageZoom',
            link    : function (scope, element, attrs, ctrl)
            {
                ctrl.zoomImageEl = element[0];
            }
        };
    }

    function wipImageZoomThumbsDirective()
    {
        return {
            restrict: 'EA',
            require : '^wipImageZoom',
            template: '<div class="thumbs-wrapper" ng-swipe-left="vm.nextThumb()" ng-swipe-right="vm.prevThumb()">\n    <div class="thumbs" >\n        <div class="thumb-wrapper" ng-repeat="image in vm.images">\n            <img ng-src="{{image.thumb}}" ng-click="vm.updateMainImage(image)"\n                 ng-class="{\'selected\': vm.mainImage.thumb === image.thumb}">\n        </div>\n    </div>\n</div>\n<div class="prev-button"\n     ng-if="vm.thumbsPos !== 0 && vm.images.length > vm.options.thumbCol"\n     ng-click="vm.prevThumb()"\n     ng-bind-html="vm.options.prevThumbButton">Prev\n</div>\n<div class="next-button"\n     ng-if="vm.thumbsPos !== vm.maxPosX && vm.images.length > vm.options.thumbCol"\n     ng-click="vm.nextThumb()"\n     ng-bind-html="vm.options.nextThumbButton">Next\n</div>',
            link    : function (scope, element, attrs, ctrl)
            {
                ctrl.thumbsWrapper = element[0].getElementsByClassName('thumbs-wrapper')[0];
                ctrl.thumbsEl = element[0].getElementsByClassName('thumbs')[0];
                ctrl.initThumbs();
            }
        };
    }

    function imageOnLoadDirective($log)
    {
        return {
            restrict: 'A',
            link    : function (scope, element, attrs)
            {
                element[0].addEventListener('load', function ()
                {
                    scope.$apply(attrs.imageOnLoad);
                }, false);
                element[0].addEventListener('error', function ()
                {
                    $log.warn('image could not be loaded');
                });
            }
        };
    }

})();
;