$(function () {
    // product grid layout
    var grid = $('.productGrid'),
        products = grid.find('.product'),
        productWidth = products.width(),
        productHeight = products.height(),
        columns = Math.floor(grid.width() / productWidth),
        rows = Math.ceil(grid.height() / productWidth),
        pageSize = rows * columns;

    var elements, totalColumns, offset = 0;

    function columnForElement(i) {
        return Math.floor(i / rows);
    }

    function elementForColumn(c) {
        return rows * c;
    }

    function layoutProducts() {
        offset = 0;
        elements = products.not('.notInQuery');
        totalColumns = Math.floor((elements.length - 1) / rows) + 1;
        
        elements.each(function (i) {
            // set position
            var x = columnForElement(i), y = i % rows;
            $(this).css({
                position: 'absolute',
                top: y * productHeight,
                left: x * productWidth
            });

            // adjust ruler visibility
            if (x > 0)
                $(this).find('.leftRuler').show();
            else
                $(this).find('.leftRuler').hide();
            if (y > 0)
                $(this).find('.topRuler').show();
            else
                $(this).find('.topRuler').hide();
        });
        elements.slice(0, pageSize).removeClass('outsidePage');
        elements.slice(pageSize).addClass('outsidePage');

        // reset view
        grid.find('.container').css("left", "-1px");
        grid.find('.window').css({"visibility": "visible"});
        grid.find('.loading').hide();

        // put this inside a timeout to ensure we've had time to
        // bind to the event in the page code
        setTimeout(function () {
            grid.trigger('paginationchanged', [ { from: 0, pageSize: pageSize, total: elements.length }]);
        }, 10);
    }

    // scrolling
    var scrollButtons = grid.find('.left,.right');
    
    function getDirection(button) {
        if (button.hasClass("left"))
            return -1;
        else
            return 1;
    }

    function isActive(button) {
        var d = getDirection(button);
        return (d < 0 && offset > 0)
            || (d > 0 && columnForElement(offset + pageSize) < totalColumns);
    }

    function setButtonActivity() {
        scrollButtons.each(function () {
            var button = $(this);
            var opacity = isActive(button) ? 1 : 0.6;
            button.animate({ opacity: opacity }, 1000);
        });
    }
    
    function scrollProducts(dir) {
        var oldOffset = offset;
        offset += dir * pageSize;
        if (columnForElement(offset) > totalColumns - columns)
            offset = elementForColumn(totalColumns - columns);
        if (offset < 0)
            offset = 0;

        elements.each(function (i) {
            var c = columnForElement(i),
                newc = columnForElement(offset),
                oldc = columnForElement(oldOffset);
            if ((c >= newc && c < newc + columns) ||
                (c >= oldc && c < oldc + columns))
                $(this).removeClass("outsidePage");
            else
                $(this).addClass("outsidePage");
        });
        
        var delta = productWidth * (oldOffset - offset) / rows;
        grid.find('.container')
            .stop(true, true)
            .animate({ left: '+=' + delta},
                     { duration: 800, easing: 'easeInCubic'});

        setButtonActivity();

        grid.trigger('paginationchanged', [ { from: offset, pageSize: pageSize, total: elements.length }]);
    }

    scrollButtons.hover(function () {
        if (isActive($(this)))
            $(this).animate({ opacity: 0.85 }, 200);
    }, function () {
        if (isActive($(this)))
            $(this).animate({ opacity: 1 }, 200);
    }).click(function () {
        var button = $(this);
        if (!isActive(button))
            return;

        button
            .stop(true, true)
            .animate({ opacity: 1 }, 100)
            .animate({ opacity: 1}, 200)
            .animate({ opacity: 0.8 }, 400);

        scrollProducts(getDirection($(this)));
    });

    function setup() {
        layoutProducts();
        setButtonActivity();
    }

    setup();

    grid.bind('querychanged', setup);
});

