﻿Function.prototype.method = function(name, fn) {
    this.prototype[name] = fn;
    return this;
};

/****** Publisher/Subscriber *****/
function Publisher() {
    this.subscribers = [];
}

Publisher.prototype.deliver = function(data) {
    for (var index = 0; index < this.subscribers.length; index++) {
            this.subscribers[index](data);
    }
    return this;
};

Function.prototype.subscribe = function(publisher) {
    var alreadyExists = false;
    for (var index = 0; index < publisher.subscribers.length; index++) {
        var subscriber = publisher.subscribers[index];
        if (subscriber == this) {
            alreadyExists = true;
            break;
        }
    }

    if (!alreadyExists) {
        publisher.subscribers.push(this);
    }

    return this;
};

Function.prototype.unsubscribe = function(publisher) {
    var that = this;

    var newArray = [];
    for (var index = 0; index < publisher.subscribers.length; index++) {
        var subscriber = publisher.subscribers[index];
        if (subscriber === this) {
            continue;
        }

        newArray.push(subscriber);
    }

    publisher.subscribers = newArray;

    return this;
};

var AjaxManager = {};

AjaxManager.Territory = (function() {
    function getTerritoriesForZipCodeSuccess(res, that) {
        var response = JSON.parse(res);
        if (response === undefined || response.length === 0) {
            that.onTerritoriesRetrieved.deliver([]);
        }

        var territories = [];
        for (var index = 0; index < response.length; index++) {
            territories.push(response[index]);
        }
        that.onTerritoriesRetrieved.deliver(territories);
    }

    function onChangeZipCodeSuccess(res, that) {
        var response = JSON.parse(res);
        if (response === undefined || response.length === 0) {
            that.onNoTerritoryFound.deliver(false);
        } else if (response.length === 1) {
            that.setTerritory(response[0]);
        } else {
            var cachedTerritoryID;
            var cachedTerritory = cache.getItem('Territory');
            if (cachedTerritory === null) {
                cachedTerritoryID = $.cookie(SESSION_GUID, 'territoryID');
            } else {
                cachedTerritoryID = cachedTerritory.TerritoryID;
            }
            var selectionNeeded = true;
            if (cachedTerritoryID !== null) {
                for (var i = 0; i < response.length; i++) {
                    var t = response[i];
                    if (cachedTerritoryID === t.TerritoryID.toString()) {
                        that.setTerritory(t);
                        selectionNeeded = false;
                        break;
                    }
                }
            }

            if (selectionNeeded) {
                that.onMultipleTerritoriesFound.deliver(response)
            }
        }
    }

    function wsGetTerritoryByZip(zipCodeRequest, onSuccess, onError, onComplete) {
        $.ajax({
            url: '/Service.asmx/GetTerritoryByZip',
            type: 'POST',
            async: false,
            datatype: 'json',
            timeout: 10000,
            data: zipCodeRequest,
            contentType: 'application/json; charset=utf-8',
            success: onSuccess,
            error: onError,
            complete: onComplete
        });
    }

    return {
        onNoTerritoryFound: new Publisher,
        onTerritoryChanged: new Publisher,
        onMultipleTerritoriesFound: new Publisher,
        onError: new Publisher,
        onComplete: new Publisher,
        onTerritoriesRetrieved: new Publisher,

        getTerritory: function() {
            return cache.getItem("Territory");
        },
        setTerritory: function(territory) {
            cache.setItem("Territory", territory, { expirationAbsolute: null,
                expirationSliding: 3600,
                priority: CachePriority.High
            });
            if (territory === null) {
                $.cookie(SESSION_GUID, 'territoryID', null, { path: '/' });
                return;
            }
            var cookies = {};
            cookies['territoryID'] = territory.TerritoryID;
            cookies['zip_code'] = territory.Zip;
            $.setCookieInBulk(SESSION_GUID, cookies, true);

            this.onTerritoryChanged.deliver(territory);
            var operationManager = AjaxManager.Operation || {};
            operationManager.changeOperation(territory);
        },
        changeZipCode: function(zipCode) {
            var territory = cache.getItem("Territory");
            if (territory && territory.Zip.toString() === zipCode.toString()) {
                this.setTerritory(territory);
                return;
            }

            var zipCodeRequest = {};
            zipCodeRequest.ZipCode = zipCode;
            var json_zipCodeRequest = JSON.stringify(zipCodeRequest);
            var that = this;
            wsGetTerritoryByZip(json_zipCodeRequest, function(res) { onChangeZipCodeSuccess(res, that); }, function() { that.onError.deliver(); }, function() { that.onComplete.deliver(); });
        },
        getTerritoriesForZipCode: function(zipCode) {
            var zipCodeRequest = {};
            zipCodeRequest.ZipCode = zipCode;
            var json_zipCodeRequest = JSON.stringify(zipCodeRequest);
            var that = this;
            wsGetTerritoryByZip(json_zipCodeRequest, function(res) { getTerritoriesForZipCodeSuccess(res, that); }, function() { that.onError.deliver(); });
        }
    };
})();

AjaxManager.Operation = (function() {
    function onChangeOperationSucess(res, that) {
        if (res === undefined) {
            that.onError.deliver();
        }

        that.setOperation(JSON.parse(res));
    }

    function wsGetOperationByTerritory(operationRequest, onSuccess, onError) {
        //get the territory information
        $.ajax({
            url: '/Service.asmx/GetOperationByTerritory',
            type: 'POST',
            datatype: 'json',
            async: false,
            data: operationRequest,
            timeout: 10000,
            contentType: 'application/json; charset=utf-8',
            success: onSuccess,
            error: onError
        });
    }

    return {
        onOperationChanged: new Publisher,
        onOperationsRetrieved: new Publisher,
        onError: new Publisher,

        getOperation: function() {
            return cache.getItem("Operation");
        },
        setOperation: function(operation) {
            cache.setItem("Operation", operation, { expirationAbsolute: null,
                expirationSliding: 3600,
                priority: CachePriority.High
            });

            if (operation === null) {
                $.cookie(SESSION_GUID, 'operationID', null, { path: '/' });
                return;
            }
            $.cookie(SESSION_GUID, 'operationID', operation.OperationID, { path: '/' });

            this.onOperationChanged.deliver(operation);
            var areasAndServicesManager = AjaxManager.AreasAndServices || {};
            areasAndServicesManager.changeAreasAndServices(operation);

            var associationsManager = AjaxManager.Associations || {};
            associationsManager.changeAssociations(operation);
        },
        changeOperation: function(territory) {
            var operation = cache.getItem("Operation");
            if (operation && operation.OperationID.toString() === territory.OperationID.toString()) {
                this.setOperation(operation);
                return;
            }
            var json_operationRequest = JSON.stringify({ Territory: territory });
            var that = this;
            wsGetOperationByTerritory(json_operationRequest, function(res) { onChangeOperationSucess(res, that); }, function() { that.onError.deliver(); });
        },
        getOperationsForZipCode: function(zipCode) {
            var that = this;
            var t = AjaxManager.Territory;
            var fn = function(territories) {
                var operations = [];
                for (var index = 0; index < territories.length; index++) {
                    var json_operationRequest = JSON.stringify({ Territory: territories[index] });
                    wsGetOperationByTerritory(json_operationRequest,
						function(res) {
						    if (res !== undefined) {
						        operations.push(JSON.parse(res));
						    }
						});
                }
                that.onOperationsRetrieved.deliver(operations);
                arguments.callee.unsubscribe(t.onTerritoriesRetrieved);
            }
            fn.subscribe(t.onTerritoriesRetrieved);
            t.getTerritoriesForZipCode(zipCode);
        }
    };
})();

var Service = function(serviceID, description) {
    this.serviceId = serviceID;
    this.description = description;
}

AjaxManager.AreasAndServices = (function() {
    return {
        onAreasAndServicesChanged: new Publisher,
        onComplete: new Publisher,
        onError: new Publisher,

        getAreasAndServices: function() {
            return cache.getItem("AreasAndServices");
        },
        setAreasAndServices: function(areasAndServices) {
            //cache results
            cache.setItem("AreasAndServices", areasAndServices, { expirationAbsolute: null,
                expirationSliding: 3600,
                priority: CachePriority.High
            });

            this.onAreasAndServicesChanged.deliver(areasAndServices);
        },
        changeAreasAndServices: function(operation) {
            var areasAndServices_request = JSON.stringify({ Operation: operation });
            var that = this;

            //get service information
            $.ajax({
                url: '/Service.asmx/GetAreasAndServices',
                type: 'POST',
                datatype: 'json',
                data: areasAndServices_request,
                timeout: 10000,
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    if (res === undefined) {
                        that.onError.deliver();
                    }
                    that.setAreasAndServices(JSON.parse(res));
                },
                error: function() {
                    that.onError.deliver();
                },
                complete: function() {
                    that.onComplete.deliver();
                }
            });
        },
        Areas: {
            Carpet: {},
            Upholstered: {},
            Leather: {},
            Auto: {},
            TileGrout: {},
            AirDuct: {},
            Guarantee: {}
        },
        buildAreas: function() {
            var aas = this.getAreasAndServices();

            if (aas == undefined) {
                return;
            }

            for (var i in aas.CarpetCollection.Areas) {

                var area = aas.CarpetCollection.Areas[i];
                this.Areas.Carpet[area.Description] = area.AreaID;
            }

            for (var i in aas.UpholsteredCollection.Areas) {
                var area = aas.UpholsteredCollection.Areas[i];
                this.Areas.Upholstered[area.Description] = area.AreaID;
            }

            for (var i in aas.LeatherCollection.Areas) {
                var area = aas.LeatherCollection.Areas[i];
                this.Areas.Leather[area.Description] = area.AreaID;
            }

            for (var i in aas.AutomobileCollection.Areas) {
                var area = aas.AutomobileCollection.Areas[i];
                this.Areas.Auto[area.Description] = area.AreaID;
            }

            for (var i in aas.TileCollection.Areas) {
                var area = aas.TileCollection.Areas[i];
                this.Areas.TileGrout[area.Description] = area.AreaID;
            }

            for (var i in aas.AirDuctCollection.Areas) {
                var area = aas.AirDuctCollection.Areas[i];
                this.Areas.AirDuct[area.Description] = area.AreaID;
            }
        },
        Services: {
            Carpet: {Clean: null, Protect: null, Deodorize: null},
            Upholstered: { Clean: null, Protect: null, Deodorize: null },
            Leather: { Clean: null, Protect: null, Moisturize: null },
            Auto: { Clean: null },
            TileGrout: { Clean: null, ClearSeal: null, ColorSeal: null },
            AirDuct: { Clean: null},
            Guarantee: { Guarantee: null, GSC: null, Renewal: null }
        },
        buildServices: function() {
            var aas = this.getAreasAndServices();

            for (var i in aas) {
                aas[i].findService = function(id) {
                    for (var i in this.Services) {
                        if (this.Services[i].ServiceID == id) {
                            var service = this.Services[i];
                            return new Service(service.ServiceID, service.Description);
                        }
                    }
                }
            }

            this.Services.Carpet.Clean = aas.CarpetCollection.findService(1);
            this.Services.Carpet.Protect = aas.CarpetCollection.findService(2);
            this.Services.Carpet.Deodorize = aas.CarpetCollection.findService(3);
            this.Services.Upholstered.Clean = aas.UpholsteredCollection.findService(1);
            this.Services.Upholstered.Protect = aas.UpholsteredCollection.findService(2);
            this.Services.Upholstered.Deodorize = aas.UpholsteredCollection.findService(3);
            this.Services.Leather.Clean = aas.LeatherCollection.findService(9);
            this.Services.Leather.Moisturize = aas.LeatherCollection.findService(10);
            this.Services.Leather.Protect = aas.LeatherCollection.findService(11);
            this.Services.Auto.Clean = aas.AutomobileCollection.findService(1);
            this.Services.TileGrout.Clean = aas.TileCollection.findService(4);
            this.Services.TileGrout.ClearSeal = aas.TileCollection.findService(5);
            this.Services.TileGrout.ColorSeal = aas.TileCollection.findService(6);
            this.Services.AirDuct.Clean = aas.AirDuctCollection.findService(8);
            this.Services.Guarantee.Guarantee = new Service(12, "Guarantee");
            this.Services.Guarantee.GSC = new Service(13, "GSC");
            this.Services.Guarantee.Renewal = new Service(14, "Renewal");
        }
    };
})();

function initAreasAndServicesList() {
    AjaxManager.AreasAndServices.buildAreas();
    AjaxManager.AreasAndServices.buildServices();
}
initAreasAndServicesList.subscribe(AjaxManager.AreasAndServices.onComplete);
initAreasAndServicesList.subscribe(AjaxManager.AreasAndServices.onAreasAndServicesChanged);

AjaxManager.Associations = (function() {
    return {
        onAssociationsChanged: new Publisher,
        onError: new Publisher,

        changeAssociations: function(operation) {
            var associations_request = JSON.stringify({ Operation: operation });
            var that = this;

            $.ajax({
                url: '/Service.asmx/GetAssociations',
                type: 'POST',
                datatype: 'json',
                timeout: 10000,
                data: associations_request,
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    if (res === undefined) {
                        that.onError.deliver();
                    }
                    that.onAssociationsChanged.deliver(JSON.parse(res));
                },
                error: function() {
                    that.onError.deliver();
                }
            });
        }

    }
})();

AjaxManager.Customer = (function() {

    function extendAccount(account) {
        account.getAddressByID = getAddressByID();
        account.setSelectedAddressID = setSelectedAddressID();
        account.getSelectedAddress = getSelectedAddress();

        if (account.selectedAddressID === undefined) {
            account.selectedAddressID = 0;
        }
    };

    function isAccountEmpty(account) {
        if (account === undefined || account === null || account.AddressBook === null) {
            return true;
        }

        return false;
    };

    function getAddressByID(addressID) {
        return function(addressID) {
            for (var i = 0; i < this.AddressBook.length; i++) {
                if (this.AddressBook[i].AddressID === addressID) {
                    return this.AddressBook[i];
                }
            }

            return null;
        }
    };

    function getSelectedAddress() {
        return function() {
            if (this.AddressBook.length === 1 || this.selectedAddressID === 0) {
                return this.AddressBook[0];
            }

            for (var i = 0; i < this.AddressBook.length; i++) {
                if (this.AddressBook[i].AddressID === this.selectedAddressID) {
                    return this.AddressBook[i];
                }
            }

            return null;
        }
    };

    function setSelectedAddressID(addressID) {
        return function(addressID) {
            this.selectedAddressID = addressID;
            AjaxManager.Customer.setAccount(this)
        }
    };

    return {
        onComplete: new Publisher,
        onSignedIn: new Publisher,
        onSignedOut: new Publisher,
        onErrorCreatingCustomer: new Publisher,
        onSignInError: new Publisher,
        onPasswordRequested: new Publisher,
        onPasswordRequestedError: new Publisher,
        onNewAccountCreated: new Publisher,
        onNewAccountCreatedError: new Publisher,
        onNewAccountCreatedInvalid: new Publisher,
        onAccountUpdated: new Publisher,
        onAccountUpdatedError: new Publisher,
        onAccountUpdatedInvalid: new Publisher,
        onGetOrderHistory: new Publisher,
        onAddressAdded: new Publisher,

        hasChanged: function(customer) {
            //TODO: redo logic to handle the account (if still needed).
            return true;
        },
        getAccount: function() {
            var account = $.cookie(SESSION_GUID, 'account')
            if (account === null) {
                return null;
            }

            account = JSON.parse(account);
            extendAccount(account);

            this.onComplete.deliver(account);
            return account;
        },

        setAccount: function(account) {

            extendAccount(account);

            $.cookie(SESSION_GUID, 'account', JSON.stringify(account), { async: false });
        },
        enhanceAccount: function(newProperty, value) {
            var account = this.getAccount();
            if (account === undefined || account === null) {
                return;
            }
            //adds objects to the customer account object stored in the cookie only.
            account[newProperty] = value;
            this.setAccount(account);
        },
        signOut: function() {
            $.cookie(SESSION_GUID, 'account', null);

            this.onSignedOut.deliver();
        },
        getOrderHistory: function() {
            var account = this.getAccount();
            if (account === null) {
                return null;
            }

            var account = { account: account };
            var that = this;
            $.ajax({
                url: '/Service.asmx/GetCustomerOrderHistory',
                type: 'POST',
                datatype: 'json',
                timeout: 50000,
                data: JSON.stringify(account),
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    var orderHistory = JSON.parse(res);
                    if (res === undefined || orderHistory === null || orderHistory.length === 0) {
                        that.onGetOrderHistory.deliver(null);
                    }
                    that.onGetOrderHistory.deliver(orderHistory);
                },
                error: function() { that.onGetOrderHistory.deliver(null); }
            });
        },
        signIn: function(username, password) {
            var that = this;
            var login_request = {
                username: username,
                password: password
            };

            $.ajax({
                url: '/Service.asmx/GetCustomerByLogin',
                type: 'POST',
                datatype: 'json',
                timeout: 100000,
                data: JSON.stringify(login_request),
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    var account = JSON.parse(res);
                    if (res === undefined || account === null || account.Customers === null) {
                        that.onSignInError.deliver(login_request);
                        return;
                    }

                    if (account.IsError) {
                        that.onSignInError.deliver(login_request);
                        return;
                    }

                    that.setAccount(account);
                    that.onComplete.deliver(account);
                    that.onSignedIn.deliver(account);
                },
                error: function() {
                    that.onSignInError.deliver(username, password);
                }
            });
        },
        requestPassword: function(emailaddress) {
            var forgot_password_request = JSON.stringify({
                EmailAddress: emailaddress
            });
            var that = this;
            $.ajax({
                url: '/Service.asmx/SendCustomerPassword',
                type: 'POST',
                async: false,
                datatype: 'json',
                timeout: 10000,
                data: forgot_password_request,
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    if (res == "true" || res == "True") {
                        that.onPasswordRequested.deliver(emailaddress);
                    }
                    else {
                        that.onPasswordRequestedError.deliver(emailaddress);
                    }
                },
                error: function() { that.onPasswordRequestedError.deliver(emailaddress); }
            });
        },
        createNewAccount: function(account) {
            var account_info = JSON.stringify({ account: account });
            var that = this;

            $.ajax({
                url: '/Service.asmx/CreateAccount',
                type: 'POST',
                async: true,
                datatype: 'json',
                timeout: 10000,
                data: account_info,
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    var newAccount = JSON.parse(res);
                    if (res === undefined || newAccount === null || newAccount.IsError) {
                        that.onNewAccountCreatedError.deliver(account);
                        return;
                    }

                    if (!(newAccount.IsValid)) {
                        that.onNewAccountCreatedInvalid.deliver(newAccount);
                    } else {
                        that.setAccount(newAccount);
                        that.onNewAccountCreated.deliver(newAccount);
                    }
                },
                error: function() {
                    that.onNewAccountCreatedError.deliver(account);
                }
            });
        },
        updateAccount: function(oldAccount) {
            var that = this;

            for (var i in oldAccount.AddressBook) {
                oldAccount.AddressBook[i].AddressID = 0;
                delete oldAccount.AddressBook[i].CustomerRecord;
            }

            var account_info = JSON.stringify({ account: oldAccount });

            $.ajax({
                url: '/Service.asmx/UpdateAccount',
                type: 'POST',
                async: true,
                datatype: 'json',
                timeout: 10000,
                data: account_info,
                contentType: 'application/json; charset=utf-8',
                success: function(res) {
                    var updatedAccount = JSON.parse(res);

                    if (res === undefined || updatedAccount === null || updatedAccount.IsError) {
                        that.onAccountUpdatedError.deliver(oldAccount);
                        return;
                    }

                    if (!(updatedAccount.IsValid)) {
                        that.onAccountUpdatedInvalid.deliver(updatedAccount);
                    } else {

                        var newAddressID = null;
                        for (var i = updatedAccount.AddressBook.length - 1; i > 0; i--) {
                            var addressID = updatedAccount.AddressBook[i].AddressID;
                            if (oldAccount.getAddressByID(addressID) === null) {
                                newAddressID = addressID;
                                break;
                            }
                        }

                        that.setAccount(updatedAccount);
                        that.onAccountUpdated.deliver(updatedAccount);

                        if (newAddressID !== null) {
                            that.onAddressAdded.deliver(newAddressID);
                        }
                    }
                },
                error: function() { that.onAccountUpdatedError.deliver(oldAccount); }
            });
        }
    }
})();

var GuaranteeManager = function() {
    this.active = {};
    this.inactive = {};
    this.onActivation = new Publisher;
    this.onDeactivation = new Publisher;
    this.onComplete = new Publisher;
    this.onError = new Publisher;
    _initialized = false;

    this.clear = function() {
        this.active = {};
        this.inactive = {};
        $.cookie(SESSION_GUID, 'guar_list', null);
    }

    this.clear.subscribe(AjaxManager.Customer.onSignedOut);

    this.activate = function(id) {
        this.initialize();
        this.active[id] = this.inactive[id];
        delete this.inactive[id];
        this.save();
        this.onActivation.deliver(id);
        return this;
    }

    this.deactivate = function(id) {
        this.initialize();
        this.inactive[id] = this.active[id];
        delete this.active[id];
        this.onDeactivation.deliver(id);
        this.save();
        return this;
    }

    this.getAll = function() {
        this.initialize();
        var list = [];

        for (var i in this.active) {
            this.active[i].active = true;
            list.push(this.active[i]);
        }
        for (var j in this.inactive) {
            this.inactive[j].active = false;
            list.push(this.inactive[j]);
        }

        return list;
    }

    this.hasActive = function() {
        this.initialize();
        var active = false;
        for (var i in this.active) {
            active = true;
        }
        return active;
    }

    this.isActive = function(guar) {
        var id = "0";
        if (typeof guar === "object") {
            id = guar.Id;
        } else if (typeof guar === "string") {
            id = guar;
        }

        for (var k in this.active) {
            if (k == id) {
                return true;
            }
        }

        return false;
    }

    this.count = function() {
        this.initialize();
        var c = 0;
        for (var i in this.active) {
            c++;
        }
        for (var j in this.inactive) {
            c++;
        }
        return c;
    }

    this.isEmpty = function() {
        this.initialize();
        var empty = true;

        for (var i in this.inactive) {
            empty = false;
        }

        for (var i in this.active) {
            empty = false;
        }

        return empty;
    }


    this.save = function() {
        $.cookie(SESSION_GUID, 'guar_list', JSON.stringify(this));
        return this;
    }

    this.loadFromCookie = function() {
        var cookie = $.cookie(SESSION_GUID, 'guar_list');
        if (cookie === null || cookie === undefined) return;
        var temp = JSON.parse(cookie);

        this.active = temp.active;
        this.inactive = temp.inactive;
        this.onComplete.deliver(temp);
        return this;
    }

    this.loadFromService = function() {
        var that = this;
        var results;
        var account = AjaxManager.Customer.getAccount();

        $.ajax({
            url: '/Service.asmx/GetGuaranteeHistory',
            type: 'POST',
            datatype: 'json',
            async: false,
            data: JSON.stringify({ account: account }),
            contentType: 'application/json; charset=utf-8',
            success: function(res) {
                results = JSON.parse(res);
                that.onComplete.deliver(results);
            },
            error: function(err) {
                that.onError.deliver(err);
            }
        });

        for (var k in results) {
            this.inactive[results[k].Id] = results[k];
        }
        this.save();
        return this;
    };

    this.load = function() {
        if ($.cookie(SESSION_GUID, 'guar_list') === null
             || $.cookie(SESSION_GUID, 'guar_list') === undefined) {
            this.loadFromService();
        } else {
            this.loadFromCookie();
        }
    }

    this.initialize = function() {
        if (!_initialized) {
            _initialized = true;
            this.load();
        }
    }

    this.addGSCs = function() {
        this.initialize();
        if (!this.hasActive()) {
            return;
        }

        for (var i in this.active) {
            SchedulingTool.addGuarantee(this.active[i], false);
        }
    }
};

AjaxManager.Guarantee = new GuaranteeManager();


AjaxManager.Promotion = {
    onComplete: new Publisher,
    onError: new Publisher,
    onPromotionChagned: new Publisher,
    promotions: {},

    loadPromotions: function() {
        var that = this;
        var terr = AjaxManager.Territory.getTerritory();

        var promo_request = {
            territory: terr
        }

        $.ajax({
            url: '/Service.asmx/getPromoCodes',
            type: 'POST',
            async: true,
            datatype: 'json',
            timeout: 10000,
            data: JSON.stringify(promo_request),
            contentType: 'application/json; charset=utf-8',
            success: function(res) {
                var results = JSON.parse(res);
                that.promotions = results;
                that.onComplete.deliver(results);
            },
            error: function(err) {
                that.onError.deliver();
            }
        });
    },

    validatePromoCode: function(code) {
        for (var i in this.promotions) {
            if (this.promotions[i].PromoCode.toUpperCase() === code) {
                return this.promotions[i];
            }
        }
        return false;
    },

    setActivePromotion: function(code) {
        for (var i in this.promotions) {
            if (this.promotions[i].PromoCode.toUpperCase() === code) {
                $.cookie(SESSION_GUID, 'activePromotion', JSON.stringify(this.promotions[i]));
            }
        }
    },

    getActivePromotion: function() {
        var json = $.cookie(SESSION_GUID, 'activePromotion');
        if (json === null || json === undefined) return null;
        var promo = JSON.parse(json);
        return promo;
    },

    clearActivePromotion: function() {
    $.cookie(SESSION_GUID, 'activePromotion', null);
    }
};

function loadPromo() {
    AjaxManager.Promotion.loadPromotions();
}
loadPromo.subscribe(AjaxManager.Territory.onComplete);

AjaxManager.Discount = (function() {
    return {
        hasSpecial: false,
        hasPromo: true,
        hasGuarantee: true,

        setActiveDiscountType: function(type) {
            $.cookie(SESSION_GUID, 'activeDiscount', type);
        },

        getActiveDiscountType: function() {
            var type = $.cookie(SESSION_GUID, 'activeDiscount');
            if (type === null || type === undefined) return 'NONE';
            else return type;
        },

        getActiveDiscount: function() {
            var type = $.cookie(SESSION_GUID, 'activeDiscount');

            switch (type) {
                case 'NONE': return null;
                case 'SPECIAL':
                    var specialJson = $.cookie(SESSION_GUID, 'current_special');
                    var special = JSON.parse(specialJson);
                    return special;
                case 'PROMO':
                    return AjaxManager.Promotion.getActivePromotion();
                case 'GUARANTEE': return null;
                default: return null;
            }
        },

        clearActiveDiscount: function() {
            $.cookie(SESSION_GUID, 'activeDiscount', 'NONE');
            AjaxManager.Promotion.clearActivePromotion();
        }
    }
})();

AjaxManager.Estimate = {
    onOrderGuaranteed: new Publisher,
    onOrderNotGuaranteed: new Publisher,
    onUpdateTotal: new Publisher,

    isGuaranteed: false,

    publishTotal: function(data) {
        this.onUpdateTotal.deliver(data);
    },

    publishOrderGuaranteed: function(data) {
        this.isGuaranteed = true;
        this.onOrderGuaranteed.deliver(data);
    },

    publishOrderNotGuaranteed: function(data) {
        this.isGuaranteed = false;
        this.onOrderNotGuaranteed.deliver(data);
    }
}

function initGuarantee() {
    AjaxManager.Guarantee.initialize();
}
initGuarantee.subscribe(AjaxManager.Customer.onComplete);

function clearGuaranteeHistory() {
    AjaxManager.Guarantee.clear();
}
clearGuaranteeHistory.subscribe(AjaxManager.Customer.onSignedIn);