var configurator;
var dependencyRules = new Array();
var incompatibilityRules = new Array();
var sectionLimits = new Array();

function checkboxChange(e) {
    var target = getEventTarget(e);
    target.name.match(/(section\d*)(Group\d+)(Product\d+)/i);
    var id = RegExp.$1 + RegExp.$2 + RegExp.$3;
    var group = RegExp.$1 + RegExp.$2;
    var section = RegExp.$1;
    // update  price
    var selectedItemPriceNode = document.getElementById(id + 'Price');
    var selectedItemPrice = getPrice(selectedItemPriceNode);
    if (selectedItemPrice > 0)
        selectedItemPriceNode.innerHTML = ' [subtract $' + selectedItemPrice + ']';
    else if (selectedItemPrice < 0)
        selectedItemPriceNode.innerHTML = ' [add $' + -selectedItemPrice + ']';
    updatePriceTotal(selectedItemPrice);
    updatePriceSubtotal(section, selectedItemPrice);
    // update cost 
    var selectedItemCostNode = document.getElementById(id + 'Cost');
    if (selectedItemCostNode != null) {
        var selectedItemCost = getPrice(selectedItemCostNode);
        if (selectedItemCost > 0)
            selectedItemCostNode.innerHTML = ' [subtract $' + selectedItemCost + ']';
        else if (selectedItemCost < 0)
            selectedItemCostNode.innerHTML = ' [add $' + -selectedItemCost + ']';
        updateCostTotal(selectedItemCost);
        updateCostSubtotal(section, selectedItemCost);
    }
    // update summary
    var summary = document.getElementById(group + 'Summary');
    if (summary) {
        var descriptionNode = document.getElementById(id + 'Description');
        if (target.checked) {
            summary.innerHTML += descriptionNode.innerHTML + '<br />';
        }
        else {
            summary.innerHTML = summary.innerHTML.replace(descriptionNode.innerHTML, '').replace(/^\s*<br\s*\/?>/, "").replace(/<br\s*\/?>\s*<br\s*\/?>/, "<br \/>");
        }
    }
}

function radioChange(e) {
    var target = getEventTarget(e);
    target.name.match(/(section\d*)(Group\d+)/i);
    var id = RegExp.$1 + RegExp.$2;
    var section = RegExp.$1;
    //find the selected option
    var groupNode = document.getElementById(id);
    var options = groupNode.getElementsByTagName('input');
    var checkIndex = 0;
    while (options[checkIndex].checked != true)
        checkIndex++;
    // get the selected options price adjustment
    var selectedItemPriceNode = document.getElementById(id + 'Product' + options[checkIndex].value + 'Price');
    var selectedItemPrice = getPrice(selectedItemPriceNode);
    // get the selected options cost adjustment
    var selectedItemCostNode = document.getElementById(id + 'Product' + options[checkIndex].value + 'Cost');
    if (selectedItemCostNode != null)
        var selectedItemCost = getPrice(selectedItemCostNode);
    // update the total
    updatePriceTotal(selectedItemPrice);
    updatePriceSubtotal(section, selectedItemPrice);
    if (selectedItemCostNode != null) {
        updateCostTotal(selectedItemCost);
        updateCostSubtotal(section, selectedItemCost);
    }
    // update summary
    var summary = document.getElementById(id + 'Summary');
    var descriptionNode = document.getElementById(id + 'Product' + options[checkIndex].value + 'Description');
    if (descriptionNode && summary)
        summary.innerHTML = descriptionNode.innerHTML;
    //update option prices
    if (selectedItemPriceNode != null)
        selectedItemPriceNode.innerHTML = '';
    if (selectedItemCostNode != null)
        selectedItemCostNode.innerHTML = '';
    for (i = 0; i < options.length; i++) {
        if (i != checkIndex) {
            updatePrice(id + 'Product' + options[i].value + 'Price', selectedItemPrice);
            if (selectedItemCostNode != null) {
                updatePrice(id + 'Product' + options[i].value + 'Cost', selectedItemCost);
            }
        }
    }
}

function dropdownChange(e) {
    var target = getEventTarget(e);
    target.id.match(/(section\d*)(Group\d+)/i);
    var id = RegExp.$1 + RegExp.$2;
    var section = RegExp.$1;
    //find the selected option
    var dropdown = document.getElementById(id + 'Select');
    var selectedItemNode = dropdown.options[dropdown.selectedIndex];

    var parts = selectedItemNode.text.split('[');
    var selectedItemPrice = 0;
    var selectedItemText = parts[0];
    if (parts[1]) {
        selectedItemPrice = parseInt(parts[1].replace(/\D/g, ''));
        if (parts[1].search(/subtract/) >= 0)
            selectedItemPrice = -selectedItemPrice;
        if (selectedItemPrice == NaN)
            selectedItemPrice = 0;
    }
    var selectedItemCost = 0;
    if (parts[2]) {
        selectedItemCost = parseInt(parts[2].replace(/\D/g, ''));
        if (parts[2].search(/subtract/) >= 0)
            selectedItemCost = -selectedItemCost;
        if (selectedItemCost == NaN)
            selectedItemCost = 0;
    }

    // update the total
    updatePriceTotal(selectedItemPrice);
    updatePriceSubtotal(section, selectedItemPrice);
    if (selectedItemCostNode != null) {
        updateCostTotal(selectedItemCost);
        updateCostSubtotal(section, selectedItemCost);
    }
    // update summary
    var summary = document.getElementById(id + 'Summary');
    descriptionNode = document.getElementById(id + 'Product' + selectedItemText);
    if (descriptionNode && summary)
        summary.innerHTML = selectedItemText;
    //update option prices
    selectedItemNode.text = selectedItemText;

    for (i = 0; i < dropdown.options.length; i++) {
        if (i != dropdown.selectedIndex) {
            updateDropdownProductValues(dropdown.options[i], selectedItemPrice, selectedItemCost);
        }
    }
}

function updateDropdownProductValues(option, price, cost) {
    var parts = option.text.split('[');
    var itemPrice = 0;
    var text = parts[0];
    if (parts[1]) {
        itemPrice = parseInt(parts[1].replace(/\D/g, ''));
        var t = parts[1].replace(/\D/, '');
        if (parts[1].search(/subtract/) >= 0)
            itemPrice = -itemPrice;
        if (itemPrice == NaN)
            itemPrice = 0;
    }
    var itemCost = 0;
    if (parts[2]) {
        itemCost = parseInt(parts[2].replace(/\D/g, ''));
        if (parts[2].search(/subtract/) >= 0)
            itemCost = -itemCost;
        if (itemCost == NaN)
            itemCost = 0;
    }
    itemPrice -= price;
    itemCost -= cost;
    var priceText = '';
    if (itemPrice > 0)
        priceText = ' [add $' + itemPrice + '] ';
    else if (itemPrice < 0)
        priceText = ' [subtract $' + -itemPrice + '] ';
    var costText = '';
    if (itemCost > 0)
        costText = ' [add $' + itemCost + '] ';
    else if (itemCost < 0)
        costText = ' [subtract $' + -itemCost + '] ';
    option.text = text + priceText + costText;
}

function updatePriceTotal(priceAdjustment) {
    if (totalPriceNode != null) {
        var totalPriceNode = document.getElementById('totalPrice');
        var totalPrice = parseInt(totalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        totalPriceNode.innerHTML = '$' + (totalPrice + priceAdjustment);
    }
}

function updateCostTotal(priceAdjustment) {
    var totalPriceNode = document.getElementById('totalCost');
    var totalPrice = parseInt(totalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
    totalPriceNode.innerHTML = ' ($' + (totalPrice + priceAdjustment) + ')';
}

function updatePriceSubtotal(section, priceAdjustment) {
    var subtotalPriceNode = document.getElementById(section + 'PriceSubtotal');
    if (subtotalPriceNode) {
        var priceNode = document.getElementById(section + 'Price');
        var totalPrice = parseInt(subtotalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        subtotalPriceNode.innerHTML = '$' + (totalPrice + priceAdjustment);
        if (priceNode)
            priceNode.innerHTML = ' [subtract $' + (totalPrice + priceAdjustment) + ']';
    }
    var sectionPriceNode = document.getElementById(section + 'Price');
    if (sectionPriceNode) {
        var priceNode = document.getElementById(section + 'Price');
        var totalPrice = parseInt(sectionPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        sectionPriceNode.innerHTML = '$' + (totalPrice + priceAdjustment);
        if (priceNode)
            priceNode.innerHTML = ' [subtract $' + (totalPrice + priceAdjustment) + ']';
    }
}

function updateCostSubtotal(section, priceAdjustment) {
    var subtotalPriceNode = document.getElementById(section + 'CostSubtotal');
    if (subtotalPriceNode) {
        var priceNode = document.getElementById(section + 'Cost');
        var totalPrice = parseInt(subtotalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        subtotalPriceNode.innerHTML = ' ($' + (totalPrice + priceAdjustment) + ')';
        if (priceNode)
            priceNode.innerHTML = ' [subtract $' + (totalPrice + priceAdjustment) + ']';
    }
}

function updatePrice(nodeID, priceAdjustment) {
    //find this options current price adjustment
    var itemPriceNode = document.getElementById(nodeID);
    if (itemPriceNode) {
        var itemPrice = getPrice(itemPriceNode);
        itemPrice -= priceAdjustment;
        if (itemPrice > 0) {
            itemPriceNode.innerHTML = ' [add $' + itemPrice + ']';
        }
        else {
            itemPriceNode.innerHTML = ' [subtract $' + (itemPrice * -1) + ']';
        }
    }
}

function getPrice(itemPriceNode) {
    if (itemPriceNode == null)
        return 0;
    else {
        var itemPrice = parseInt(itemPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        if (isNaN(itemPrice))
            itemPrice = 0;
        if (itemPriceNode.innerHTML.match("subtract") && itemPrice > 0)
            itemPrice = -itemPrice;
        return itemPrice;
    }
}

function editSection(e) {
    var target = getEventTarget(e);
    var sectionID = target.id.replace(/[^\d]/gi, '');
    //close any open editors
    closeSections();
    //open the selected editor
    var sectionSummary = document.getElementById('section' + sectionID + 'Summary');
    sectionSummary.style.display = 'none';
    var sectionEditor = document.getElementById('section' + sectionID + 'Editor');
    sectionEditor.style.display = '';
    var sectionNotSelected = document.getElementById('section' + sectionID + 'NotSelected');
    if (sectionNotSelected)
        sectionNotSelected.style.display = 'none';
    var sectionOpen = document.getElementById('section' + sectionID + 'open');
    sectionOpen.style.display = 'none';
    var sectionClose = document.getElementById('section' + sectionID + 'close');
    sectionClose.style.display = '';
    // count sections
    var sectionTemplate = document.getElementById('section' + sectionID);
    var title = sectionTemplate.getElementsByTagName('legend');
    var sections = 0;
    var sectionTitles = configurator.getElementsByTagName('legend');
    for (var i = 0; i < sectionTitles.length; i++) {
        if (title[0].innerHTML == sectionTitles[i].innerHTML)
            sections++;
    }
    var sectionOptional = document.getElementById('section' + sectionID + 'Optional');
    if (sections > 1 || sectionOptional.value == 'true') {
        var sectionRemove = document.getElementById('section' + sectionID + 'remove');
        sectionRemove.style.display = '';
    }
}

function closeSections() {
    var fieldsets = document.getElementsByTagName('fieldset');
    for (var i = 0; i < fieldsets.length; i++) {
        if (fieldsets[i].id.search(/^section[\d]+$/) >= 0) {
            var sectionEditor = document.getElementById(fieldsets[i].id + 'Editor');
            if (sectionEditor && sectionEditor.style.display == '') {
                var sectionEnabled = document.getElementById(fieldsets[i].id + 'enabled');

                sectionEditor.style.display = 'none';

                if (sectionEnabled && sectionEnabled.checked == false) {
                    var sectionNotSelected = document.getElementById(fieldsets[i].id + 'NotSelected');
                    sectionNotSelected.style.display = '';
                }
                else {
                    var sectionSummary = document.getElementById(fieldsets[i].id + 'Summary');
                    sectionSummary.style.display = '';
                }

                var sectionOpen = document.getElementById(fieldsets[i].id + 'open');
                sectionOpen.style.display = '';
                var sectionClose = document.getElementById(fieldsets[i].id + 'close');
                sectionClose.style.display = 'none';
                var sectionRemove = document.getElementById(fieldsets[i].id + 'remove');
                sectionRemove.style.display = 'none';
            }
        }
    }
}

function addSection(e) {
    var target = getEventTarget(e);
    var sectionID = target.id.replace(/[^\d]/gi, '');
    // count sections
    var sectionTemplate = document.getElementById('section' + sectionID);
    var title = sectionTemplate.getElementsByTagName('legend');
    var sections = 0;
    var sectionTitles = configurator.getElementsByTagName('legend');
    for (var i = 0; i < sectionTitles.length; i++) {
        if (title[0].innerHTML == sectionTitles[i].innerHTML)
            sections++;
    }
    if (sections < sectionLimits[sectionID]) {
        closeSections();
        var defaultSection = document.getElementById('section' + sectionID)
        if (defaultSection.style.display == 'none')
            defaultSection.style.display = '';
        else {
            //find an unused section id
            var fieldsets = document.getElementsByTagName('fieldset');
            var ids = ',';
            for (var i = 0; i < fieldsets.length; i++)
                ids += fieldsets[i].id.replace(/[^\d]/gi, '') + ',';
            var newSectionID = 1;
            while (ids.search(',' + newSectionID + ',') >= 0)
                newSectionID++;
            var clone = document.getElementById('section' + sectionID).cloneNode(true);
            clone.id = 'section' + newSectionID;
            // fix ids and names and add event listeners
            var clonedDivs = clone.getElementsByTagName('div');
            for (var i = 0; i < clonedDivs.length; i++)
                clonedDivs[i].id = clonedDivs[i].id.replace('section' + sectionID, 'section' + newSectionID);
            var clonedLinks = clone.getElementsByTagName('a');
            for (var i = 0; i < clonedLinks.length; i++) {
                clonedLinks[i].id = clonedLinks[i].id.replace('section' + sectionID, 'section' + newSectionID);
                if (clonedLinks[i].id.search(/section\d+open/) >= 0)
                    addEvent(clonedLinks[i], 'click', editSection);
                else if (clonedLinks[i].id.search(/section\d+close/) >= 0)
                    addEvent(clonedLinks[i], 'click', closeSections);
                else if (clonedLinks[i].id.search(/section\d+remove/) >= 0)
                    addEvent(clonedLinks[i], 'click', removeSection);
            }
            var clonedInputs = clone.getElementsByTagName('input');
            for (var i = 0; i < clonedInputs.length; i++) {
                var input = clonedInputs[i];
                clonedInputs[i].id = clonedInputs[i].id.replace('section' + sectionID, 'section' + newSectionID);
                clonedInputs[i].name = clonedInputs[i].name.replace('section' + sectionID, 'section' + newSectionID);
                switch (clonedInputs[i].type) {
                    case 'radio':
                        addEvent(clonedInputs[i], 'change', radioChange);
                        break;
                    case 'checkbox':
                        addEvent(clonedInputs[i], 'change', checkboxChange);
                        break;
                    case 'button':
                        if (clonedInputs[i].id.search(/section\d+open/) >= 0)
                            addEvent(clonedInputs[i], 'click', editSection);
                        else if (clonedInputs[i].id.search(/section\d+close/) >= 0)
                            addEvent(clonedInputs[i], 'click', closeSections);
                        else if (clonedInputs[i].id.search(/section\d+remove/) >= 0)
                            addEvent(clonedInputs[i], 'click', removeSection);
                        break;
                }
            }
            var clonedSpans = clone.getElementsByTagName('span');
            for (var i = 0; i < clonedSpans.length; i++)
                clonedSpans[i].id = clonedSpans[i].id.replace('section' + sectionID, 'section' + newSectionID);
            var clonedSelects = clone.getElementsByTagName('select');
            for (var i = 0; i < clonedSelects.length; i++) {
                clonedSelects[i].id = clonedSelects[i].id.replace('section' + sectionID, 'section' + newSectionID);
                clonedSelects[i].name = clonedSelects[i].name.replace('section' + sectionID, 'section' + newSectionID);
                addEvent(clonedSelects[i], 'change', dropdownChange);
            }
            // insert the cloned node in the document
            var addLink = document.getElementById('section' + sectionID + 'add');
            addLink.parentNode.insertBefore(clone, addLink);
        }
        // update the totals
        var subtotalPriceNode = document.getElementById('section' + sectionID + 'Price');
        if (subtotalPriceNode != null) {
            var sectionPrice = parseInt(subtotalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
            updatePriceTotal(sectionPrice);
        }
        var subtotalCostNode = document.getElementById('section' + sectionID + 'Cost' + sectionID);
        if (subtotalCostNode != null) {
            var sectionCost = parseInt(subtotalCostNode.innerHTML.replace(/[^\d]/gi, ''));
            updateCostTotal(sectionCost);
        }
    }
    else {
        alert('You can not add any additional ' + title[0].innerHTML + ' sections.');
    }
}

function removeSection(e) {
    if (confirm('Are you sure that you want to remove this section?')) {
        var target = getEventTarget(e);
        var sectionID = target.id.replace(/[^\d]/gi, '');
        // update the totals
        var subtotalPriceNode = document.getElementById('section' + sectionID + 'Price');
        var sectionPrice = parseInt(subtotalPriceNode.innerHTML.replace(/[^\d]/gi, ''));
        updatePriceTotal(-sectionPrice);
        var subtotalCostNode = document.getElementById('section' + sectionID + 'Cost' + sectionID);
        if (subtotalCostNode != null) {
            var sectionCost = parseInt(subtotalCostNode.innerHTML.replace(/[^\d]/gi, ''));
            updateCostTotal(-sectionCost);
        }

        // remove section
        var sectionNode = document.getElementById('section' + sectionID);
        var sectionType = sectionNode.getElementsByTagName('legend')[0].innerHTML;
        var sectionTypes = configurator.getElementsByTagName('legend');
        var sectionCount = 0;
        for (var i = 0; i < sectionTypes.length; i++) {
            if (sectionTypes[i].innerHTML == sectionType)
                sectionCount++;
        }
        if (sectionCount > 1)
            sectionNode.parentNode.removeChild(sectionNode);
        else
            sectionNode.style.display = 'none';
    }
}

function dependencyRule(id, products, dependencies, quantity, message) {
    this.id = id;
    this.products = products;
    this.dependencies = dependencies;
    this.quantity = quantity;
    this.message = message;
}

function evaluateDependencies(e) {
    var target = getEventTarget(e);
    target.id.match(/Product(\d+)/i);
    var productID = RegExp.$1;
    for (var i = 0; i < dependencyRules.length; i++) {
        // check rules that apply to this product
        for (var j = 0; j < dependencyRules[i].products.length; j++) {
            if (dependencyRules[i].products[j] == productID)
                checkDependencyRule(dependencyRules[i]);
        }
        // check rules that  this product is a requirement for
        for (var j = 0; j < dependencyRules[i].dependencies.length; j++) {
            if (dependencyRules[i].dependencies[j] == productID)
                checkDependencyRule(dependencyRules[i]);
        }
    }
}

function checkDependencyRule(rule) {
    // check to see if the dependencies for this rule are met
    var reqirementMet = true;
    var quantity = 0;
    var inputs = configurator.getElementsByTagName('input');
    var selects = configurator.getElementsByTagName('select');
    for (var i = 0; i < inputs.length; i++) {
        if (inputs[i].checked && inputs[i].value > 0) {
            for (var j = 0; j < rule.products.length; j++) {
                if (inputs[i].value == rule.products[j]) {
                    quantity++;
                }
            }
        }
    }
    for (var i = 0; i < selects.length; i++) {
        if (selects[i].value > 0) {
            for (var j = 0; j < rule.products.length; j++) {
                if (selects[i].value == rule.products[j]) {
                    quantity++;
                }
            }
        }
    }
    if (quantity >= rule.quantity) {
        reqirementMet = false;
        for (var i = 0; i < inputs.length; i++) {
            for (var j = 0; j < rule.dependencies.length; j++) {
                if (inputs[i].value > 0 && inputs[i].value == rule.dependencies[j] && inputs[i].checked)
                    reqirementMet = true;
            }
        }
        for (var i = 0; i < selects.length; i++) {
            for (var j = 0; j < rule.dependencies.length; j++) {
                if (selects[i].value == rule.dependencies[j] && selects[i].value > 0)
                    reqirementMet = true;
            }
        }
    }
    if (reqirementMet == false) {
        // dependencies are not met so add an error message if it is not all ready there
        var configurationErrors = document.getElementById('configurationErrors');
        var errorMessage = document.getElementById('dependencyRule' + rule.id + 'Error');
        if (errorMessage == null) {
            errorMessage = document.createElement('div');
            errorMessage.id = 'dependencyRule' + rule.id + 'Error';
            errorMessage.innerHTML = rule.message;
            errorMessage.className = 'error';
            configurationErrors.appendChild(errorMessage);
        }
    }
    else {
        // dependencies are met so remove any associated error messages
        var errorMessage = document.getElementById('dependencyRule' + rule.id + 'Error');
        if (errorMessage) {
            errorMessage.parentNode.removeChild(errorMessage);
        }
    }
}

function incompatibilityRule(id, products, incompatibleProducts, quantity, message) {
    this.id = id;
    this.products = products;
    this.incompatibleProducts = incompatibleProducts;
    this.quantity = quantity;
    this.message = message;
}

function evaluateIncompatibilities(e) {
    var target = getEventTarget(e);
    target.id.match(/Product(\d+)/i);
    var productID = RegExp.$1;
    for (var i = 0; i < incompatibilityRules.length; i++) {
        // check rules that apply to this product
        for (var j = 0; j < incompatibilityRules[i].products.length; j++) {
            if (incompatibilityRules[i].products[j] == productID)
                checkIncompatibilityRule(incompatibilityRules[i]);
        }
        // check rules that  this product is a requirement for
        for (var j = 0; j < incompatibilityRules[i].incompatibleProducts.length; j++) {
            if (incompatibilityRules[i].incompatibleProducts[j] == productID)
                checkIncompatibilityRule(incompatibilityRules[i]);
        }
    }
}

function checkIncompatibilityRule(rule) {
    var ruleActive = false;
    var quantity = 0;
    // check if any products this rule applies to are selected
    var inputs = configurator.getElementsByTagName('input');
    var selects = configurator.getElementsByTagName('select');
    for (var i = 0; i < inputs.length; i++) {
        for (var j = 0; j < rule.products.length && ruleActive == false; j++) {
            if (rule.products[j] > 0 && inputs[i].value == rule.products[j] && inputs[i].checked) {
                ruleActive = true;
            }
        }
    }
    for (var i = 0; i < selects.length; i++) {
        for (var j = 0; j < rule.products.length && ruleActive == false; j++) {
            if (rule.products[j] > 0 && selects[i].value == rule.products[j]) {
                ruleActive = true;
            }
        }
    }
    if (ruleActive) {
        for (var i = 0; i < inputs.length; i++) {
            if (inputs[i].checked && inputs[i].value > 0) {
                for (var j = 0; j < rule.incompatibleProducts.length; j++) {
                    if (inputs[i].value == rule.incompatibleProducts[j]) {
                        quantity++;
                    }
                }
            }
        }
        for (var i = 0; i < selects.length; i++) {
            if (selects[i].value > 0) {
                for (var j = 0; j < rule.incompatibleProducts.length; j++) {
                    if (selects[i].value == rule.incompatibleProducts[j]) {
                        quantity++;
                    }
                }
            }
        }
    }
    if (ruleActive && quantity >= rule.quantity) {
        // incompatibilities are present so add an error message if it is not all ready there
        var configurationErrors = document.getElementById('configurationErrors');
        var errorMessage = document.getElementById('incompatibilityRule' + rule.id + 'Error');
        if (errorMessage == null) {
            errorMessage = document.createElement('div');
            errorMessage.id = 'incompatibilityRule' + rule.id + 'Error';
            errorMessage.innerHTML = rule.message;
            errorMessage.className = 'error';
            configurationErrors.appendChild(errorMessage);
        }
    }
    else {
        // no incompatibility exisits for this rule so remove any associated error messages
        var errorMessage = document.getElementById('incompatibilityRule' + rule.id + 'Error');
        if (errorMessage) {
            errorMessage.parentNode.removeChild(errorMessage);
        }
    }
}

function initialize() {
    configurator = document.getElementById('configurator');
    if (configurator) {
        loadRules();
        var links = configurator.getElementsByTagName('input');
        for (var i = 0; i < links.length; i++) {
            if (links[i].id.search(/section\d+close/) >= 0)
                addEvent(links[i], 'click', closeSections);
            else if (links[i].id.search(/section\d+open/) >= 0)
                addEvent(links[i], 'click', editSection);
            else if (links[i].id.search(/section\d+remove/) >= 0)
                addEvent(links[i], 'click', removeSection);
            else if (links[i].id.search(/section\d+add/) >= 0)
                addEvent(links[i], 'click', addSection);
        }
        var inputs = configurator.getElementsByTagName('input');
        for (var i = 0; i < inputs.length; i++) {
            // add event to update prices
            switch (inputs[i].type) {
                case 'radio':
                    addEvent(inputs[i], 'click', radioChange);
                    break;
                case 'checkbox':
                    addEvent(inputs[i], 'click', checkboxChange);
                    break;
            }
            // add events to test dependency rules
            for (var j = 0; j < dependencyRules.length; j++) {
                for (var k = 0; k < dependencyRules[j].products.length; k++) {
                    if (inputs[i].id.search('Product' + dependencyRules[j].products[k]) > 0) {
                        addEvent(inputs[i], 'click', evaluateDependencies);
                    }
                }
                for (var k = 0; k < dependencyRules[j].dependencies.length; k++) {
                    if (inputs[i].id.search('Product' + dependencyRules[j].dependencies[k]) > 0) {
                        addEvent(inputs[i], 'click', evaluateDependencies);
                    }
                }
            }
            // add events to test incompatibility rules
            for (var j = 0; j < incompatibilityRules.length; j++) {
                for (var k = 0; k < incompatibilityRules[j].products.length; k++) {
                    if (inputs[i].id.search('Product' + incompatibilityRules[j].products[k]) > 0) {
                        addEvent(inputs[i], 'click', evaluateIncompatibilities);
                    }
                }
                for (var k = 0; k < incompatibilityRules[j].incompatibleProducts.length; k++) {
                    if (inputs[i].id.search('Product' + incompatibilityRules[j].incompatibleProducts[k]) > 0) {
                        addEvent(inputs[i], 'click', evaluateIncompatibilities);
                    }
                }
            }
        }
        // add event to update prices
        var selects = configurator.getElementsByTagName('select');
        for (var i = 0; i < selects.length; i++)
            addEvent(selects[i], 'change', dropdownChange);
        // add events to test dependency rules
        var options = configurator.getElementsByTagName('option');
        for (var i = 0; i < options.length; i++) {
            for (var j = 0; j < dependencyRules.length; j++) {
                for (var k = 0; k < dependencyRules[j].products.length; k++) {
                    if (options[i].value == dependencyRules[j].products[k]) {
                        addEvent(options[i].parentNode, 'change', evaluateDependencies);
                    }
                }
                for (var k = 0; k < dependencyRules[j].dependencies.length; k++) {
                    if (options[i].value == dependencyRules[j].dependencies[k]) {
                        addEvent(options[i].parentNode, 'change', evaluateDependencies);
                    }
                }
            }
        }
        // add events to test incompatibility rules
        for (var i = 0; i < options.length; i++) {
            for (var j = 0; j < incompatibilityRules.length; j++) {
                for (var k = 0; k < incompatibilityRules[j].products.length; k++) {
                    if (options[i].value == incompatibilityRules[j].products[k]) {
                        addEvent(options[i].parentNode, 'change', evaluateIncompatibilities);
                    }
                }
                for (var k = 0; k < incompatibilityRules[j].incompatibleProducts.length; k++) {
                    if (options[i].value == incompatibilityRules[j].incompatibleProducts[k]) {
                        addEvent(options[i].parentNode, 'change', evaluateIncompatibilities);
                    }
                }
            }
        }
    }
    configurator = document.getElementById('configurationSummary');
    if (configurator) {

        var quantity = document.getElementById('summaryQuantity');
        addEvent(quantity, 'change', updateGrandTotal);
        updateGrandTotal();
    }
}

function updateGrandTotal(e) {
    document.getElementById('summaryQuantity').value = document.getElementById('summaryQuantity').value.replace(/[^0-9.]/g, "")
    var quantity = parseInt(document.getElementById('summaryQuantity').value);
    if (isNaN(quantity)) {
        alert("The specified quantity is not valid.");
    }
    else {
        var totalPriceNode = document.getElementById('totalPrice');
        if (totalPriceNode != null) {
            var totalPrice = parseInt(totalPriceNode.innerHTML.replace(/[^0-9.]/g, ""))
            var grandTotalPrice = document.getElementById('grandTotalPrice');
            grandTotalPrice.innerHTML = "$" + totalPrice * quantity;
        }
    }
}

function getEventTarget(e) {
    var targ;
    if (!e) var e = window.event;
    if (e.target) targ = e.target;
    else if (e.srcElement) targ = e.srcElement;
    if (targ.nodeType == 3) // defeat Safari bug
        targ = targ.parentNode;
    return targ;
}

function addEvent(obj, evType, fn) {
    if (obj.addEventListener) {
        obj.addEventListener(evType, fn, true);
        return true;
    }
    else if (obj.attachEvent) {
        var r = obj.attachEvent("on" + evType, fn);
        return r;
    }
    else
        return false;
}

addEvent(window, 'load', initialize);
