/***
 * Singleton/module that encapsulates general interactions between modules on Product Archive page.
 * @author Ryan Mulloy (based off of WTBInteraction Manager by Adam McIntyre)
 * @see GMapsManager
 * @see DDListManager
 */
ArchiveInteractionManager = function() {
    var CI_URL = '/servlet/ci';    // Third-party feed URL
    var REQ_PARAMS = {    // Required third-party parameters
        'sSKU' : "",
        'sZip' : "",
        'nRadius' : 0,
        'nRGID' : 0
    };
    var conn;    // Placeholders for YUI connection object
    var htmlTemplate = '<div id="retailer_{index}" class="retailer"><img src="http://www.google.com/mapfiles/marker{charCode}.png" onclick="GMapsManager.showOverlay({index})" class="marker"/>' +
                       '<div class="hd"><h3 id="retailerName_{index}">{name}</h3>&nbsp;&ndash;&nbsp;<span>{distance}</span></div>' +
                       '<div class="bd"><div id="formattedAddress_{index}"><address>{address}</address><strong>{phone}</strong></div><span id="markerFmtAddress_{index}" class="noD">{markerFmtAddress}</span></div></div>';
    var productTemplate = '<h1>{productName}</h1><div class="content"><p>{longValueProp}</p> ' +
                          '<div>{productBullets}</div>' +
                          '<p class="infoLinks"><a href="{productLink}">Find out more</a><br/>' +
                          '<a href="javascript:void(0)" onclick="ArchiveInteractionManager.showAuthDealers()">Authorized Dealer Disclaimer</a></p>' +
                          '<img src="{imgUrl}" id="swapTarget"/></div>';
    var retailerPoints = [];

    return{
        /***
         * Fetches a result set from third-party.
         * Requires REQ_PARAMS being set before call.
         * @param {Function} cb (Optional) Optional callback Function to run once request completes.
         */
        gotoUrl:null,
        fetchResults : function(cb) {
            var that = this;
            if(REQ_PARAMS.set) {
                var callback = {
                    cache : false,
                    success : function(o) {
                        var templatedHtml = that.xmlTemplate(o.responseXML);

                        // It's possible for there to be no matching results.
                        // If there are matches, templatedHtml will have HTML in it and
                        // its length will be greater than 0 characters. Otherwise, there are no results.
                        if(templatedHtml.length > 0) {
                            document.getElementById('retailers_target').innerHTML = templatedHtml;
                            document.getElementById('listingsDisclaimerText').innerHTML =
                            "Please contact your Nikon Authorized Retailer directly to confirm whether" +
                            " the product you are looking for is in stock.";

                            YAHOO.util.Dom.removeClass('listingsDisclaimerText', 'error');
                            YAHOO.util.Dom.removeClass('results_container', 'noD');
                            YAHOO.util.Dom.removeClass('container_retailers', 'noD');
                            YAHOO.util.Dom.removeClass('container_map', 'noD');

                            if(GBrowserIsCompatible()) {
                                GMapsManager.setMap('container_map').center(retailerPoints[0]);
                                GMapsManager.addMarker(retailerPoints);
                            }

                            Expanders.init();
                        }
                        else {
                            document.getElementById('listingsDisclaimerText').innerHTML =
                            "<em>Sorry, we were unable to locate a Nikon Authorized Retailer. Please confirm that the " +
                            "zip code entered above is correct. You may also try increasing the search radius.</em>";

                            YAHOO.util.Dom.addClass('listingsDisclaimerText', 'error');
                            YAHOO.util.Dom.addClass('container_retailers', 'noD');
                            YAHOO.util.Dom.addClass('container_map', 'noD');
                        }

                        if(o.responseXML.getElementsByTagName('pixel-url').length > 0) {
                            var pixel = o.responseXML.getElementsByTagName('pixel-url')[0];
                            var im = document.createElement('img');

                            if(pixel.text) {
                                im.src = pixel.text;
                            }
                            else {
                                im.src = pixel.textContent;
                            }
                            document.body.appendChild(im);
                        }

                        if(cb) {
                            cb();
                        }

                        YAHOO.util.Event.addListener(document.body, 'unload', function() {
                            GUnload();
                        });

                        acc.openBlade(acc.bladeEls[2]);
                    },
                    failure : function() {
                        alert("We encountered a problem. Please try again.")
                    },
                    error : function() {
                        alert("We encountered a problem. Please try again.")
                    }
                }

                var sUrl = CI_URL + '?';

                for(var p in REQ_PARAMS) {
                    sUrl += p + '=' + REQ_PARAMS[p] + '&';
                }
                sUrl = sUrl.substr(0, sUrl.length - 1); // Remove trailing &

                if(YAHOO.util.Connect.isCallInProgress(conn)) {
                    YAHOO.util.Connect.abort(conn);
                }

                if(YAHOO.util.Connect.isCallInProgress(conn)) {
                    YAHOO.util.Connect.abort(conn);
                }
                conn = YAHOO.util.Connect.asyncRequest('GET', sUrl, callback);
            }
            else {
                return false;
            }
        },
        /***
         * Sets the parameters required by third-party to retrieve merchant results.
         * @param {Object} params Object matching REQ_PARAMS template above.
         */
        setRequiredParameters : function(params) {
            REQ_PARAMS = params;
            REQ_PARAMS.set = true;

            return this;
        },
        /***
         * Default template for Channel Intelligence's returned Document.
         * @param {Document} d XML Document containing CI data.
         */
        xmlTemplate : function(d) {
            var dealers = d.getElementsByTagName('dealer');
            var x = new Date();
            var html = "";
            retailerPoints = [];

            if(dealers.length > 0) {
                var len = (dealers.length > 26) ? 26 : dealers.length;
                html = '<label class="small"><strong>Results Found: ' + dealers.length + '</strong></label>';

                for(var i = 0; i < len; i++) {
                    var dealer = dealers[i];
                    var children = YAHOO.util.Dom.getChildren(dealer);
                    var distance = YAHOO.util.Dom.getChildren(children[2]);
                    var contactNodeChildren = YAHOO.util.Dom.getChildren(children[1]);

                    if(contactNodeChildren[0].text) { // IE uses "text" attribute...
                        var markerFmtHtml = contactNodeChildren[0].text + ' ' +
                                            contactNodeChildren[1].text +
                                            ', ' +
                                            contactNodeChildren[2].text +
                                            ' ' +
                                            contactNodeChildren[3].text;

                        retailerPoints.push(markerFmtHtml);

                        // Calculate/concatonate distance string.
                        var strDistance = parseFloat(distance[0].text).toFixed(1);
                        strDistance += (distance.length > 1 ? distance[1].text.toLowerCase() : 'm');

                        // Is there a phone number available?
                        if(contactNodeChildren.length > 5) {
                            var phoneStr = this.formatPhone(contactNodeChildren[5].text);
                        }
                        else {
                            var phoneStr = "&nbsp;";
                        }

                        html += htmlTemplate.replace('{name}', children[0].text).replace(/{index}/g,
                                i).replace('{distance}', strDistance).replace('{address}',
                                contactNodeChildren[0].text + '<br/>' +
                                contactNodeChildren[1].text +
                                ', ' +
                                contactNodeChildren[2].text +
                                ' ' +
                                contactNodeChildren[3].text).replace('{markerFmtAddress}',
                                markerFmtHtml).replace('{phone}', phoneStr).replace('{charCode}',
                                String.fromCharCode("A".charCodeAt(0) + i));
                    }
                    else {
                        var markerFmtHtml = contactNodeChildren[0].textContent + ' ' +
                                            contactNodeChildren[1].textContent +
                                            ', ' +
                                            contactNodeChildren[2].textContent +
                                            ' ' +
                                            contactNodeChildren[3].textContent;

                        retailerPoints.push(markerFmtHtml);

                        // Calculate/concatonate distance string.
                        var strDistance = parseFloat(distance[0].textContent).toFixed(1);
                        strDistance += (distance.length > 1 ? distance[1].textContent.toLowerCase() : 'm');

                        // Is there a phone number available?
                        if(contactNodeChildren.length > 5) {
                            var phoneStr = this.formatPhone(contactNodeChildren[5].textContent);
                        }
                        else {
                            var phoneStr = "&nbsp;";
                        }

                        html += htmlTemplate.replace('{name}', children[0].textContent).replace(/{index}/g,
                                i).replace('{distance}', strDistance).replace('{address}',
                                contactNodeChildren[0].textContent + '<br/>' +
                                contactNodeChildren[1].textContent +
                                ', ' +
                                contactNodeChildren[2].textContent +
                                ' ' +
                                contactNodeChildren[3].textContent).replace('{markerFmtAddress}',
                                markerFmtHtml).replace('{phone}', phoneStr).replace('{charCode}',
                                String.fromCharCode("A".charCodeAt(0) + i));
                    }
                }
            }
            return html;
        },
        /***
         * Format a phone number into "."-separated version.
         * @param {String} str Phone nmber to format
         */
        formatPhone : function(str) {
            var m = str.match(/([0-9]{3}).?([0-9]{3}).?([0-9]{4})/);
            return m[1] + '.' + m[2] + '.' + m[3];
        },
        /***
         * Placeholder for DDListManager's selected product's ID.
         */
        selectedProduct : '',
        /***
         * Interwoven "Ajax Url" for retrieving products/categories
         */
        ajaxUrl : '',
        /***
         * This determines if we will show ARCHIVED, ACTIVE, or ALL products
         */
        productStatus : '',
        /***
         * Fetches and formats product data into select boxes.
         * @param {MultipleSelectItem} o MultipleSelectItem that triggered this action
         * @param {String} selectedValue "Value" of selected option
         */
        getData : function(o, selectedValue) {
            var that = this;
            var callback = {
                argument : [that],
                success : function(r) {
                    // Do we have a products list?
                    if(r.responseXML.getElementsByTagName('Product').length > 0) {
                        // Do we need to process groups?
                        if(r.responseXML.getElementsByTagName('Group').length > 0) {
                            that.processGroupData(r.responseXML.getElementsByTagName('Group'),
                                    r.responseXML.getElementsByTagName('Product'),
                                    o, selectedValue, r.responseXML.getElementsByTagName('Variants'));
                        }
                        else {
                            that.processProductData(r.responseXML.getElementsByTagName('Product'), o, selectedValue,
                                    r.responseXML.getElementsByTagName('Variants'));
                        }
                    }
                },
                failure : function(r) {
                    alert("There was a problem. Please try again.")
                },
                error : function(r) {
                    alert("There was a problem. Please try again.")
                }
            }

            if(YAHOO.util.Connect.isCallInProgress(conn)) {
                YAHOO.util.Connect.abort(conn);
            }

            // Build up the parameters we'll need to send to component, including
            // action, ctc, and cc
            var params = '?';
            var sOpt = o.el.options[o.el.selectedIndex];
            var vals = sOpt.value.split('&');

            var ctcVal = vals[0].split('=')[1];
            var ccVal = vals[1].split('=')[1];

            if(ctcVal != '') {
                params += 'action=getModels&ProductStatus=' + ArchiveInteractionManager.productStatus + '&ctc=' + ctcVal + '&cc=' + ccVal;
            }
            else {
                for(var i = 0; i < o.children.length; i++) {
                    if(o.children[i].displayed) {
                        var ch = o.children[i];

                        sOpt = o.el.options[o.el.selectedIndex];
                        vals = sOpt.value.split('&');

                        ctcVal = vals[0].split('=')[1];
                        ccVal = vals[1].split('=')[1];

                        params += 'action=getModels&ProductStatus=' + ArchiveInteractionManager.productStatus + '&ctc=' + ctcVal + '&cc=' + ccVal;
                    }
                }
            }
            conn = YAHOO.util.Connect.asyncRequest('GET', ArchiveInteractionManager.ajaxUrl + params, callback);
        },
        /***
         * Processes a series of Group nodes, creating drop-down-parsing ready Objects.
         * @param {Array} groups Groups to be processed.
         */
        _buildGroupData : function(groups) {
            var arr = [];

            for(var i = 0; i < groups.length; i++) {
                var g = groups[i];
                var cProducts = g.getElementsByTagName('Product');
                var cOpts = [];

                for(var j = 0; j < cProducts.length; j++) {
                    var el = cProducts[j];
                    if(! (el.parentNode.tagName.toLowerCase() == "variants")) {
                        var tmpObj = {};

                        var productTitle = el.getElementsByTagName('Title')[0];
                        var productUrl = el.getElementsByTagName('URL')[0];
                        tmpObj.trigger = el.getAttribute('ProductId');

                        if(productTitle.text) {
                            tmpObj.text = productTitle.text;
                        }
                        else {
                            tmpObj.text = productTitle.textContent;
                        }

                        if(productUrl.text) {
                            tmpObj.value = productUrl.text;
                        }
                        else {
                            tmpObj.value = productUrl.textContent;
                        }
                        cOpts.push(tmpObj);
                    }
                }

                arr.push({'name' : g.getAttribute('name'), 'childOptions' : cOpts})
            }
            return arr;
        },
        /***
         * Builds the Object structure necessary for a single Product node for dropdown parsing.
         * @param {Element} prod Product to be parsed and processed.
         */
        _buildProductItem : function(prod) {
            var tmpObj = {};
            var productTitle = prod.getElementsByTagName('Title')[0];
            var productUrl = prod.getElementsByTagName('URL')[0];
            tmpObj.trigger = prod.getAttribute('ProductId');

            if(productTitle.text) {
                tmpObj.text = productTitle.text;
            }
            else {
                tmpObj.text = productTitle.textContent;
            }

            if(productUrl.text) {
                tmpObj.value = productUrl.text;
            }
            else {
                tmpObj.value = productUrl.textContent;
            }
            return tmpObj;
        },
        /***
         * Processes, if applicable, a series of Variant nodes, building them into dropdowns locked to a parent product ID.
         * @param {ElementArray} v Array of variants to be processed. Could very well be empty.
         * @param {string} msiID ID of Multiple Select Item we'll be tying these variant dropdowns to.
         */
        _processVariants : function(v, msiID) {
            var that = this;
            if(v.length == 0) {
                return false;
            }
            else {
                for(var i = 0; i < v.length; i++) {
                    var curV = v[i];
                    var pNode = curV.parentNode;

                    var products = curV.getElementsByTagName('Product');
                    var arr = [];

                    arr.push({value : '', text : '-- ' + nikon.utils.locale.get("Global.Labels.selectColor") + ' --' });

                    for(var j = 0; j < products.length; j++) {
                        var product = products[j];
                        var tmpObj = {};
                        var productColor = product.getElementsByTagName('Color')[0]
                                .getElementsByTagName('Name')[0];

                        tmpObj.value = product.getAttribute('ProductId');

                        if(productColor.text) {
                            tmpObj.text = productColor.text;
                        }
                        else {
                            tmpObj.text = productColor.textContent;
                        }

                        tmpObj.optional = { key : 'pId', value : pNode.getAttribute('ProductId') };

                        arr.push(tmpObj);
                    }
                    if(! document.getElementById('variant_' + pNode.getAttribute('ProductId'))) {
                        dd.addSelectItems(arr, 'variant_' + pNode.getAttribute('ProductId'), msiID,
                                '_' + curV.parentNode.getAttribute('ProductId'),
                                function(e, args, o) {
                                    that.showCenteredLoadingIcon('hero', 'content_inner');
                                    var selectedValue = o.el.options[o.el.selectedIndex].getAttribute('value');
                                    var params = "?action=getProduct&ProductStatus=" + WTBInteractionManager.productStatus + "&pid=" + selectedValue;
                                    var cb = {
                                        argument : [that],
                                        success : ArchiveInteractionManager.updateProductInfo,
                                        failure : function(o) {
                                            alert(nikon.utils.locale.get("Global.ErrorLoad"));
                                        },
                                        error : function(o) {
                                            alert(nikon.utils.locale.get("Global.ErrorLoad"));
                                        }
                                    }
                                    if(YAHOO.util.Connect.isCallInProgress(conn)) {
                                        YAHOO.util.Connect.abort(conn);
                                    }
                                    conn = YAHOO.util.Connect.asyncRequest('GET',
                                            ArchiveInteractionManager.ajaxUrl + params, cb);
                                });
                        dd.hideSelects(msiID);
                    }
                }
            }
        },
        /***
         * Processes a set of Group nodes, building them into an optgroup-separated dropdown list which is inserted into the DOM.
         * @param {ElementAray} groups Array of Group nodes
         * @param {ElementArray} products Array of Product nodes. Used to check if there are un-grouped Product nodes.
         * @param {Object} o Calling object. Used in dropdown creation.
         * @param {String} selectedValue Currently selected dropdown value. Used in dropdown creation.
         * @param {ElementArray} v Array of Variant nodes.
         */
        processGroupData : function(groups, products, o, selectedValue, v) {
            var that = this;
            var arrBefore = [
                {value : '', text : "-- " + nikon.utils.locale.get("Global.SelectProduct") + "--" }
            ];
            var arr = this._buildGroupData(groups);

            // Some products may not have a group as a parent. These we add to the "after" array
            // to tack them onto the bottom of the dropdown.
            var arrAfter = [];
            for(var i = 0; i < products.length; i++) {
                if(products[i].parentNode.tagName.toLowerCase() == 'group' ||
                   products[i].parentNode.tagName.toLowerCase() == "variants") {
                    continue;
                }
                else {
                    arrAfter.push(this._buildProductItem(products[i]));
                }
            }

            var newItemId = dd.addGroupSelectItems(arr, arrBefore, arrAfter, null, o.id, selectedValue,
                    function(e, args, o) {
                        /*******
                         * RM: I commented out most of this code because it won't be used in Product Archive
                         * I want to keep it in here in case Nikon wants to show the product info here
                         */
                        ArchiveInteractionManager.gotoUrl = o.el.options[o.el.selectedIndex].getAttribute('value');
                        ArchiveInteractionManager.updateProductInfo();
                        /*var selectedValue = o.el.options[o.el.selectedIndex].getAttribute('data-trigger');
                         var cItem = o._getChildItem('_' + selectedValue);

                         o.hideChildren();
                         if(cItem){
                         cItem.showItem();
                         }
                         else{
                         that.showCenteredLoadingIcon('hero','content_inner');
                         var params = "?action=getProduct&ProductStatus=" + ArchiveInteractionManager.productStatus + "&pid=" + selectedValue;
                         var cb = {
                         argument : [that],
                         success : ArchiveInteractionManager.updateProductInfo,
                         failure : function(o){
                         alert("We've encountered an error retrieving your product. Please try again.");
                         },
                         error : function(o){
                         alert("We've encountered an error retrieving your product. Please try again.");
                         }
                         }
                         if(YAHOO.util.Connect.isCallInProgress(conn)){
                         YAHOO.util.Connect.abort(conn);
                         }
                         conn = YAHOO.util.Connect.asyncRequest('GET',ArchiveInteractionManager.ajaxUrl + params,cb);
                         }*/
                    });

            /*** Exception: Products with variants ... ***/
            this._processVariants(v, newItemId);
        },
        /***
         * Processes a set of Product nodes, building them into a options in a dropdown list which is inserted into the DOM.
         * @param {ElementArray} products Array of Product nodes. Used to check if there are un-grouped Product nodes.
         * @param {Object} o Calling object. Used in dropdown creation.
         * @param {String} selectedValue Currently selected dropdown value. Used in dropdown creation.
         * @param {ElementArray} v Array of Variant nodes.
         */
        processProductData : function(products, o, selectedValue, v) {
            var that = this;
            var arr = [];
            arr.push({value : '', text : "-- " + nikon.utils.locale.get("Global.SelectProduct") + " --" });

            for(var i = 0; i < products.length; i++) {
                var el = products[i];
                if(! (el.parentNode.tagName.toLowerCase() == "variants")) {
                    arr.push(this._buildProductItem(products[i]));
                }
            }

            var newItemId = dd.addSelectItems(arr, null, o.id, selectedValue,
                    function(e, args, o) {
                        /*******
                         * RM: I commented out most of this code because it won't be used in Product Archive
                         * I want to keep it in here in case Nikon wants to show the product info here
                         */
                        ArchiveInteractionManager.gotoUrl = o.el.options[o.el.selectedIndex].getAttribute('value');
                        ArchiveInteractionManager.updateProductInfo();
                        /*var selectedValue = o.el.options[o.el.selectedIndex].getAttribute('data-trigger');
                         var cItem = o._getChildItem('_' + selectedValue);

                         o.hideChildren();
                         if(cItem){
                         cItem.showItem();
                         }
                         else{
                         that.showCenteredLoadingIcon('hero','content_inner');
                         var params = "?action=getProduct&ProductStatus=" + ArchiveInteractionManager.productStatus + "&pid=" + selectedValue;
                         var cb = {
                         argument : [that],
                         success : ArchiveInteractionManager.updateProductInfo,
                         failure : function(o){
                         alert("We've encountered an error retrieving your product. Please try again.");
                         },
                         error : function(o){
                         alert("We've encountered an error retrieving your product. Please try again.");
                         }
                         }
                         if(YAHOO.util.Connect.isCallInProgress(conn)){
                         YAHOO.util.Connect.abort(conn);
                         }
                         conn = YAHOO.util.Connect.asyncRequest('GET',ArchiveInteractionManager.ajaxUrl + params,cb);
                         }*/
                    });

            /*** Exception: Products with variants ... ***/
            this._processVariants(v, newItemId);
        },
        /***
         * Attaches appropriate "click" action to "next" button.
         */
        attachNextButtonEvent : function() {
            var that = this;
            var btnNext = document.getElementById('btn_next');
            btnNext.src = "/static/images/" + nikon.utils.locale.get("Global.locale") + "/buttons/btn_archive_show_product_on.jpg";
            nikon(btnNext).removeClass('button-disabled');

            // Clean up any other attched 'click' listeners.
            YAHOO.util.Event.removeListener('btn_next', 'click');

            YAHOO.util.Event.addListener('btn_next', 'click', function() {
                window.location = ArchiveInteractionManager.gotoUrl;
            });
            return this;
        },
        /***
         * Attaches special-case "click" action to "next" button for redirecting between sites.
         */
        attachNextButtonRedirect : function(strUrl) {
            var btnNext = document.getElementById('btn_next');
            btnNext.src = "/static/images/" + nikon.utils.locale.get("Global.locale") + "/buttons/btn_archive_show_product_on.jpg";
            nikon(btnNext).removeClass('button-disabled');

            // Clean up any other attched 'click' listeners.
            YAHOO.util.Event.removeListener('btn_next', 'click');

            YAHOO.util.Event.addListener('btn_next', 'click', function() {
                window.open(strUrl, '');
            });
            return this;
        },
        /***
         * Attaches appropriate "click" action to "next" button.
         */
        disableNextButton : function() {
            var btnNext = document.getElementById('btn_next');
            btnNext.src = "/static/images/" + nikon.utils.locale.get("Global.locale") + "/buttons/btn_archive_show_product_off.jpg";
            nikon(btnNext).addClass('button-disabled');
        },
        /*crazy hack to make this work correctly in Safari 3 in Mac. Turn it off and use the select boxes to see what I mean */
        toggleMargin:function(targetElement) {
            if(YAHOO.env.ua.webkit) {
                setTimeout(function() {
                    YAHOO.util.Dom.setStyle(targetElement, 'margin-top', "1px");
                    setTimeout(function() {
                        YAHOO.util.Dom.setStyle(document.getElementById("wtb_categories"), 'margin-top', "0px");
                    }, 100);
                }, 1000);
            }
        },
        /***
         * Attaches appropriate "click" action to "search" button.
         */
        attachSearchButtonEvent : function() {
            var that = this;
            YAHOO.util.Event.addListener('btn_search', 'click', function() {
                that.showLoadingIndicator('loader_section3');
                that.setRequiredParameters({
                    'sSKU' : that.selectedProduct,
                    'sZip' : document.getElementById('wtb_zip').value,
                    'nRadius' : document.getElementById('wtb_distance')
                            .options[document.getElementById('wtb_distance').selectedIndex].value,
                    'nRGID' : 2121    // Using Channel Intelligence's stock RGID for testing
                }).fetchResults(function() {
                    ArchiveInteractionManager.hideLoadingIndicator('loader_section3');
                });
                YAHOO.util.Event.removeListener(this, 'click');
                that.setSearchAgainButtonEvents();
            });
            return this;
        },
        /***
         * Attaches appropriate "click" actions to "next" and "search" buttons
         * for users that have already performed a search.
         */
        setSearchAgainButtonEvents : function() {
            var arr = ['btn_search','btn_next'];

            YAHOO.util.Event.addListener(arr, 'click', function() {
                var el = YAHOO.util.Dom.getElementsByClassName('wide_content')[0];
                ArchiveInteractionManager.showCenteredLoadingIcon(el, 'results_container');
                GMapsManager._getMap().clearOverlays();
                ArchiveInteractionManager.setRequiredParameters({
                    'sSKU' : ArchiveInteractionManager.selectedProduct,
                    'sZip' : document.getElementById('wtb_zip').value,
                    'nRadius' : document.getElementById('wtb_distance')
                            .options[document.getElementById('wtb_distance').selectedIndex].value,
                    'nRGID' : 2121    // Using Channel Intelligence's stock RGID for testing
                }).fetchResults(function() {
                    ArchiveInteractionManager.hideCenteredLoadingIcon(el, 'results_container');
                });
            });
            return this;
        },
        /***
         * Shows a loading indicator (or any element, really) of given ID.
         * @param {String|HTMLElement} el ID of indicator we'd like to show.
         * @param {Function} cb (Optional) Callback we'd like to run on fade in animation's onComplete Event.
         */
        showLoadingIndicator : function(el, cb) {
            if(YAHOO.env.ua.ie != 0 && !(YAHOO.env.ua.ie > 6)) {
                YAHOO.util.Dom.setStyle(el, 'filter', '');
            }
            else {
                var anim = new YAHOO.util.Anim(el, {
                    opacity: {
                        to: 0.99
                    }
                }, 0.15, YAHOO.util.Easing.easeIn);

                if(cb) {
                    anim.onComplete.subscribe(cb);
                }

                anim.animate();
            }
        },
        /***
         * Hides a loading indicator (or any element, really) of given ID.
         * @param {String|HTMLElement} el ID of indicator we'd like to hide.
         * @param {Function} cb (Optional) Callback we'd like to run on fade out animation's onComplete Event.
         */
        hideLoadingIndicator : function(el, cb) {
            if(YAHOO.env.ua.ie != 0 && !(YAHOO.env.ua.ie > 6)) {
                YAHOO.util.Dom.setStyle(el, 'opacity', '0');
            }
            else {
                var anim = new YAHOO.util.Anim(el, {
                    opacity: {
                        to: 0
                    }
                }, 0.15, YAHOO.util.Easing.easeOut);

                if(cb) {
                    anim.onComplete.subscribe(cb);
                }

                anim.animate();
            }
        },
        /***
         * Shows the "loading wheel" centered in given el. Fades el to 35% opacity prior.
         * @param {String|HTMLElement} el Element we'd like to show as loading. We'll fade out a "bd" element below it.
         * @param {String} (Optional) cName ClassName of Element we'd like to fade back in.
         * @param {Function} cb (Optional) Function we'd like to run after animation completes.
         */
        showCenteredLoadingIcon : function(el, cName, cb) {
            el = YAHOO.util.Dom.get(el);
            if(! cName) {
                cName = 'bd';
            }

            var bdElement = YAHOO.util.Dom.getElementsByClassName(cName, 'div', el)[0];

            var anim = new YAHOO.util.Anim(bdElement, {
                opacity : { to : 0.35 }
            },
                    0.35,
                    YAHOO.util.Easing.easeIn);

            anim.onStart.subscribe(function() {
                var d = document.createElement('div');
                d.id = "loadingIndicator";
                d.className = "centeredLoading";
                el.appendChild(d);
            });

            anim.onComplete.subscribe(function() {
                if(cb) {
                    cb();
                }
            });

            anim.animate();
        },
        /***
         * Hides the "loading wheel" centered in given el.
         * @param {String|HTMLElement} el Element we'd like to show as "finished" loading. We'll fade in a "bd" element below it.
         * @param {String} (Optional) cName ClassName of Element we'd like to fade back in.
         * @param {Function} cb (Optional) Function we'd like to run after animation completes.
         */
        hideCenteredLoadingIcon : function(el, cName, cb) {
            el = YAHOO.util.Dom.get(el);
            if(! cName) {
                cName = 'bd';
            }

            var bdElement = YAHOO.util.Dom.getElementsByClassName(cName, 'div', el)[0];
            var loadingEl = document.getElementById('loadingIndicator');

            var anim = new YAHOO.util.Anim(bdElement, {
                opacity : { to : 1 }
            },
                    0.35,
                    YAHOO.util.Easing.easeOut);

            anim.onStart.subscribe(function() {
                lAnim = new YAHOO.util.Anim(loadingEl, {
                    opacity : { to : 0 }
                },
                        0.10,
                        YAHOO.util.Easing.easeOut).animate();
            });

            anim.onComplete.subscribe(function() {
                YAHOO.util.Dom.setStyle(bdElement, 'filter', '');
                if(cb) {
                    cb();
                }
                loadingEl.parentNode.removeChild(loadingEl);
            });

            anim.animate();
        },
        /***
         * Init code for binding initial Events, etc.
         *     Pre-selects any products passed along as URL parameters.
         *     Expects "ctc" and "pnbr" parameters to be set with content category and product number, respectivley.
         */
        init : function() {
            var sUrl = window.location.href;
            var that = this;

            dd.onSelectDisplay(function() {
                setTimeout(function() { ArchiveInteractionManager.hideLoadingIndicator('loader_section1') }, 250);
            });


            var catDD = document.getElementById('wtb_categories');
            //reset default value for category drop down.
            if(catDD) {
                catDD.value = "";
                YAHOO.util.Event.addListener(catDD, 'change', function(e, args) {
                    ArchiveInteractionManager.toggleMargin(catDD); //disable go button on change since so it gets disabled when you go backwards in the selection process
                    // We can select one of the "extra" items meant to redirect us in this dropdown,
                    // so we test for it...
                    if(! this.options[this.selectedIndex].getAttribute('data-redirect')) {
                        ArchiveInteractionManager.disableNextButton(); //disable go button on change since so it gets disabled when you go backwards in the selection process
                    }
                }, this);
            }


            if(sUrl.indexOf('ctc') > -1 &&
               sUrl.indexOf('pnbr') > -1) {
                var ctcCode = sUrl.match(/ctc=([A-Z]*)&?/)[1];
                var urlProduct = sUrl.match(/pnbr=([0-9A-Za-z]*)&?/)[1];
                var ccType = null;
                if(sUrl.indexOf('ccType') > 0) {
                    ccType = sUrl.match(/ccType=([\w\+\-]*)&?/)[1].replace(/\+/g, '/');
                }

                // Match the CTC code passed in the URL with the ctc value
                // stored in each option's value attribute.

                for(var i = 0; i < catDD.options.length; i++) {
                    var val = catDD.options[i].value;

                    // Do we have matching values?
                    // If so, load "product" dropdown and selected product
                    if(val.indexOf(ctcCode) > -1) {
                        catDD.selectedIndex = i;
                        dd.managedSelects['wtb_categories'].onSelectChangeEvent.fire()
                        dd.onSelectDisplay(function(type, args, o) {

                            var el = args[1].el;
                            setTimeout(function() {
                                // This gets tricky with color variants.
                                // Basically, we iterate through all the options in the product Select Element.
                                // If it's not a matched value, we see if there's a variant drop down using that Element's value as an ID.
                                // If that Element exists, we see if its options' values match up with the product, and select both items if they do.
                                for(var k = 0; k < el.options.length; k++) {
                                    var val = el.options[k].value
                                    if(val == urlProduct) {
                                        el.selectedIndex = k;
                                        ArchiveInteractionManager.attachNextButtonEvent();
                                        var params = "?action=getProduct&ProductStatus=" + ArchiveInteractionManager.productStatus + "&pid=" + urlProduct;
                                        var cb = {
                                            argument : [that],
                                            success : ArchiveInteractionManager.updateProductInfo,
                                            failure : function(o) {
                                                alert("We've encountered an error retrieving your product. Please try again.");
                                            },
                                            error : function(o) {
                                                alert("We've encountered an error retrieving your product. Please try again.");
                                            }
                                        }
                                        conn = YAHOO.util.Connect.asyncRequest('GET',
                                                ArchiveInteractionManager.ajaxUrl + params, cb);
                                        break;
                                    }
                                    else if(document.getElementById('variant_' + val)) {
                                        var varDD = document.getElementById('variant_' + val);
                                        var matched = false;
                                        for(var l = 0; l < varDD.options.length; l++) {
                                            if(varDD.options[l].value == urlProduct) {
                                                varDD.selectedIndex = l;
                                                el.selectedIndex = k;
                                                matched = true;
                                                dd.managedSelects[el.id].onSelectChangeEvent.fire()
                                                break;
                                            }
                                        }
                                        if(matched) {
                                            break;
                                        }
                                    }
                                }
                            }, 100);
                        });
                    }

                    // Options with second-level category dropdowns will not have a
                    // ctc value. Their values will be in the form of ctc=&cc= ...,
                    // so if their values match the pattern below they fit this criteria.
                    else if(val.match(/ctc=&/)) {
                        var dd_id = catDD.options[i].id;
                        var subCatDD = document.getElementById(dd_id + "_dd");

                        YAHOO.util.Event.addListener(subCatDD, 'change', function(e, args) {
                            ArchiveInteractionManager.toggleMargin(subCatDD); //disable go button on change since so it gets disabled when you go backwards in the selection process
                            ArchiveInteractionManager.disableNextButton(); //disable go button on change since so it gets disabled when you go backwards in the selection process
                        }, this);

                        if(subCatDD) {
                            for(var j = 0; j < subCatDD.options.length; j++) {
                                if(eval('subCatDD.options[' + j + '].value.match(/ctc=' + ctcCode + '&/)')) {
                                    // Select this item in both dropdowns
                                    // and load the appropriate sub-category and product dropdowns.
                                    // Also load appropriate product through a callback.
                                    catDD.selectedIndex = i;
                                    // Need to handle lenses separately...
                                    if(ccType) {
                                        if(subCatDD.options[j].value.match(ccType)) {
                                            subCatDD.selectedIndex = j;
                                        }
                                        else {
                                            continue;
                                        }
                                    }
                                    else {
                                        subCatDD.selectedIndex = j;
                                    }

                                    dd.managedSelects['wtb_categories'].onSelectChangeEvent.fire();

                                    dd.managedSelects[subCatDD.id].onSelectAdd(function(type, args, o) {
                                        var el = args[1].el;
                                        for(var k = 0; k < el.options.length; k++) {
                                            if(el.options[k].value == urlProduct) {
                                                el.selectedIndex = k;
                                                break;
                                            }
                                        }
                                        ArchiveInteractionManager.attachNextButtonEvent();
                                    });
                                    dd.managedSelects[subCatDD.id].onSelectChangeEvent.fire();

                                    var params = "?action=getProduct&ProductStatus=" + ArchiveInteractionManager.productStatus + "&pid=" + urlProduct;
                                    var cb = {
                                        argument : [that],
                                        success : ArchiveInteractionManager.updateProductInfo,
                                        failure : function(o) {
                                            alert("We've encountered an error retrieving your product. Please try again.");
                                        },
                                        error : function(o) {
                                            alert("We've encountered an error retrieving your product. Please try again.");
                                        }
                                    }
                                    conn = YAHOO.util.Connect.asyncRequest('GET',
                                            ArchiveInteractionManager.ajaxUrl + params, cb);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        },
        /***
         * Updates the product displayed on the Where to Buy page.
         * @param {Object} o Reponse object as this function is used as an Ajax callback.
         */
        updateProductInfo : function(o) {
            ArchiveInteractionManager.attachNextButtonEvent();
        },
        testOpenIntvl : null,
        /***
         * Opens the "print-friendly" window.
         */
        openPrintWindow : function() {
            var startPoint = GMapsManager._getCurrentDirections().getGeocode(0);
            var endPoint = GMapsManager._getCurrentDirections().getGeocode(GMapsManager._getCurrentDirections().getNumGeocodes() - 1);

            var retailerName = document.getElementById('retailerName_' + GMapsManager._getCurrentIndex()).innerHTML;
            //var formattedAddress = document.getElementById('formattedAddress_' + GMapsManager._getCurrentIndex()).innerHTML;

            var pWin = window.open('/static/html/wtb_frame.html?start=' +
                                   startPoint.address + '&end=' + endPoint.address + '&retailerName=' + retailerName,
                    'pWin');

            testOpenIntvl = setInterval(function() {
                if(pWin.document && pWin.document.getElementById('body_content')) {
                    clearInterval(testOpenIntvl);
                    var pBody = pWin.document.getElementById('body_content');
                    var baseUrl = document.location.protocol + '//' + document.location.host;

                    var newWinMarkup = '<a class="print none std" href="javascript:window.print()">Print</a><img class="logo" width="82" height="68" src="' + baseUrl + '/static/images/logos/logo_nikon.gif" alt="Nikon - NikonUSA.com"/>' +
                                       '{heroMarkup}' +
                                       '<div class="clear"> </div><div id="container_directions">' +
                                       '<div class="travelInfo"><label><strong>Start:</strong></label><address>{startAddress}</address><div class="clear"> </div>' +
                                       '<label><strong>End:</strong></label><address>{endAddress}</address><div class="clear"> </div>' +
                                       '<label><strong>Travel:</strong></label><span class="travel">{travelInfo}</span><div class="clear"> </div></div>';

                    pBody.innerHTML = newWinMarkup.replace('{heroMarkup}',
                            '<div id="hero" class="hero product wtb">' + document.getElementById('hero').innerHTML + '<div class="mediabar_ft"> </div></div>').replace('{startAddress}',
                            startPoint.address.replace(',', "<br>")).replace('{endAddress}',
                            retailerName + '<br>' + endPoint.address.replace(',', "<br>")).replace('{travelInfo}',
                            GMapsManager._getCurrentDirections().getSummaryHtml());

                    pWin.document.getElementById('swapTarget').src = document.getElementById('swapTarget').src;
                }
            }, 150);
        },
        /***
         * Shows the "Authorized Dealers Disclaimer" pop-up
         */
        showAuthDealers : function() {
            document.getElementById('authDealer_pop').style.left = '438px';
            document.getElementById('authDealer_pop').style.top = '195px';
            YAHOO.util.Event.addListener('authDealer_pop_close', 'click', ArchiveInteractionManager.hideAuthDealers);
        },
        /***
         * Hides the "Authorized Dealers Disclaimer" pop-up
         */
        hideAuthDealers : function() {
            document.getElementById('authDealer_pop').style.left = '-4000px';
        }
    }
}();

/*****
 * obj = { 'sSKU' : "32627", 'sZip' : "10016", 'nRadius' : 10, 'nRGID' : 551 };
 * ArchiveInteractionManager.setRequiredParameters(obj).fetchResults({ success: function(o){ArchiveInteractionManager.xmlTemplate(o.responseXML)}});
 */


/***
 * Utility class for managing expanding/collapsing retailer names.
 */
Expanders = function() {
    return{
        init : function() {
            var that = this;
            var locHeaders = YAHOO.util.Selector.query('div.retailer div.hd');

            YAHOO.util.Dom.batch(locHeaders, function(o) {
                o.style.backgroundColor = 'rgb(247,243,247)';

                YAHOO.util.Event.addListener(o, 'click', function() {
                    that.toggleNode(o, YAHOO.util.Dom.getNextSibling(o));
                    //that.toggleOverlay(nd,nd.id.indexOf('_')+1);
                });
            });
        },
        toggleNode : function(oNode, bNode) {
            var pNode = oNode.parentNode;
            if(YAHOO.util.Dom.hasClass(pNode, 'open')) {
                var a = new YAHOO.util.Anim(bNode, {
                    height : { to : 34 },
                    opacity : { to : 0 }
                },
                        0.15,
                        YAHOO.util.Easing.easeIn);

                var f = function() {
                    new YAHOO.util.ColorAnim(oNode, {
                        backgroundColor : { to : 'rgb(247,243,247)'}
                    },
                            0.15).animate();
                    YAHOO.util.Dom.setStyle(pNode, 'height', '34px');
                    YAHOO.util.Dom.setStyle(bNode, 'height', '0');
                }

                a.onComplete.subscribe(f);
                a.animate();

                YAHOO.util.Dom.addClass(pNode, 'closed');
                YAHOO.util.Dom.removeClass(pNode, 'open');
            }
            else {
                var a = new YAHOO.util.Anim(bNode, {
                    height : { to : 80 },
                    opacity : { from : 0 , to : 0.99 }
                },
                        0.15,
                        YAHOO.util.Easing.easeOut);

                var f = function() {
                    YAHOO.util.Dom.setStyle(pNode, 'height', 'auto');
                    new YAHOO.util.ColorAnim(oNode, {
                        backgroundColor : { to : 'rgb(255,246,191)'}
                    },
                            0.15).animate();
                }

                a.onStart.subscribe(f);
                a.animate();

                YAHOO.util.Dom.addClass(pNode, 'open');
                YAHOO.util.Dom.removeClass(pNode, 'closed');
            }
        }
    }
}();

