/***
 * A "manager" module that handles interaction with the accoridon widget on "Template Q"-style pages.
 *
 * @author Adam J. McIntyre
 */

AccordionManager = function() {
    var PRODUCT_ROW_CHARS = 90;
    var pageLink = '/';
    var currentEl = null;

    return{
        setUrlPrefix : function(p) { pageLink = p; },
        formatter : function(eName, args) {
            var targetNode = YAHOO.util.Dom.getFirstChild(args[0]);    // Args[0] = div we'll append to
            var response = args[1].responseXML;    // Args[1] = response object
            var that = arguments[2];    // We pass in a reference to this object in our event sub function

            var pList = document.createElement('ol');
            pList.className = 'products';

            var template = '<li id="row_product_{productId}" class="row {evenOdd}"><div class="container_new {isNew}">&nbsp;</div>' +
                           '<div class="container_l"><a href="{productUrl}" class="none"><img class="list_product" width="47" height="40" src="{productImage}"/></a></div>' +
                           '<h4><a href="{productUrl}" class="none">{productName}</a></h4><h5><a href="{productUrl}" class="none">{productDesc}</a></h5>' +
                           '<div class="container_r"><a id="link_{productId}" href="javascript:void(0);" onclick="AccordionManager.showQuickView(event,\'{productId}\')">' + nikon.utils.locale.get("Global.QuickView") + '</a>' +
                           '<div id="quickView_data_{productId}" class="noD">' +
                           '<div class="hd"><a class="closeIcon" href="javascript:AccordionManager.hideQuickView()">&nbsp;</a>' +
                           '<h3 class="nkYellow">{productName}</h3></div>' +
                           '<div class="bd"><div class="shim"> </div>' +
                           '<a href="{productUrl}" id="data_url_{productId}" class="none">' +
                           '<img width="160" height="136" src="{productImage}" alt="{productName}" id="item_{productId}_img" class="pop"/></a>' +
                           '<div class="col"><div id="data_bullets_{productId}">{productBullets}</div>' +
                           '<strong id="data_price_{productId}" class="shift">{productPrice}</strong></div><div class="clear"> </div></div>' +
                           '<a href="{productUrl}" class="more">' + nikon.utils.locale.get("Global.Labels.findOutMore") + '</a><div class="ft">&nbsp;</div></div>' +
                           '</div></li>';

            var products = response.getElementsByTagName('Product');
            var tmpHtml = '';

            for(var i = 0; i < products.length; i++) {
                var p = products[i];
                var evenOdd, isNew, productId, productImage, productName, productDesc;

                // Set up templated content
                if(i % 2 == 0) {
                    evenOdd = 'even';
                }
                else {
                    evenOdd = 'odd';
                }

                // Additional styling for the last item in the product list
                if(i == products.length - 1) {
                    evenOdd += ' last';
                }

                // Should we use IE or W3C methods for retrieving text content from these nodes?
                if('text' in p.getElementsByTagName('Image')[0]) {   // IE
                    if(p.getAttribute('New') == 'true') {
                        isNew = 'is_new';
                    }
                    else {
                        isNew = '';
                    }
                    productId = p.getAttribute('ProductId');

                    // Need to adapt Image to fit conventions
                    var imgText = p.getElementsByTagName('Image')[0].text;
                    productImage = imgText.substr(0,
                            imgText.lastIndexOf(productId)) + '160_' + imgText.substr(imgText.lastIndexOf(productId));
                    productName = p.getElementsByTagName('Title')[0].text;
                    productDesc = that._formatDescriptionText(productName, p.getElementsByTagName('Overview')[0].text);
                    productBullets = p.getElementsByTagName('Bullets')[0].text;
                    productPrice = that._formatPriceText(p.getElementsByTagName('Price')[0].text,
                            p.getElementsByTagName('ReducedPrice'), p.getAttribute('Reduced'), true);
                    productUrl = that._formatUrl(p.getElementsByTagName('URL')[0].text,
                            p.getElementsByTagName('QueryString'), p.getElementsByTagName('isProduction'), true);
                }
                else {   // Everyone else
                    if(p.getAttribute('New') == 'true') {
                        isNew = 'is_new';
                    }
                    else {
                        isNew = '';
                    }

                    productId = p.getAttribute('ProductId');

                    // Need to adapt Image to fit conventions
                    var imgText = p.getElementsByTagName('Image')[0].textContent;

                    productImage = imgText.substr(0,
                            imgText.lastIndexOf(productId)) + '160_' + imgText.substr(imgText.lastIndexOf(productId));
                    productName = p.getElementsByTagName('Title')[0].textContent;
                    productDesc = that._formatDescriptionText(productName,
                            p.getElementsByTagName('Overview')[0].textContent);
                    productBullets = p.getElementsByTagName('Bullets')[0].textContent;
                    productPrice = that._formatPriceText(p.getElementsByTagName('Price')[0].textContent,
                            p.getElementsByTagName('ReducedPrice'), p.getAttribute('Reduced'), false);
                    productUrl = that._formatUrl(p.getElementsByTagName('URL')[0].textContent,
                            p.getElementsByTagName('QueryString'), p.getElementsByTagName('isProduction'), false);
                }
                tmpHtml += template.replace('{evenOdd}', evenOdd)
                        .replace(/{productId}/g, productId)
                        .replace('{isNew}', isNew)
                        .replace(/{productImage}/g, productImage)
                        .replace(/{productName}/g, productName)
                        .replace('{productDesc}', productDesc)
                        .replace('{productBullets}', productBullets)
                        .replace(/{productPrice}/g, productPrice)
                        .replace(/{productUrl}/g, productUrl);
            }
            pList.innerHTML = tmpHtml;
            targetNode.appendChild(pList);
        },
        /***
         * Formats a product's description text, stripping out HTML characters and truncating it
         * where appropriate.
         * @param {String} name Product's name.
         * @param {String} desc Product's description.
         */
        _formatDescriptionText : function(name, desc) {
            var remainingChars = PRODUCT_ROW_CHARS - name.length;

            // Strip out any HTML tags
            var strippedHtml = desc.replace(/<(.|\n)*?>/ig, '');

            if(strippedHtml.length >= remainingChars) {
                return strippedHtml.substr(0, remainingChars - 3) + '...';
            }
            else {
                return strippedHtml;
            }
        },
        /***
         * Shows the "Quick View" panel with the markup associated with the product
         * whose ProductId == id.
         * @param {String} e Event that triggered this function call.
         * @param {String} id ID of product we'd like to show in Quick View.
         */
        showQuickView : function(e, id) {
            if(! e) {
                e = window.event;
            }
            YAHOO.util.Event.preventDefault(e);
            YAHOO.util.Event.stopPropagation(e);

            var y = YAHOO.util.Event.getPageY(e);

            // Hide the quickview element off the page, just in case it's displayed
            var qv = document.getElementById('quickView');
            this.hideQuickView();

            // Set quickview's HTML to selected product's
            qv.innerHTML = document.getElementById('quickView_data_' + id).innerHTML;

            // Truncate title, if necessary. We use a 25-character hard limit.
            var el = YAHOO.util.Selector.query('div.hd h3', 'quickView', true);
            if(el.innerHTML.length > 25) {
                el.innerHTML = el.innerHTML.substr(0, 25) + '&hellip;'
            }

            // Set quickview's XY position to match the clicked link.
            var linkEl = document.getElementById('link_' + id)
            var x = YAHOO.util.Dom.getX(linkEl);

            // Set the y coordinate using the following rule:
            // --If flyout would appear off bottom of page, shift it up (not currently the case)
            var yPos = y;

            if(yPos + qv.offsetHeight > YAHOO.util.Dom.getClientRegion().bottom) {
                yPos = yPos - qv.offsetHeight + linkEl.offsetHeight
            }
            YAHOO.util.Dom.setY(qv, yPos);    // Shift up appropriately so we're above link
            YAHOO.util.Dom.setX(qv, x - qv.offsetWidth);
        },
        /***
         * Hides the "Quick View" panel by placing it off the left side of the screen.
         */
        hideQuickView : function() {
            YAHOO.util.Dom.setStyle('quickView', 'left', '-4000px');
        },
        /***
         * Formats a product's price text, taking into account whether or not that product is reduced.
         * @param {String} p Value of Product's Price element.
         * @param {Array} reducedPrice Value of  Product's ReducedPrice element.
         * @param {String} isReduced Value of product's "Reduced" attribute.
         * @param {Boolean} isIE Flag for whether browser is IE and we need to use "text" or "textContent."
         */
        _formatPriceText : function(price, reducedPrice, isReduced, isIE) {
            if(reducedPrice.length > 0) {
                if(isIE) {
                    var rp = reducedPrice[0].text;
                }
                else {
                    var rp = reducedPrice[0].textContent;
                }

                if(isReduced) {
                    if(rp.length > 0) {
                        return 'Now: $' + rp;
                    }
                    else {
                        return "";
                    }
                }
                else {
                    if(rp.length > 0) {
                        return 'Price: $' + rp;
                    }
                    else {
                        return "";
                    }
                }
            }
            else {
                if(price.length > 0) {
                    return 'Price: $' + price;
                }
                else {
                    return "";
                }
            }
        },
        /***
         * Formats a product's URL, depending on whether or not the current environment is Production.
         * @param {String} u Value of Product's URL element.
         * @param {String} q Value of Product's QueryString element.
         * @param {String} isProduction Value of Product's isProduction element.
         * @param {Boolean} isIE Flag for whether browser is IE and we need to use "text" or "textContent."
         */
        _formatUrl : function(u, q, isProduction, isIE) {
            var qs = "";
            // We may need to do a bit of formatting in this case:
            // If pageLink is set to the root ("/"), we need to make sure that the first character
            // of u is not also "/". If it is and we don't chop it, we'll create malformed URLs.
            if(u.indexOf('/') == 0) {
                u = u.substr(1);
            }

            if(q.length > 0) {
                if(isIE) {
                    qs = q[0].text;
                }
                else {
                    qs = q[0].textContent;
                }
            }
            if(isProduction.length > 0) {
                if(isIE) {
                    if(isProduction[0].text) {
                        return pageLink + u;
                    }
                    else {
                        return pageLink + u + '?' + qs;
                    }
                }
                else {
                    if(isProduction[0].textContent) {
                        return pageLink + u;
                    }
                    else {
                        return pageLink + u + '?' + qs;
                    }
                }
            }
            else {
                return pageLink + u;
            }
        },
        /***
         * Handles showing a "loading" icon while the accordion fetches data
         * @param {String} type Type of Event calling this function
         * @param {Array} args Array of arguments passed by Event triggering this function call
         */
        handleBeforeDataLoad : function(type, args) {
            var hd = args[1];

            if(YAHOO.util.Dom.hasClass(hd.parentNode, 'remote') && ! YAHOO.util.Dom.hasClass(hd.parentNode, 'loaded')) {
                var loadingDiv = YAHOO.util.Dom.getElementsByClassName('loading', 'div', hd)[0];
                var productName = hd.parentNode.getElementsByTagName('h2')[0].innerHTML;

                YAHOO.util.Dom.addClass(hd, 'opening');
                loadingDiv.innerHTML = '<label>' + nikon.utils.locale.get("Global.Loading") + ' ' + productName + ' ' + nikon.utils.locale.get("Global.Labels.products") + '</label> <img src="/static/images/icons/icon_loadingBar_trans.gif" width="170" height="19" alt="' + nikon.utils.locale.get("Global.Loading") + '..."/>';
            }
        },
        /***
         * Handles hiding a "loading" icon after the accordion fetches data
         * @param {String} type Type of Event calling this function
         * @param {Array} args Array of arguments passed by Event triggering this function call
         */
        handleAfterDataLoad : function(type, args) {
            var hd = args[1];

            if(YAHOO.util.Dom.hasClass(hd.parentNode, 'remote') &&
               YAHOO.util.Dom.getElementsByClassName('loading', 'div', hd).length > 0) {
                var loadingDiv = YAHOO.util.Dom.getElementsByClassName('loading', 'div', hd)[0];

                setTimeout(function() {
                    var anim = new YAHOO.util.Anim(loadingDiv, {
                        height: {
                            to: 0
                        },
                        opacity: {
                            to: 0
                        }
                    }, 0.15);
                    anim.onStart.subscribe(function() {
                        var ht = YAHOO.util.Dom.getStyle(hd, 'height').substr(0,
                                YAHOO.util.Dom.getStyle(hd, 'height').indexOf('px'))
                        new YAHOO.util.Anim(hd, {
                            height: {
                                to: (ht - loadingDiv.offsetHeight)
                            }
                        }, 0.15).animate();
                    });

                    anim.onComplete.subscribe(function() {
                        YAHOO.util.Dom.removeClass(hd, 'opening');
                        loadingDiv.parentNode.removeChild(loadingDiv);
                        var pEl = hd.parentNode;
                        if(YAHOO.util.Dom.hasClass(pEl, 'last')) {
                            YAHOO.util.Dom.addClass(pEl, 'last_open');
                            currentEl = pEl;
                        }
                        else {
                            currentEl = null;
                        }
                    });
                    anim.animate();
                }, 250);
            }
            else {
                var pEl = hd.parentNode;
                if(YAHOO.util.Dom.hasClass(pEl, 'last')) {
                    YAHOO.util.Dom.addClass(pEl, 'last_open');
                    currentEl = pEl;
                }
                else {
                    currentEl = null;
                }
            }
        },
        /***
         * Handles a "show all" click.
         * @param {String} type Type of Event calling this function
         * @param {Array} args Array of arguments passed by Event triggering this function call
         */
        handleShowAll : function(type, args) {
            document.getElementById('viewAll').onclick = function() {
                acc.hideAll();
            };
            document.getElementById('viewAll_text').innerHTML = nikon.utils.locale.get("Global.HideAll");
            document.getElementById('viewAll_toggle').src = "/static/images/icons/sro/icon_accClose_lt.gif";
        },
        /***
         * Handles a "hide all" click.
         * @param {String} type Type of Event calling this function
         * @param {Array} args Array of arguments passed by Event triggering this function call
         */
        handleHideAll : function(type, args) {
            document.getElementById('viewAll').onclick = function() {
                acc.showAll();
            }
            document.getElementById('viewAll_text').innerHTML = nikon.utils.locale.get("Global.Labels.viewAll");
            document.getElementById('viewAll_toggle').src = "/static/images/icons/sro/icon_accOpen.gif";
        },
        /***
         * Handles a "click" event on a product list-item, essentially just making the whole thing
         * one big link to a product page.
         * @param {Event} e Event that triggered this call.
         */
        handleElClick : function(e) {
            YAHOO.util.Event.stopPropagation(e);
            var linkEl = YAHOO.util.Selector.query('div.container_r div a.more', this, true);

            if(linkEl) {
                window.location.href = linkEl.getAttribute('href');
            }
            else {    // Handle multiple monarch sub-categories separately
                linkEl = YAHOO.util.Selector.query('a.catLink', this, true);
                if(linkEl) {
                    window.location.href = linkEl.getAttribute('href');
                }
            }
        }
    }
}();

