var generic = generic || {};
var bb = bb || {};

bb.productView = bb.productView || {}
bb.productView.mpp = bb.productView.mpp || {}
bb.productView.mpp.hasPageControls = false;

// TODO: replace with actual RB
bb.rb = bb.rb || {}
bb.rb.product = new Hash({});

bb.mpp = function () {
    var tableContainerNode, pagingContainerNode;
    var productsDataArray = [];
    var isFranchiseCategory = false;

    // the following are common in BrX but not implemented in BB JP:
    var tableContainerNodeName = "products_container"; // "products-grid-container"
    var pagingContainerNodeName = "paging-controls-container"; // "paging-controls-container";

    var self;

    //
    // define filter fields and menu labels for different categories
    // BB JP does not implement category filters
    var categoryFilterMenus = new Hash({
    });

    var that = bb.productView.filterTable();

    that.init = function(mppData) {
        self = this;
        pagingContainerNode = pagingContainerNodeName ? $$("#" + pagingContainerNodeName)[0] : null;
        tableContainerNode  = tableContainerNodeName  ? $$("#" + tableContainerNodeName)[0]  : null;

        productsDataArray = this.sortProducts(mppData.products);
        productsDataArray.each(function(item){
            item.display = true;
        });

        // Sets the proper category in the global nav to 'on'.
        var global_cat = generic.page_data("global_cat").get("global_cat");
        bb.page.setGlobalCat(global_cat)

        // Franchise are What's New categories have a different page layout
        isFranchiseCategory = mppData.isFranchiseCategory ? 1 : 0

        //
        // start filter & sort logic. This should remain on JS side
        var filtersContainerNode = $('filter-toolbar');
        var hideFilters = true;
        
        if (Object.isElement(filtersContainerNode)) {
            // BB JP does not implement filtering and sorting.
        }

        this.renderTable();
    };

    /**
     * This method provides a hook for the bb.filter class. It is called
     * after that class filters & sorts the data.
     * @methodOf bb.mpp
     */
    that.build = function(filteredData) {
        productsDataArray = filteredData;
        this.renderTable();
    }

    that.renderTable = function() {
        // display property will be toggled when the table is filtered or sorted
        var filteredProducts = productsDataArray.select( function(p) {
            return p.display;
        });

        // BB JP: display only shoppable products
        //filteredProducts  = filteredProducts.findAll(function(p){
        //    return p.isShoppable;
        //});

        if (tableContainerNode) {
            tableContainerNode.update();
        }
        
        if (isFranchiseCategory) {
            this.renderFranchiseTable(filteredProducts);
        }
        else {
            this.renderCommonTable(filteredProducts);
        }

        // pagination controls
        // BB JP does not implement pagination
        if (bb.productView.mpp.hasPageControls) {
            this.renderPageControls({
                productData: filteredProducts,
                startIndex: startIndex,
                maxItems: maxItems
            });
        }
    }

    that.renderCommonTable = function(filteredProducts) {
        // BB MPP logic
        // First row has three products and 'quote' image
        // Remaining products are arrayed in rows of four products per row.
        var productsPerFirstRow = 3;
        var productsPerCommonRow   = 4;

        // hide featured container
        $$(".franchise_area")[0].setStyle({display:"none"});

        var containerNode = $$(".whatsnew-area")[0]; // "common-product-row"
        var rowOuterContainer = $$(".products_block")[0];        
        var rowInnerContainer = new Element("div", {"class":"content products"});
        rowOuterContainer.insert(rowInnerContainer);

        var rowIndex = 0;
        var featuredRowProductsLength = (filteredProducts.length < productsPerFirstRow) ? filteredProducts.length : productsPerFirstRow;
        var featuredRowProducts = filteredProducts.splice(0,featuredRowProductsLength);

        rowIndex++;
        for (var i=0, len=featuredRowProducts.length; i<len; ++i) {
            var productData = featuredRowProducts[i];            
            this.loadProducts(productData, rowInnerContainer);
        }

        // process remaining products as standard rows
        for (var i=0, len=filteredProducts.length; i<len; ++i) {
            if ((i % 4) === 0) {
                // make new row
                rowOuterContainer = new Element("div", {"class":"whatsnew-block", style:"visibility:hidden"});
                rowInnerContainer = new Element("div", {"class":"content products"});
                rowOuterContainer.insert(rowInnerContainer);
                containerNode.insert(rowOuterContainer);
            }
            var productData = filteredProducts[i];
            this.loadProducts(productData, rowInnerContainer);
        }

        // handle the category-specific Quote image
        if (window.CATEGORY_ID && window.CATEGORY_ID.length > 0) {
            var quoteContainerNode = $$("div.products_area div.quote")[0];
            if (quoteContainerNode) {
                var catBaseID = window.CATEGORY_ID.substring(3, window.CATEGORY_ID.length);
                var quoteImgSrc  = "/images/products/quotes/" + catBaseID + ".gif";
                var quoteImgNode = new Element("img", {src: quoteImgSrc});
                quoteContainerNode.update(quoteImgNode); // replace
            }
        }

        // show the resulting page
        this.displayProducts();
    }

    that.renderFranchiseTable = function(filteredProducts) {
        var productsPerCommonRow = 4;

        var containerNode = $$(".whatsnew-area")[0]; // "common-product-row"

        // all rows will be inserted into the DOM
        var rowOuterContainer = null;
        var rowInnerContainer = null;

        for (var i=0, len=filteredProducts.length; i<len; ++i) {
            // new row condition
            if ((i % 4) === 0) {
                rowOuterContainer = new Element("div", {"class":"whatsnew-block", style:"visibility:hidden"});
                rowInnerContainer = new Element("div", {"class":"content products"});

                // first row exception: insert page-spanning row for cat header image
                if (i < 4) {
                    var headerContainer = new Element("div", {"class":"header-block"});
                    rowInnerContainer.insert(headerContainer);
                }

                rowOuterContainer.insert(rowInnerContainer);
                containerNode.insert(rowOuterContainer);
            }
            var productData = filteredProducts[i];
            this.loadProducts(productData, rowInnerContainer);
        }

        // handle the category-specific Quote and header image
        if (window.CATEGORY_ID && window.CATEGORY_ID.length > 0) {
            // hide quote
            $$("div.products_area div.quote")[0].setStyle({display:"none"});
            $$(".products_area")[0].setStyle({background:"none", margin:"0", padding:"0"});

            // top merch window
            var franchiseContainerNode = $$(".franchise_area")[0];
            var catBaseID = window.CATEGORY_ID.substring(3, window.CATEGORY_ID.length);

            if (franchiseContainerNode) {
                var imgSrc = "/images/products/collections/imgs/" + catBaseID + ".jpg";
                var img = new Element("img", {src: imgSrc});
                franchiseContainerNode.update(img);

                var linksArray = null;
                if (linksArray) {
                    linksArray.each(function(link){
                        var styleString = "top:" + link.top + "px; left:" + link.left + "px;";
                        var linkElement = new Element("a", {
                            href    : link.href,
                            "style" : styleString,
                            "class" : "franchise-image-link"
                        });
                        styleString = "width:" + link.width + "px; height:" + link.height + "px;";
                        var imgElement = new Element("img", {
                            src     : "/images/global/transparent.gif",
                            "style" : styleString
                        });
                        franchiseContainerNode.insert(linkElement);
                        linkElement.update(imageElement);
                    });
                }
            }
            
            // category header
            var franchiseHeaderNode = $$(".header-block")[0];
            if (franchiseHeaderNode) {
                var categoryDisplayName = null;
                var imgSrc = "/images/products/collections/headers/" + catBaseID + ".gif";
                var img = new Element("img", {src: imgSrc});
                franchiseHeaderNode.update(img);
            }
        }

        // show the resulting page
        this.displayProducts();
    }

    that.loadProducts = function(productData, rowInnerContainer) {

        // 1. Augment the productData structure if necessary

        // BRX: fetch the template for an LI for each product
        // here we perform the same logical task but using a different
        // containing block structure
        var templt_args = {};

        templt_args.ratingReviewString = productData.TOTAL_REVIEW_COUNT > 1 ? 'reviews' : 'review';
        templt_args.ratingDisplay = typeof productData.AVERAGE_RATING == 'number' && isFinite(productData.AVERAGE_RATING) ? 'block' : 'none';
        templt_args.ratingRounded = Math.round(productData.AVERAGE_RATING*10)/10;

        Object.extend(productData, templt_args);

        generic.templatefactory.get({path: '/templates/products/product_thumb.tmpl'}).evaluateCallback({
            object: productData,
            callback: function(container, productData, html) {
                var thumbNode = new Element("div");
                container.insert(thumbNode);
                thumbNode.insert(html);
                that.initProductThumb({
                    thumbNode: thumbNode,
                    productData: productData
                });
                var parentContainerNode = container.parentNode;
                $(parentContainerNode).setStyle({visibility: "visible"});
            }.curry(rowInnerContainer, productData)
        });

    };

    that.sortProducts = function(products) {
        var productsDataArray = products;

        productsDataArray = productsDataArray.sortBy(function(productData){
            return productData.PROD_CAT_DISPLAY_ORDER;
        });

        return productsDataArray;

    }

    that.displayProducts = function() {
        // once the product table is constructed...
        $$(".loading-container")[0].style.display = "none";
        var productAreaArray = [$$(".products_area")[0], $$(".whatsnew-area")[0], $$(".sec_content")[0], $$(".products_container")[0]];
        productAreaArray.each(function(s){
            s.setStyle({display:"block"});
        });
    }

    that.initProductThumb = function (args) {

        // Note: truncated short-description provided by back-end
        var calloutContainer = args.thumbNode.select('.callout')[0];
        if (calloutContainer) {
            bb.productView.setCallout(calloutContainer, args.productData);
        }

        var quickshopLinkNode = args.thumbNode.select('a.open-product-1')[0];
        bb.productView.initQuickshopLink(quickshopLinkNode, args.productData);

        //
        // TO DO: Bobbi Features
        // render attributes (Coverage, Skin Types, Benefits, etc)
        var attrContainer = args.thumbNode.select('.attributes')[0];
        if (attrContainer) {
            this.displayAttributes({
                containerNode : attrContainer,
                productData   : args.productData
            });
        }

        // render product price
        var priceContainer = args.thumbNode.select('.price')[0];
        if (priceContainer) {
        	var price = bb.productView.formatPriceRange(args.productData);
        	priceContainer.update(price)
        }
    };

    /* Not needed for BB JP: for reference only */
    that.renderPageControls = function(args) {
        var totalProducts = args.productData.length;
        var rangeEnd = args.startIndex + args.maxItems;
        if (rangeEnd > totalProducts) {
            rangeEnd = totalProducts;
        }
        var range = (args.startIndex + 1) + " - " + rangeEnd;
        //
        // create links to pages
        var pageNumber = 1;
        var pageLinks = [];
        for (var i=0; i< totalProducts; i++) {
            if (i % defaultMaxItems === 0) {
                var link = new Element("a", {
                    href:"#"
                });
                if ( (maxItems <= defaultMaxItems) && // if we are not showing All Items
                        (i == args.startIndex) ) { // if this is the current page number
                    link = new Element("span"); // use SPAN instead of A
                }
                link.className += " start-" + i;
                link.insert(pageNumber);
                pageNumber++;
                pageLinks.push(link);
            }
        }
        generic.templatefactory.get({path: '/templates/products/mpp-paging-controls.tmpl'}).evaluateCallback({
            object: {
                totalProducts: totalProducts,
                range: range
            },
            callback: function(html) {
                pagingContainerNode.update(html);
                var linksContainer = pagingContainerNode.select("span#page-links")[0];
                pageLinks.each( function (link) {
                    linksContainer.insert(" ");
                    linksContainer.insert(link);
                    if (link.tagName.toLowerCase() === "a") {
                        link.observe("click", function(e) {
                            var reResults = e.target.className.match(/start\-(\d)+/);
                            if (Object.isArray(reResults)) {
                                maxItems = defaultMaxItems;
                                startIndex = parseInt(reResults[1]);
                                self.renderTable();
                            }
                        });
                    }
                }); // end pageLinks.each()
                var viewAllLinkNode = pagingContainerNode.select("a#view-all-link")[0];
                if (viewAllLinkNode) {
                    viewAllLinkNode.observe("click", function(e) {
                        maxItems = totalProducts;
                        startIndex = 0;
                        self.renderTable();
                    });
                }
            } // end callback
        }); // end generic.templatefactory.get() 
        
    };
    /**
     * This method determines which optional attribute fields are present in a product data object.
     * It then renders a UL that contains those field values along with labels and drops that UL
     * into a container node that it receives as a parameter.
     * The fields which get selected as attributes can be modified in the "fields" array
     * @param {Node} args.containerNode the node into which the UL will be inserted
     * @param {Object} productData JSON-formatted data that contains product information.
     */
    that.displayAttributes = function(args) {
        if (!args.containerNode) { 
            return;
        }
        var p = args.productData;
        var fields = [
            { label: bb.rb.product.get('Formula'), field: p.FORMULA },
            { label: bb.rb.product.get('Coverage'), field: p.ATTRIBUTE_COVERAGE },
            { label: bb.rb.product.get('Benefits'), field: p.ATTRIBUTE_BENEFIT },
            { label: bb.rb.product.get('Concern'), field: p.SKIN_CONCERN_LABEL }
        ];
        var ul = new Element('ul', {'class':'attributes'});
        args.containerNode.update(ul);
        for (var i=0, len=fields.length; i<len; i++) {
            if (fields[i].field && fields[i].field.length > 0) {
                var strEle = new Element('strong').update(fields[i].label + ': ');
                var li = new Element('li').update(strEle);
                li.insert(fields[i].field);
                ul.insert(li);
            }
        }
    };

    // default product catalog rpc fields
    that.mppParams = {
        categoryFields: {
            categoryFields : ["CATEGORY_ID", "CAT_BASE_ID", "CATEGORY_NAME", "products"]
        },
        productFields: {
            productFields : ["PRODUCT_ID", "PROD_BASE_ID", "DEFAULT_CAT_ID", "PARENT_CAT_ID", "PROD_RGN_NAME", "PROD_RGN_SUBHEADING", "SUB_LINE", "DESCRIPTION", "SHORT_DESCRIPTION", "PROD_SKIN_TYPE", "PROD_SKIN_TYPE_TEXT", "PROD_CAT_IMAGE_NAME", "PROD_CAT_DISPLAY_ORDER", "SMALL_IMAGE", "LARGE_IMAGE", "THUMBNAIL_IMAGE", "PRODUCT_USAGE", "ATTRIBUTE_FORM", "displayName", "skus", "palette", "shaded", "sized", "url"]
        },
        skuFields: {
            skuFields : ["SKU_ID", "SKU_BASE_ID", "PRODUCT_ID", "SHADENAME", "SHADE_DESCRIPTION", "DISPLAY_ORDER", "SKIN_TYPE", "SKIN_TYPE_TEXT", "PRODUCT_SIZE", "STRENGTH", "PRICE", "formattedPrice", "formattedTaxedPrice", "INVENTORY_STATUS", "SMOOSH_DESIGN", "SMOOSH_PATH_STRING", "REFILLABLE", "HEX_VALUE", "HEX_VALUE_STRING", "FINISH", "LIFE_OF_PRODUCT", "COLORGROUPING"]
        }
    };

    return that;    
}();

document.observe("dom:loaded", function() {
    $$('.products_block')[0].update(''); 

    // load data from either page_data or AJAX
    // 1. Set up the product catalog fetch parameters
    var productDataParams = {};
    productDataParams.pageDataKey = 'catalog.mpp';
    productDataParams.categoryId = window.CATEGORY_ID;
    productDataParams.callback = function(mppData) {
        // pass category and products to multiple product filter view
        bb.mpp.init(mppData);
    };
    // obtain the fields from the page_data resource otherwise use a hardcoded default
    bb.mpp.page_data_configuration = generic.rb("page_data_configuration");
    if (bb.mpp.page_data_configuration.get("catalog.mpp.categoryFields") != 'catalog.mpp.categoryFields') {
        productDataParams.categoryFields = bb.mpp.page_data_configuration.get("catalog.mpp.categoryFields");
        productDataParams.productFields = bb.mpp.page_data_configuration.get("catalog.mpp.productFields");
        productDataParams.skuFields = bb.mpp.page_data_configuration.get("catalog.mpp.skuFields");
    }
    else {
        productDataParams = Object.extend ( productDataParams, bb.mpp.mppParams.categoryFields );
        productDataParams = Object.extend ( productDataParams, bb.mpp.mppParams.productFields );
        productDataParams = Object.extend ( productDataParams, bb.mpp.mppParams.skuFields );
    }

    // 2. Obtain the data
    generic.productData.getCategoryData(productDataParams);
});
//
//document.observe('cart:updated', function(e) {
//    alert(e.memo.ac_results[0].result.CARTITEM["prod.PROD_RGN_NAME"] + " added to cart.");
//});

// 
// document.observe("mpp-product-thumb:rendered", function (e) {
//     bb.mpp.initProductThumb(e.memo);    
// });
