﻿// Root Namespace
var aspdnsf = new function() { };

aspdnsf.StringResource = {

    initialize: function() {
        this.strings = new Hash();
    },

    registerString: function(key, value) {
        this.strings[key] = value;
    },

    getString: function(key) {
        if (this.strings[key]) {
            return this.strings[key];
        }
        else {
            return key;
            //return aspdnsf.Constants.EMPTY_STRING;
        }
    }

}

aspdnsf.StringResource.initialize();

// uses numberFormat154.js internally
aspdnsf.CurrencyFormatter = {

    initialize: function() {
        // set defaults
        this.symbol = '';
        this.decimalDigits = 2;
    },

    setSymbol: function(symbol) {
        this.symbol = symbol;
    },

    setDecimalDigits: function(digits) {
        this.decimalDigits = digits;
    },

    format: function(price) {
        var formatter = new NumberFormat();
        formatter.setCurrencyValue(this.symbol);
        formatter.setPlaces(this.decimalDigits, false);
        formatter.setInputDecimal('.');
        formatter.setCurrency(true);
        formatter.setCurrencyPosition(formatter.LEFT_OUTSIDE);
        formatter.setNegativeFormat(formatter.LEFT_DASH);
        formatter.setNegativeRed(false);
        formatter.setSeparators(true, ',', ',');
        formatter.setNumber(price);

        return formatter.toFormatted();
    }

}

aspdnsf.CurrencyFormatter.initialize();

aspdnsf.Errors = new Object();
aspdnsf.Errors.ValidateError = new Object();

aspdnsf.Errors.ValidateError.MissingRequiredItem = 1;
aspdnsf.Errors.ValidateError.EmptyTextItem = 1;

aspdnsf.Controls = new function() { };


aspdnsf.Controls.PriceDeltaControl = Class.create();
aspdnsf.Controls.PriceDeltaControl.prototype = {

    initialize: function(id, clientId) {
        this.id = id;
        this.ctrl = $(clientId);
    },

    setControl: function(control) {
        if (control) {
            control.addDeltaPriceChangedEventHandler(this.controlDeltaPriceChangedEventHandler.bind(this));
        }
    },

    controlDeltaPriceChangedEventHandler: function(control) {
        if (!control.hasLoaded) {

            if (control.getPrice() > 0) {
                var delta = control.getPrice();
                var display = '';

                display = ', ' + aspdnsf.StringResource.getString('showproduct.aspx.14') + ' ' + aspdnsf.CurrencyFormatter.format(delta);

                if (control.getIsVatEnabled()) {
                    if (control.getIsVatInclusive()) {
                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
                    }
                    else {
                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
                    }
                }

                this.ctrl.innerHTML = display;
            }

            //            if (control.getIsIncluded() && control.getPrice() == 0) {
            //                //this.ctrl.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.10');
            //            }
            //            else {
            //                var delta = control.getDeltaPrice();
            //                var display = '';

            //                // if(delta>=0) {
            //                display = ', ' + aspdnsf.StringResource.getString('showproduct.aspx.14') + ' ' + aspdnsf.CurrencyFormatter.format(delta);
            //                //}
            //                //else {
            //                //     display = aspdnsf.StringResource.getString('showproduct.aspx.15') + ' ' + aspdnsf.CurrencyFormatter.format(Math.abs(delta));
            //                //}

            //                if (control.getIsVatEnabled()) {
            //                    if (control.getIsVatInclusive()) {
            //                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
            //                    }
            //                    else {
            //                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
            //                    }
            //                }

            //                this.ctrl.innerHTML = display;
            //            }
            control.hasLoaded = true;
        }
    }

}

aspdnsf.Controls.KitItemRadioControl = Class.create();
aspdnsf.Controls.KitItemRadioControl.prototype = {

    initialize: function(id, clientId, price, name) {
        this.id = id;
        this.name = name;

        this.ctrl = $(clientId);
        this.ctrl.onclick = this.onSelected.bind(this);
        this.price = price;
        this.isIncluded = false;
        this.deltaPrice = 0.0;
        this.selectedEventHandlers = new Array();
        this.deltaPriceChangedEventHandlers = new Array();
        this.hasLoaded = false;

        this.tax = 1;
        this.discount = 0;
        this.vatEnabled = false;
        this.vatInclusive = false;
    },

    getId: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    },

    getPrice: function(excludeDiscount) {
        if (arguments.length == 0 || !excludeDiscount) {
            return this.price * this.tax * (1 - (this.discount / 100));
        }

        return this.price * this.tax;
    },

    getDeltaPrice: function() {
        return this.deltaPrice;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    compareWith: function(other) {
        var delta = 0;
        if (other == this) {
            delta = 0;
        }
        else {
            delta = this.getPrice() - other.getPrice();
        }

        this.setDeltaPrice(delta);
    },

    setDeltaPrice: function(delta) {
        this.deltaPrice = delta;

        this.onDeltaPriceChanged();
    },

    getIsIncluded: function() {
        return this.isIncluded;
    },

    setIsIncluded: function(included) {
        this.isIncluded = included;
    },

    addSelectedEventHandler: function(handler) {
        this.selectedEventHandlers.push(handler);
    },

    onSelected: function() {
        for (var ctr = 0; ctr < this.selectedEventHandlers.length; ctr++) {
            var handler = this.selectedEventHandlers[ctr];
            handler(this);
        }
    },

    addDeltaPriceChangedEventHandler: function(handler) {
        this.deltaPriceChangedEventHandlers.push(handler);
    },

    onDeltaPriceChanged: function() {
        for (var ctr = 0; ctr < this.deltaPriceChangedEventHandlers.length; ctr++) {
            var handler = this.deltaPriceChangedEventHandlers[ctr];
            handler(this);
        }
    }

}

aspdnsf.Controls.KitRadioGroupControl = Class.create();
aspdnsf.Controls.KitRadioGroupControl.prototype = {

    initialize: function(id) {
        this.id = id;
        this.controls = new Array();
        this.selectionChangedEventHandlers = new Array();
        this.selectedControl = null;

        this.required = false;
    },

    getId: function() {
        return this.id;
    },

    getIsRequired: function() {
        return this.required;
    },

    setIsRequired: function(required) {
        this.required = required;
    },

    getSelectedItems: function() {
        return [this.selectedControl];
    },

    getDeltaPrice: function(excludeDiscount) {
        return this.selectedControl.getPrice(excludeDiscount);
    },

    addSelectionChangedEventHandler: function(handler) {
        this.selectionChangedEventHandlers.push(handler);
    },

    registerControl: function(control) {
        if (control) {
            this.controls.push(control);
            if (control.getIsIncluded()) {
                this.selectedControl = control;
            }
            control.addSelectedEventHandler(this.onControlSelected.bind(this));
        }

        //this.refreshView();
    },

    onControlSelected: function(control) {
        control.setIsIncluded(true);

        for (var ctr = 0; ctr < this.controls.length; ctr++) {
            var currentControl = this.controls[ctr];
            if (currentControl != control) {
                currentControl.setIsIncluded(false);
            }
        }

        this.selectedControl = control;

        this.refreshView();
        this.onSelectionChanged();
    },

    refreshView: function() {
        if (this.selectedControl) {
            for (var ctr = 0; ctr < this.controls.length; ctr++) {
                var currentControl = this.controls[ctr];
                currentControl.compareWith(this.selectedControl);
            }
        }
    },

    onSelectionChanged: function() {
        for (var ctr = 0; ctr < this.selectionChangedEventHandlers.length; ctr++) {
            var handler = this.selectionChangedEventHandlers[ctr];
            handler(this);
        }
    },

    validate: function() {
        if (this.getIsRequired() == true) {
            return this.getSelectedItems().length > 0;
        }

        return true;
    }

}

aspdnsf.Controls.KitItemCheckBoxControl = Class.create();
aspdnsf.Controls.KitItemCheckBoxControl.prototype = {

    initialize: function(id, clientId, price, name) {
        this.id = id;
        this.name = name;

        this.ctrl = $(clientId);
        this.ctrl.onclick = this.onControlCheckChanged.bind(this);

        this.price = price;

        this.isIncluded = false;
        this.deltaPrice = 0.0;
        this.selectedEventHandlers = new Array();
        this.unSelectedEventHandlers = new Array();
        this.deltaPriceChangedEventHandlers = new Array();

        this.tax = 1;
        this.discount = 0;

        this.vatEnabled = false;
        this.vatInclusive = false;
    },

    getId: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    },

    getPrice: function(excludeDiscount) {
        if (arguments.length == 0 || !excludeDiscount) {
            return this.price * this.tax * (1 - (this.discount / 100));
        }

        return this.price * this.tax;
    },

    getDeltaPrice: function() {
        return this.deltaPrice;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    setDeltaPrice: function(delta) {
        this.deltaPrice = delta;

        this.onDeltaPriceChanged();
    },

    getIsIncluded: function() {
        return this.isIncluded;
    },

    setIsIncluded: function(included) {
        this.isIncluded = included;
    },

    addSelectedEventHandler: function(handler) {
        this.selectedEventHandlers.push(handler);
    },

    addUnSelectedEventHandler: function(handler) {
        this.unSelectedEventHandlers.push(handler);
    },

    onControlCheckChanged: function() {
        if (this.ctrl.checked) {
            this.onSelected();
        }
        else {
            this.onUnSelected();
        }
    },

    onSelected: function() {
        for (var ctr = 0; ctr < this.selectedEventHandlers.length; ctr++) {
            var handler = this.selectedEventHandlers[ctr];
            handler(this);
        }
    },

    onUnSelected: function() {
        for (var ctr = 0; ctr < this.unSelectedEventHandlers.length; ctr++) {
            var handler = this.unSelectedEventHandlers[ctr];
            handler(this);
        }
    },

    addDeltaPriceChangedEventHandler: function(handler) {
        this.deltaPriceChangedEventHandlers.push(handler);
    },

    onDeltaPriceChanged: function() {
        for (var ctr = 0; ctr < this.deltaPriceChangedEventHandlers.length; ctr++) {
            var handler = this.deltaPriceChangedEventHandlers[ctr];
            handler(this);
        }
    }

}

aspdnsf.Controls.KitCheckBoxGroupControl = Class.create();
aspdnsf.Controls.KitCheckBoxGroupControl.prototype = {

    initialize: function(id) {
        this.id = id;
        this.controls = new Array();
        this.selectionChangedEventHandlers = new Array();
        this.selectedControls = new Array();

        this.required = false;
    },

    getId: function() {
        return this.id;
    },

    getIsRequired: function() {
        return this.required;
    },

    setIsRequired: function(required) {
        this.required = required;
    },

    getSelectedItems: function() {
        return this.selectedControls;
    },

    getDeltaPrice: function(excludeDiscount) {
        var delta = 0;
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            delta += currentControl.getPrice(excludeDiscount);
        }
        return delta;
    },

    addSelectionChangedEventHandler: function(handler) {
        this.selectionChangedEventHandlers.push(handler);
    },

    registerControl: function(control) {
        if (control) {
            this.controls.push(control);
            if (control.getIsIncluded()) {
                this.selectedControls.push(control);
            }
            control.addSelectedEventHandler(this.onControlSelected.bind(this));
            control.addUnSelectedEventHandler(this.onControlUnSelected.bind(this));

            //this.refreshView();
        }
    },

    onControlSelected: function(control) {
        control.setIsIncluded(true);

        this.selectedControls.push(control);

        this.refreshView();
        this.onSelectionChanged();
    },

    onControlUnSelected: function(control) {
        control.setIsIncluded(false);

        var newItems = new Array();
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            if (currentControl != control) {
                newItems.push(currentControl);
            }
        }

        this.selectedControls = newItems;

        this.refreshView();
        this.onSelectionChanged();
    },

    refreshView: function() {
        if (this.selectedControls) {
            for (var ctr = 0; ctr < this.controls.length; ctr++) {
                var currentControl = this.controls[ctr];
                currentControl.setDeltaPrice(currentControl.getPrice());
            }
        }
    },

    onSelectionChanged: function() {
        for (var ctr = 0; ctr < this.selectionChangedEventHandlers.length; ctr++) {
            var handler = this.selectionChangedEventHandlers[ctr];
            handler(this);
        }
    },

    validate: function() {
        if (this.getIsRequired() == true) {
            return this.getSelectedItems().length > 0;
        }

        return true;
    }

}

aspdnsf.Controls.KitDropDownOptionControl = Class.create();
aspdnsf.Controls.KitDropDownOptionControl.prototype = {

    initialize: function(id, price, name) {
        this.id = id;
        this.price = price;
        this.name = name;
        this.deltaPrice = 0;
        this.isIncluded = false;
        this.shouldDisplayPriceDelta = true;

        this.tax = 1;
        this.discount = 0;

        this.vatEnabled = false;
        this.vatInclusive = false;
    },

    getId: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    },

    getPrice: function(excludeDiscount) {
        if (arguments.length == 0 || !excludeDiscount) {
            return this.price * this.tax * (1 - (this.discount / 100));
        }

        return this.price * this.tax;
    },

    getDeltaPrice: function() {
        return this.deltaPrice;
    },

    getIsIncluded: function() {
        return this.isIncluded;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    setIsIncluded: function(included) {
        this.isIncluded = included;
    },

    setShouldDisplayPriceDelta: function(shouldDisplay) {
        this.shouldDisplayPriceDelta = shouldDisplay;
    },

    compareWith: function(other) {
        var delta = 0;
        if (other == this) {
            delta = 0;
        }
        else {
            delta = this.getPrice() - other.getPrice();
        }

        this.deltaPrice = delta;
    },

    getDisplay: function() {
        if (this.shouldDisplayPriceDelta) {
                if (this.getPrice() == 0) {
                    return this.name;

                }
                else {
                var display = '';

                    //if (this.deltaPrice >= 0) {
                        display = this.name + ', ' + aspdnsf.StringResource.getString('showproduct.aspx.14') + ' ' + aspdnsf.CurrencyFormatter.format(this.getPrice());
                    //}
                    //else {
                    //    display = this.name + ', ' + aspdnsf.StringResource.getString('showproduct.aspx.15') + ' ' + aspdnsf.CurrencyFormatter.format(Math.abs(this.deltaPrice));
                    //}

                    if (this.getIsVatEnabled()) {
                        if (this.getIsVatInclusive()) {
                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
                    }
                    else {
                        display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
                    }
                }

                    return display;
            }
            //                if (this.isIncluded) {
            //                    return this.name;

            //                }
            //                else {
            //                    var display = '';

            //                    if (this.deltaPrice >= 0) {
            //                        display = this.name + ', ' + aspdnsf.StringResource.getString('showproduct.aspx.14') + ' ' + aspdnsf.CurrencyFormatter.format(this.deltaPrice);
            //                    }
            //                    else {
            //                        display = this.name + ', ' + aspdnsf.StringResource.getString('showproduct.aspx.15') + ' ' + aspdnsf.CurrencyFormatter.format(Math.abs(this.deltaPrice));
            //                    }

            //                    if (this.getIsVatEnabled()) {
            //                        if (this.getIsVatInclusive()) {
            //                            display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
            //                        }
            //                        else {
            //                            display += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
            //                        }
            //                    }

            //                    return display;
            //                }
        }
        else {
            return this.name;
        }
    }

}

aspdnsf.Controls.KitDropDownGroupControl = Class.create();
aspdnsf.Controls.KitDropDownGroupControl.prototype = {

    initialize: function(id, clientId) {
        this.id = id;
        this.ctrl = $(clientId);
        this.ctrl.onchange = this.onOptionChanged.bind(this);

        this.controls = new Array();
        this.selectionChangedEventHandlers = new Array();
        this.selectedControl = null;

        this.required = false;
    },

    getId: function() {
        return this.id;
    },

    getIsRequired: function() {
        return this.required;
    },

    setIsRequired: function(required) {
        this.required = required;
    },

    getSelectedItems: function() {
        return [this.selectedControl];
    },

    getDeltaPrice: function(excludeDiscount) {
        return this.selectedControl.getPrice(excludeDiscount);
    },

    addSelectionChangedEventHandler: function(handler) {
        this.selectionChangedEventHandlers.push(handler);
    },

    registerControl: function(control) {
        if (control) {
            this.controls.push(control);
            if (control.getIsIncluded()) {
                this.selectedControl = control;
            }

            //this.refreshView();
        }
    },

    onOptionChanged: function() {
        var index = this.ctrl.selectedIndex;
        if (index < this.controls.length) {
            this.selectedControl = this.controls[index];
            this.selectedControl.setIsIncluded(true);
        }

        for (var ctr = 0; ctr < this.controls.length; ctr++) {
            var currentControl = this.controls[ctr];
            if (currentControl != this.selectedControl) {
                currentControl.setIsIncluded(false);
            }
        }

        //this.refreshView();
        this.onSelectionChanged();
    },

    refreshView: function() {
        if (this.controls.length == 0) return;

        if (this.selectedControl) {
            this.ctrl.options.length = 0;

            var index = 0;

            for (var ctr = 0; ctr < this.controls.length; ctr++) {
                var currentControl = this.controls[ctr];
                currentControl.compareWith(this.selectedControl);
                if (currentControl == this.selectedControl) {
                    index = ctr;
                }
                this.ctrl.options[ctr] = new Option(currentControl.getDisplay(), currentControl.getId());
            }

            this.ctrl.selectedIndex = index;
        }
        else {
            this.selectedControl = this.controls[0];
            this.refreshView();
        }
    },

    onSelectionChanged: function() {
        for (var ctr = 0; ctr < this.selectionChangedEventHandlers.length; ctr++) {
            var handler = this.selectionChangedEventHandlers[ctr];
            handler(this);
        }
    },

    validate: function() {
        if (this.getIsRequired() == true) {
            return this.getSelectedItems().length > 0;
        }

        return true;
    }

}


aspdnsf.Controls.KitController = {

    initialize: function() {
        this.controls = new Hash();
        this.observers = new Array();
    },

    registerControl: function(control) {
        if (control) {
            this.controls[control.getId()] = control;
            this.notifyObservers(control);

            return control;
        }
    },

    getControl: function(id) {
        return this.controls[id];
    },

    addObserver: function(observer) {
        if (observer) {
            this.observers[this.observers.length] = observer;
        }
    },

    notifyObservers: function(control) {
        for (var ctr = 0; ctr < this.observers.length; ctr++) {
            this.observers[ctr].notify(control);
        }
    }
}

aspdnsf.Controls.KitController.initialize();

aspdnsf.Controls.KitControl = Class.create();
aspdnsf.Controls.KitControl.prototype = {

    initialize: function(id, basePrice, regBasePrice) {
        this.id = id;
        this.basePrice = basePrice;
        this.regBasePrice = regBasePrice;
        this.isOnSale = (this.basePrice < this.regBasePrice);

        this.groups = new Array();
        this.compositionChangedEventHandlers = new Array();

        this.tax = 1;
        this.discount = 0;

        this.groupCompositionCompleteEventHandlers = new Array();

        this.form = null;
    },

    getId: function() {
        return this.id;
    },

    getGroups: function() {
        return this.groups;
    },

    registerGroup: function(group) {
        if (group) {
            this.groups.push(group);
            group.addSelectionChangedEventHandler(this.groupSelectionChangedEventHandler.bind(this));
        }
    },

    getBasePrice: function() {
        return this.basePrice * this.tax;
    },

    getIsOnSale: function() {
        return this.isOnSale;
    },

    getRegularBasePrice: function() {
        return this.regBasePrice;
    },

    getCustomizedPrice: function(excludeDiscount) {
        var delta = 0;
        for (var ctr = 0; ctr < this.groups.length; ctr++) {
            var group = this.groups[ctr];
            delta += group.getDeltaPrice(excludeDiscount);
        }

        var basePrice = this.getBasePrice();
        if (arguments.length == 0 || !excludeDiscount) {
            basePrice *= (1 - (this.discount / 100));
        }

        return basePrice + delta;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    addCompositionChangedEventHandler: function(handler) {
        this.compositionChangedEventHandlers.push(handler);
    },

    setGroupCompositionComplete: function() {
        this.onGroupCompositionComplete();
    },

    addGroupCompositionCompleteEventHandler: function(handler) {
        this.groupCompositionCompleteEventHandlers.push(handler);
    },

    onGroupCompositionComplete: function() {
        for (var ctr = 0; ctr < this.groupCompositionCompleteEventHandlers.length; ctr++) {
            var handler = this.groupCompositionCompleteEventHandlers[ctr];
            handler(this);
        }
    },

    groupSelectionChangedEventHandler: function(group) {
        this.persistComposition();
        this.onCompositionChanged();
    },

    getComposition: function() {
        var compositions = new Array();
        for (var gctr = 0; gctr < this.groups.length; gctr++) {
            var group = this.groups[gctr];
            var items = group.getSelectedItems();
            for (var ictr = 0; ictr < items.length; ictr++) {
                var item = items[ictr];
                compositions.push(group.getId() + '+' + item.getId());
            }
        }

        return compositions;
    },

    persistComposition: function() {
        var composition = this.getComposition();

        var items = document.getElementsByClassName('KitItems');
        items.each(
            function(elem, idx) {
                elem.value = composition;
            }
        );
    },

    onCompositionChanged: function() {
        for (var ctr = 0; ctr < this.compositionChangedEventHandlers.length; ctr++) {
            var handler = this.compositionChangedEventHandlers[ctr];
            handler(this);
        }
    },


    getPersistCompositionHandler: function() {
        var persistCompositionHandler = this.persistComposition.bind(this);
        return persistCompositionHandler;
    },

    chainHandler: function(prevHandler) {
        var persistCompositionHandler = this.persistComposition.bind(this);

        return function() {

            persistCompositionHandler();

            if (prevHandler) {
                return prevHandler();
            }

            return true;
        };
    },

    setForm: function(id) {
        var frm = $(id);
        if (frm) {
            this.form = frm;
            //Event.observe(frm, 'submit', this.onFormSubmit.bind(this));
            var prevHandler = frm.onsubmit;
            var onSubmitDelegate = this.onFormSubmit.bind(this);
            var handler = function() { return onSubmitDelegate() && (prevHandler && prevHandler()) };

            frm.onsubmit = handler;
        }
    },

    onFormSubmit: function() {
        if (!this.validate()) {
            return false;
        }

        this.persistComposition();
        this.attachOtherTypes();

        return true;
    },

    validate: function() {
        this.hideError();

        var compositions = new Array();
        for (var gctr = 0; gctr < this.groups.length; gctr++) {
            var group = this.groups[gctr];

            if (!group.validate()) {
                this.showError();
                return false;
            }
        }

        return true;
    },

    showError: function() {
        var pnlError = $('KitError');
        var lblError = $('lblKitError');
        if (pnlError && lblError) {
            pnlError.show();
            lblError.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.16');
        }
    },

    hideError: function() {
        var pnlError = $('KitError');
        var lblError = $('lblKitError');
        if (pnlError && lblError) {
            pnlError.hide();
            lblError.innerHTML = '';
        }
    },

    attachOtherTypes: function() {
        var frm = this.form;
        var container = $(frm.id + '_KitFormContainer');

        if (container) {
            try {
                var textOptions = document.getElementsByClassName('KitItemTextOption');
                textOptions.each(
                    function(elem, idx) {
                        container.appendChild(elem);
                    }
                );

                var fileUploads = document.getElementsByClassName('KitItemFileUpload');
                fileUploads.each(
                    function(elem, idx) {
                        container.appendChild(elem);
                    }
                );
            }
            catch (e) {
                alert(e);
            }
        }

    }
}

aspdnsf.Controls.Highlight = Class.create();
aspdnsf.Controls.Highlight.prototype = {

    initialize: function(id) {
        this.elem = $(id);
        this.ctr = 0;

        this.doHighLight();
    },

    colors: ["#A9FFFE", "#B1FFFE", "#BBFFFE", "#C3FFFE", "#CDFFFE", "#D7FFFE", "#E3FFFE", "#EFFFFE", "#FFFFE1"],

    doHighLight: function(pe) {
        if (this.elem) {
            if (this.ctr < this.colors.length) {
                this.elem.style.backgroundColor = this.colors[this.ctr];
                this.ctr += 1;

                new PeriodicalExecuter(this.doHighLight.bind(this), .1);
            }
            else {
                pe.stop();
            }

        }
    }

}

aspdnsf.Controls.KitPriceControl = Class.create();
aspdnsf.Controls.KitPriceControl.prototype = {

    initialize: function(id, clientId) {
        this.id = id;
        this.ctrl = $(clientId);
        //this.basePrice = basePrice;
        this.kitControl = null;
        this.lblRegularBasePrice = $(clientId + '_RegularBasePrice');
        this.lblBasePrice = $(clientId + '_BasePrice');
        this.lblCustomizedPrice = $(clientId + '_CustomizedPrice');
        this.lblLevelPrice = $(clientId + '_LevelPrice');
        this.customerHasLevel = false;
        this.customerLevel = '';
        this.vatEnabled = false;
        this.vatInclusive = false;

        this.displayEventHandlers = new Array();
    },

    setCustomerLevel: function(level) {
        this.customerHasLevel = true;
        this.customerLevel = level;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    setKitControl: function(kitControl) {
        if (kitControl) {
            this.kitControl = kitControl;
            this.kitControl.addGroupCompositionCompleteEventHandler(this.kitGroupCompositionCompleteEventHandler.bind(this));
            this.kitControl.addCompositionChangedEventHandler(this.kitCompositionChangedEventHandler.bind(this));
            this.buildDisplay();
        }
        else {
            aspdnsf.Controls.KitController.addObserver(this);
        }
    },

    notify: function(kitControl) {
        this.setKitControl(kitControl);
    },

    kitGroupCompositionCompleteEventHandler: function() {
        this.buildDisplay();
    },

    kitCompositionChangedEventHandler: function() {
        this.buildDisplay();
    },

    addDisplayEventHandler: function(handler) {
        this.displayEventHandlers.push(handler);
    },

    buildDisplay: function() {
        if (this.kitControl.getIsOnSale()) {
            this.lblRegularBasePrice.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.17') + aspdnsf.CurrencyFormatter.format(this.kitControl.getRegularBasePrice());
            //this.lblRegularBasePrice.style.textDecoration = "line-through";
            this.lblBasePrice.className = 'KitBasePriceOnSale';
            this.lblCustomizedPrice.className = 'KitCustomizedPriceOnSale';
            this.lblLevelPrice.className = 'KitLevelPriceOnSale';
        }
        this.lblBasePrice.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.13') + ' ' + aspdnsf.CurrencyFormatter.format(this.kitControl.getBasePrice());
        if (this.getIsVatEnabled()) {
            if (this.getIsVatInclusive()) {
                this.lblBasePrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
            }
            else {
                this.lblBasePrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
            }
        }

        this.lblCustomizedPrice.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.14') + ' ' + aspdnsf.CurrencyFormatter.format(this.kitControl.getCustomizedPrice(true));
        if (this.getIsVatEnabled()) {
            if (this.getIsVatInclusive()) {
                this.lblCustomizedPrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
            }
            else {
                this.lblCustomizedPrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
            }
        }

        if (this.customerHasLevel) {
            this.lblLevelPrice.style.display = "";
            this.lblLevelPrice.innerHTML = this.customerLevel + ' ' + aspdnsf.StringResource.getString('product.kit2product.xml.config.14') + ' ' + aspdnsf.CurrencyFormatter.format(this.kitControl.getCustomizedPrice(false));
            if (this.getIsVatEnabled()) {
                if (this.getIsVatInclusive()) {
                    this.lblLevelPrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.6');
                }
                else {
                    this.lblLevelPrice.innerHTML += ' ' + aspdnsf.StringResource.getString('setvatsetting.aspx.7');
                }
            }

            this.lblBasePrice.style.textDecoration = "line-through";
            this.lblCustomizedPrice.style.textDecoration = "line-through";
        }

        this.onDisplay();
    },

    onDisplay: function() {
        for (var ctr = 0; ctr < this.displayEventHandlers.length; ctr++) {
            var handler = this.displayEventHandlers[ctr];
            handler(this);
        }
    }

}


aspdnsf.Controls.KitDetailsControl = Class.create();
aspdnsf.Controls.KitDetailsControl.prototype = {

    initialize: function(id) {
        this.id = id;

        this.lnkHeader = $('lnkKitDetailHeader_' + id);
        this.lnkHeader.onclick = this.onHeaderLinkClicked.bind(this);

        this.pnlDetails = $('pnlKitDetails_' + id);

        this.kitControl = null;
    },

    setKitControl: function(control) {
        this.kitControl = control;

        this.kitControl.addCompositionChangedEventHandler(this.kitCompositionChangedEventHandler.bind(this));
        this.buildDisplay();
    },

    onHeaderLinkClicked: function() {
        if (this.pnlDetails.style.display == "") {
            this.lnkHeader.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.12');
            this.pnlDetails.style.display = "none";
        }
        else {
            this.lnkHeader.innerHTML = aspdnsf.StringResource.getString('product.kit2product.xml.config.11');
            this.pnlDetails.style.display = "";
        }
    },

    kitCompositionChangedEventHandler: function() {
        this.buildDisplay();
    },

    buildDisplay: function() {
        this.pnlDetails.innerHTML = '';

        var ul = document.createElement('ul');
        this.pnlDetails.appendChild(ul);

        var kitGroups = this.kitControl.getGroups();
        for (var gctr = 0; gctr < kitGroups.length; gctr++) {
            var currentGroup = kitGroups[gctr];
            var items = currentGroup.getSelectedItems();
            for (var ictr = 0; ictr < items.length; ictr++) {
                var item = items[ictr];
                var li = document.createElement('li');
                li.innerHTML = item.getName();

                ul.appendChild(li);
            }
        }
    }
}


aspdnsf.Controls.KitTextBoxControl = Class.create();
aspdnsf.Controls.KitTextBoxControl.prototype = {

    initialize: function(id, clientId, price, name) {
        this.id = id;
        this.name = name;

        this.ctrl = $(clientId);
        this.ctrl.onkeyup = this.onControlTextChanged.bind(this);

        this.price = price;

        this.isIncluded = false;
        this.deltaPrice = 0.0;
        this.selectedEventHandlers = new Array();
        this.unSelectedEventHandlers = new Array();
        this.deltaPriceChangedEventHandlers = new Array();

        this.tax = 1;
        this.discount = 0;

        this.vatEnabled = false;
        this.vatInclusive = false;
    },

    getId: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    },

    getPrice: function(excludeDiscount) {
        if (arguments.length == 0 || !excludeDiscount) {
            return this.price * this.tax * (1 - (this.discount / 100));
        }

        return this.price * this.tax;
    },

    getDeltaPrice: function() {
        return this.deltaPrice;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    setDeltaPrice: function(delta) {
        this.deltaPrice = delta;

        this.onDeltaPriceChanged();
    },

    getIsIncluded: function() {
        return this.isIncluded;
    },

    setIsIncluded: function(included) {
        this.isIncluded = included;
    },

    addSelectedEventHandler: function(handler) {
        this.selectedEventHandlers.push(handler);
    },

    addUnSelectedEventHandler: function(handler) {
        this.unSelectedEventHandlers.push(handler);
    },

    valueIsValid: function() {
        return this.ctrl.value != '';
    },

    onControlTextChanged: function() {
        if (this.ctrl.value != '' && !this.getIsIncluded()) {
            this.onSelected();
        }
        else if (this.ctrl.value == '' && this.getIsIncluded() == true) {
            this.onUnSelected();
        }
    },

    onSelected: function() {
        for (var ctr = 0; ctr < this.selectedEventHandlers.length; ctr++) {
            var handler = this.selectedEventHandlers[ctr];
            handler(this);
        }
    },

    onUnSelected: function() {
        for (var ctr = 0; ctr < this.unSelectedEventHandlers.length; ctr++) {
            var handler = this.unSelectedEventHandlers[ctr];
            handler(this);
        }
    },

    addDeltaPriceChangedEventHandler: function(handler) {
        this.deltaPriceChangedEventHandlers.push(handler);
    },

    onDeltaPriceChanged: function() {
        for (var ctr = 0; ctr < this.deltaPriceChangedEventHandlers.length; ctr++) {
            var handler = this.deltaPriceChangedEventHandlers[ctr];
            handler(this);
        }
    }

}

aspdnsf.Controls.KitTextBoxGroupControl = Class.create();
aspdnsf.Controls.KitTextBoxGroupControl.prototype = {

    initialize: function(id) {
        this.id = id;
        this.controls = new Array();
        this.selectionChangedEventHandlers = new Array();
        this.selectedControls = new Array();

        this.required = false;
    },

    getId: function() {
        return this.id;
    },

    getIsRequired: function() {
        return this.required;
    },

    setIsRequired: function(required) {
        this.required = required;
    },

    getSelectedItems: function() {
        return this.selectedControls;
    },

    getDeltaPrice: function(excludeDiscount) {
        var delta = 0;
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            delta += currentControl.getPrice(excludeDiscount);
        }
        return delta;
    },

    addSelectionChangedEventHandler: function(handler) {
        this.selectionChangedEventHandlers.push(handler);
    },

    registerControl: function(control) {
        if (control) {
            this.controls.push(control);
            if (control.getIsIncluded()) {
                this.selectedControls.push(control);
            }
            control.addSelectedEventHandler(this.onControlSelected.bind(this));
            control.addUnSelectedEventHandler(this.onControlUnSelected.bind(this));

            //this.refreshView();
        }
    },

    onControlSelected: function(control) {
        control.setIsIncluded(true);

        this.selectedControls.push(control);

        this.refreshView();
        this.onSelectionChanged();
    },

    onControlUnSelected: function(control) {
        control.setIsIncluded(false);

        var newItems = new Array();
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            if (currentControl != control) {
                newItems.push(currentControl);
            }
        }

        this.selectedControls = newItems;

        this.refreshView();
        this.onSelectionChanged();
    },

    refreshView: function() {
        if (this.selectedControls) {
            for (var ctr = 0; ctr < this.controls.length; ctr++) {
                var currentControl = this.controls[ctr];
                currentControl.setDeltaPrice(currentControl.getPrice());
            }
        }
    },

    onSelectionChanged: function() {
        for (var ctr = 0; ctr < this.selectionChangedEventHandlers.length; ctr++) {
            var handler = this.selectionChangedEventHandlers[ctr];
            handler(this);
        }
    },

    validate: function() {
        var items = this.getSelectedItems();
        if (this.getIsRequired() == true) {
            if (items.length == 0) {
                return false;
            }
        }

        if (items.length > 0) {
            for (var ctr = 0; ctr < items.length; ctr++) {
                if (items[ctr].valueIsValid() == false) {
                    return false;
                }
            }
        }

        return true;
    }

}


/******************************************************/
//          KitItemFileUploadControl 
/******************************************************/
aspdnsf.Controls.KitItemFileUploadControl = Class.create();
aspdnsf.Controls.KitItemFileUploadControl.prototype = {

    initialize: function(id, clientId, price, name) {
        this.id = id;
        this.name = name;

        this.ctrl = $(clientId);
        this.ctrl.onclick = this.onControlCheckChanged.bind(this);

        this.price = price;

        this.isIncluded = false;
        this.deltaPrice = 0.0;
        this.selectedEventHandlers = new Array();
        this.unSelectedEventHandlers = new Array();
        this.deltaPriceChangedEventHandlers = new Array();

        this.tax = 1;
        this.discount = 0;

        this.vatEnabled = false;
        this.vatInclusive = false;
    },

    getId: function() {
        return this.id;
    },

    getName: function() {
        return this.name;
    },

    getPrice: function(excludeDiscount) {
        if (arguments.length == 0 || !excludeDiscount) {
            return this.price * this.tax * (1 - (this.discount / 100));
        }

        return this.price * this.tax;
    },

    getDeltaPrice: function() {
        return this.deltaPrice;
    },

    getIsVatEnabled: function() {
        return this.vatEnabled;
    },

    setIsVatEnabled: function(vatEnabled) {
        this.vatEnabled = vatEnabled;
    },

    getIsVatInclusive: function() {
        return this.vatInclusive;
    },

    setIsVatInclusive: function(vatInclusive) {
        this.vatInclusive = vatInclusive;
    },

    setTax: function(tax) {
        this.tax = tax;
    },

    setDiscount: function(discount) {
        this.discount = discount;
    },

    setDeltaPrice: function(delta) {
        this.deltaPrice = delta;

        this.onDeltaPriceChanged();
    },

    getIsIncluded: function() {
        return this.isIncluded;
    },

    setIsIncluded: function(included) {
        this.isIncluded = included;
    },

    addSelectedEventHandler: function(handler) {
        this.selectedEventHandlers.push(handler);
    },

    addUnSelectedEventHandler: function(handler) {
        this.unSelectedEventHandlers.push(handler);
    },

    onControlCheckChanged: function() {
        if (this.ctrl.checked) {
            this.onSelected();
            this.showUploadControl();
        }
        else {
            if (!this.removeUpload()) {
                return false;
            }
            this.onUnSelected();
        }
    },

    valueIsValid: function() {
        var upload = $('KitItemFileUpload_' + this.id);
        if (upload) {
            return upload.value != '';
        }

        return true;
    },

    showUploadControl: function() {
        var row = $('ItemFileUploadRow_' + this.id);
        var contentArea = $('ItemFileUploadContentArea_' + this.id);

        if (row && contentArea) {
            var upload = document.createElement('input');
            upload.type = 'file';
            upload.id = 'KitItemFileUpload_' + this.id;
            upload.name = 'KitItemFileUpload_' + this.id;
            upload.className = 'KitItemFileUpload';

            contentArea.appendChild(upload);
            row.show();
        }
    },

    removeUpload: function() {
        var img = $('ItemFileUploadImage_' + this.id);
        if (img) {
            var alertMessage = aspdnsf.StringResource.getString('product.kit2product.xml.config.15');
            if (!confirm(alertMessage)) {
                return false;
            }
        }

        var contentArea = $('ItemFileUploadContentArea_' + this.id);
        contentArea.innerHTML = '';

        var row = $('ItemFileUploadRow_' + this.id);
        row.hide();

        return true;
    },

    onSelected: function() {
        for (var ctr = 0; ctr < this.selectedEventHandlers.length; ctr++) {
            var handler = this.selectedEventHandlers[ctr];
            handler(this);
        }
    },

    onUnSelected: function() {
        for (var ctr = 0; ctr < this.unSelectedEventHandlers.length; ctr++) {
            var handler = this.unSelectedEventHandlers[ctr];
            handler(this);
        }
    },

    addDeltaPriceChangedEventHandler: function(handler) {
        this.deltaPriceChangedEventHandlers.push(handler);
    },

    onDeltaPriceChanged: function() {
        for (var ctr = 0; ctr < this.deltaPriceChangedEventHandlers.length; ctr++) {
            var handler = this.deltaPriceChangedEventHandlers[ctr];
            handler(this);
        }
    }

}

/******************************************************/
//          KitItemFileUploadGroupControl 
/******************************************************/
aspdnsf.Controls.KitItemFileUploadGroupControl = Class.create();
aspdnsf.Controls.KitItemFileUploadGroupControl.prototype = {

    initialize: function(id) {
        this.id = id;
        this.controls = new Array();
        this.selectionChangedEventHandlers = new Array();
        this.selectedControls = new Array();

        this.required = false;
    },

    getId: function() {
        return this.id;
    },

    getIsRequired: function() {
        return this.required;
    },

    setIsRequired: function(required) {
        this.required = required;
    },

    getSelectedItems: function() {
        return this.selectedControls;
    },

    getDeltaPrice: function(excludeDiscount) {
        var delta = 0;
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            delta += currentControl.getPrice(excludeDiscount);
        }
        return delta;
    },

    addSelectionChangedEventHandler: function(handler) {
        this.selectionChangedEventHandlers.push(handler);
    },

    registerControl: function(control) {
        if (control) {
            this.controls.push(control);
            if (control.getIsIncluded()) {
                this.selectedControls.push(control);
            }
            control.addSelectedEventHandler(this.onControlSelected.bind(this));
            control.addUnSelectedEventHandler(this.onControlUnSelected.bind(this));

            //this.refreshView();
        }
    },

    onControlSelected: function(control) {
        control.setIsIncluded(true);

        this.selectedControls.push(control);

        this.refreshView();
        this.onSelectionChanged();
    },

    onControlUnSelected: function(control) {
        control.setIsIncluded(false);

        var newItems = new Array();
        for (var ctr = 0; ctr < this.selectedControls.length; ctr++) {
            var currentControl = this.selectedControls[ctr];
            if (currentControl != control) {
                newItems.push(currentControl);
            }
        }

        this.selectedControls = newItems;

        this.refreshView();
        this.onSelectionChanged();
    },

    refreshView: function() {
        if (this.selectedControls) {
            for (var ctr = 0; ctr < this.controls.length; ctr++) {
                var currentControl = this.controls[ctr];
                currentControl.setDeltaPrice(currentControl.getPrice());
            }
        }
    },

    onSelectionChanged: function() {
        for (var ctr = 0; ctr < this.selectionChangedEventHandlers.length; ctr++) {
            var handler = this.selectionChangedEventHandlers[ctr];
            handler(this);
        }
    },

    validate: function() {
        var items = this.getSelectedItems();
        if (this.getIsRequired() == true) {
            if (items.length == 0) {
                return false;
            }
        }

        if (items.length > 0) {
            for (var ctr = 0; ctr < items.length; ctr++) {
                if (items[ctr].valueIsValid() == false) {
                    return false;
                }
            }
        }

        return true;
    }

}