var formatDate = function (formatDate, formatString) {
	if(formatDate instanceof Date) {
		var months = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
		var yyyy    = formatDate.getFullYear();
		var yy      = yyyy.toString().substring(2);
		var m       = formatDate.getMonth();
		var mm      = m < 10 ? "0" + m : m;
		var mmm     = months[m];
		var d       = formatDate.getDate();
		var dd      = d < 10 ? "0" + d : d;
		
		var h       = formatDate.getHours();
		var hh      = h < 10 ? "0" + h : h;
		var n       = formatDate.getMinutes();
		var nn      = n < 10 ? "0" + n : n;
		var s       = formatDate.getSeconds();
		var ss      = s < 10 ? "0" + s : s;

		formatString = formatString.replace(/yyyy/i, yyyy);
		formatString = formatString.replace(/yy/i, yy);
		formatString = formatString.replace(/mmm/i, mmm);
		formatString = formatString.replace(/mm/i, mm);
		formatString = formatString.replace(/m/i, m);
		formatString = formatString.replace(/dd/i, dd);
		formatString = formatString.replace(/d/i, d);
		formatString = formatString.replace(/hh/i, hh);
		formatString = formatString.replace(/h/i, h);
		formatString = formatString.replace(/nn/i, nn);
		formatString = formatString.replace(/n/i, n);
		formatString = formatString.replace(/ss/i, ss);
		formatString = formatString.replace(/s/i, s);

		return formatString;
	} else {
		return "";
	}
}

var ProductCompare = {
    cookieName          : 'js_comparisonStack',
    comparisonStacks    : {},
    maxStackLength      : 3,
    activeStack         : null,
    popupContainerId    : 'popup_content',
    popupBackgroundId   : 'popup_background',
    messages: {
        alert: {
            fullStack:  'Je kunt niet meer dan 3 producten met elkaar vergelijken'
        }
    },
    
    initialize: function(eventObject){
        // check if there needs to be an abort
        var IE6Detected = ProductCompare.__detectIE6(eventObject);
        if (IE6Detected) {
            return false;
        }
        
        // adding and removing items from popup
        ProductCompare.observees = $$('.productComparisonButtons[productId][compareStack] .addToComparisonList');
        
        // we NEED to have a comparestack available
        ProductCompare.observees.reject(function(element){
            var buttonWrapper     = element.up('.productComparisonButtons');
            var hasCompareStack   = buttonWrapper.readAttribute('compareStack')
                ? true
                : false;
            if (!hasCompareStack) {
                buttonWrapper.hide();
            }
            return hasCompareStack;
        });
        
        ProductCompare.observees.invoke('observe', 'click', ProductCompare._events.toggleCompareState);
        ECube.d.log(1, 'ProductCompare: attached observers on:', ProductCompare.observees);
        
        if ($(ProductCompare.popupContainerId) && $(ProductCompare.popupBackgroundId)){
            // ensuring that at least the popup background will close the popup
            $(ProductCompare.popupBackgroundId).addClassName('hideComparison');
        
            // showing and hiding the popup
            $$('.showComparison').invoke('observe', 'click', ProductCompare._events.showPopup);
            $$('.hideComparison').invoke('observe', 'click', ProductCompare._events.hidePopup);
        }
        
        ProductCompare._getComparisonStacks();
    },
    
    // adds a productNo to a comparisonTypeID stack
    storeProduct: function(productNo, comparisonTypeID) {
        ECube.d.log(3, 'ProductCompare: Storing Product: ', productNo, ' of stack: ', comparisonTypeID);
        
        var recalcActiveStack = false;
        var storedTheProduct = false;
        
        // check if the stack allready exists
        if (!ProductCompare.comparisonStacks[comparisonTypeID]){
            ProductCompare.comparisonStacks[comparisonTypeID] = {
                products: []
                };
            recalcActiveStack = true;
        }
        
        // check if the productNo isn't allready in the stack
        if (ProductCompare.comparisonStacks[comparisonTypeID].products.find(function(product){
            return (product.productNo == productNo);
            })) {
            ECube.d.log(0, 'ProductCompare: productNo allready in comparestack!');
            return false;
        };
        
        // if there's still room for more products in the comparisonstack
        if (ProductCompare.comparisonStacks[comparisonTypeID].products.length <
            ProductCompare.maxStackLength){
            
            var now = new Date();
            ProductCompare.comparisonStacks[comparisonTypeID].products.push({
                productNo       : productNo,
                dtsLastModified : formatDate(now, "yyyymmdd.hhnnss")
            });
            
            storedTheProduct = true;
            
            ProductCompare.comparisonStacks[comparisonTypeID].dtsLastModified =
                formatDate(now, "yyyymmdd.hhnnss");
                
            ProductCompare.updatePopupLinks();
            ProductCompare._saveComparisonStacks();
        }
        // the stack appears to be full
        else {
            alert(ProductCompare.messages.alert.fullStack);
        }
        
        if (recalcActiveStack) {
            ProductCompare.determineActiveStack();
        }
        
        return storedTheProduct;
    },
    
    // removes a productNo from a comparisonTypeID stack
    deleteProduct: function(productNo, comparisonTypeID) {
        ECube.d.log(3, 'ProductCompare: Deleting Product: ', productNo, ' of stack: ', comparisonTypeID);
        
        ProductCompare.comparisonStacks[comparisonTypeID].products =
            ProductCompare.comparisonStacks[comparisonTypeID].products.reject(function(product){
            return (product.productNo == productNo);
        });
        
        // if there are no more items in the comparestack, we need to remove the
        // comparison from the comparestacks and re-evaluate
        // the stacklists for another active comparison 
        if (!ProductCompare.comparisonStacks[comparisonTypeID].products.length){
            delete ProductCompare.comparisonStacks[comparisonTypeID];
            ProductCompare.determineActiveStack();
        }
        ProductCompare.updatePopupLinks();
        ProductCompare._saveComparisonStacks();
    },
    
    // determines the active stack and updates the comparisonbuttons accordingly
    // needs to run when the product is removed from the stacklist (because the
    // stack now might be empty), and when the mroduct is added to the stacklist
    // (because and add on an empty stacklist sets the currently active comparison
    // to the just added product)
    determineActiveStack: function(){
        var sortedByRelevance = [];
        ECube.d.log(2, 'ProductCompare: Started determination of activestack for stacklist: ', ProductCompare.comparisonStacks);
        
        if (!$H(ProductCompare.comparisonStacks).size()){
            ProductCompare.activeStack = null;
            ProductCompare.updateCompareButtonsForStack();
            return;
        }
        
        var visibleProducts = ProductCompare.observees.collect(function(observee){
            return observee.up('.productComparisonButtons').readAttribute('productId');
        }).uniq(true);
        
        $H(ProductCompare.comparisonStacks).each(function(stack){
            var productsInStack = stack[1].products.collect(function(product){
                return product.productNo;
            });
            var amountProductsInStack = visibleProducts.intersect(productsInStack).size();
            if (amountProductsInStack){
                sortedByRelevance.push({
                    matchedProducts : amountProductsInStack,
                    stack           : stack[0]
                });
            }
        });
        
        sortedByRelevance.sortBy(function(match){
            return match.matchedProducts;
        });
        
        
        ProductCompare.activeStack
            = sortedByRelevance.size()
            ? sortedByRelevance[sortedByRelevance.size()-1].stack
            : null;
        ProductCompare.updateCompareButtonsForStack();
    },

    // update the visual buttons to appear or not to appear according to
    // the currently active stack
    updateCompareButtonsForStack: function(){
        ECube.d.log(2, 'ProductCompare: updating button states to match stack: ', ProductCompare.activeStack);
        
        var buttonWrappers = ProductCompare.observees.collect(function(observee){
            return observee.up('.productComparisonButtons');
        }).uniq(true);
        
        buttonWrappers.each(function(buttonWrapper){
            var compareStack = buttonWrapper.readAttribute('comparestack');
            if (!ProductCompare.activeStack){
                buttonWrapper.show();
            }
            else {
                if (compareStack == ProductCompare.activeStack){
                    buttonWrapper.show();
                }
                else {
                    buttonWrapper.hide();
                }
            }

        });
    },

    updatePopupLinks: function(){
        ECube.d.log(4, 'ProductCompare: updating button popup links ');
        
        var buttonWrappers = ProductCompare.observees.collect(function(observee){
            return observee.up('.productComparisonButtons');
        }).uniq(true);
        
        buttonWrappers.each(function(buttonWrapper){
            var compareStack = buttonWrapper.readAttribute('comparestack');
            if(ProductCompare.comparisonStacks[compareStack]){
                var amountProductsInComparison = ProductCompare.comparisonStacks[compareStack]['products'].length;
                console.log(buttonWrapper.select('.productComparisonActive .notEnoughProducts'), amountProductsInComparison, ProductCompare.comparisonStacks[compareStack]);
                buttonWrapper.select('.productComparisonActive .notEnoughProducts').invoke((amountProductsInComparison <= 1) ? 'show' : 'hide');
                buttonWrapper.select('.productComparisonActive .showComparison').invoke((amountProductsInComparison > 1) ? 'show' : 'hide');
            }
        });
    },

    // returns all stacks with products
    _getComparisonStacks: function(){
        var cookieValue = ECube.cookies.read(ProductCompare.cookieName);
        if (cookieValue) {
            ProductCompare.comparisonStacks = cookieValue.evalJSON();
            console.log(ProductCompare.comparisonStacks);
        }
    },
    
    // saves all stacks to the cookie
    _saveComparisonStacks: function(){
        ECube.cookies.create(
            ProductCompare.cookieName,
            Object.toJSON(ProductCompare.comparisonStacks));
    },
    
    _events: {
        // you might want to attach this in case one button serves both the purpose of
        // adding and deleting
        toggleCompareState: function(eventObject){
            var initiator = eventObject.element();
            ECube.d.log(5, 'ProductCompare: Event toggleCompareState');
            
            var buttonWrapper = initiator.up('.productComparisonButtons');
            
            // if the item allready exists in the stack we want to 
            if (buttonWrapper.hasClassName('ProductCompare_inStack')){
                ProductCompare._events.clickDelete(eventObject);
            }
            else {
                ProductCompare._events.clickStore(eventObject);
            };
        },
        
        // you might want to attach this in case there is an explicit 'add to comparison' button
        clickStore: function(eventObject){
            var initiator = eventObject.element();
            ECube.d.log(5, 'ProductCompare: Event clickStore');
                        
            var buttonWrapper = initiator.up('.productComparisonButtons');

            var productId       = buttonWrapper.readAttribute('productId');
            var compareStack    = buttonWrapper.readAttribute('compareStack');
            var wasAbleToStore  = ProductCompare.storeProduct(productId, compareStack);
            if (wasAbleToStore) {
                buttonWrapper.addClassName('ProductCompare_inStack');
            }
        },
        
        // you might want to attach this in case there is an explicit 'remove from comparison' button
        clickDelete: function(eventObject){
            var initiator = eventObject.element();
            ECube.d.log(5, 'ProductCompare: Event clickDelete');
                        
            var buttonWrapper = initiator.up('.productComparisonButtons');

            var productId       = buttonWrapper.readAttribute('productId');
            var compareStack    = buttonWrapper.readAttribute('compareStack');
            
            ProductCompare.deleteProduct(productId, compareStack);
            buttonWrapper.removeClassName('ProductCompare_inStack');
        },
        
        showPopup: function(eventobject){
            ECube.d.log(5, 'ProductCompare: Event showPopup');
            if (!$(ProductCompare.popupContainerId)){
                ECube.d.log(0, 'could not find containerId, aborting');
            }
            
            var compareStack = eventobject.element().readAttribute('compareStack');
            
            new Ajax.Request(
                '/shop/UserTemplate/comparePopupContent',
                {
                    parameters: {
                        LoadComparisonDataFor: compareStack
                    },
                    onSuccess: function(transport){
                        $(ProductCompare.popupContainerId).update(transport.responseText);
                        Effect.Appear($(ProductCompare.popupBackgroundId), {
                            duration    : 0.3,
                            from        : 0,
                            to          : 0.6
                        });
                        Effect.Appear($(ProductCompare.popupContainerId), {
                            duration    : 0.6,
                            from        : 0,
                            to          : 1
                        });
                        
                        with ($(ProductCompare.popupContainerId)){
                            select('.hideComparison').invoke('observe', 'click', ProductCompare._events.hidePopup);
                            select('.addtobasket').invoke('observe', 'click', ProductCompare._events.hidePopup);
                            select('a.addtobasket').invoke('observe', 'click', EpagesShop.miniBasket.addToBasket);
                            select('form.addtobasket').invoke('observe', 'submit', EpagesShop.miniBasket.addToBasket);
                            select('input.addtobasket').invoke('observe', 'change', EpagesShop.miniBasket.addToBasket);
                            select('select.addtobasket').invoke('observe', 'change', EpagesShop.miniBasket.addToBasket);
                        }
                   }
                });
        },
        
        hidePopup: function(eventobject){
            ECube.d.log(5, 'ProductCompare: Event hidePopup');
            Effect.Fade(ProductCompare.popupContainerId, {
                duration    : 0.3,
                from        : 1,
                to          : 0
            });

            Effect.Fade($(ProductCompare.popupBackgroundId), {
                duration    : 0.6,
                from        : 0.6,
                to          : 0
            });
        }
    },
    
    __detectIE6: function(eventObject){
        var version = parseFloat(navigator.appVersion.split('MSIE')[1]);
        // IE6 detected
        if ((version >= 5.5) && (version < 7)) {
            $$('.productComparisonButtons').invoke('hide');
            return true;
        }
        // no IE6 detected
        else {
            return false;
        }
        // TODO : abort all IE6 actions for compare
    }
};

document.observe('dom:loaded',ProductCompare.initialize);
