/*
* jQuery scrollableCanvas Plugin
* http://www.namic.dk/
* Copyright (c) 2010 Namic ApS
* Version: 0.1 (08/08/2010)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Requires: jQuery v1.4.2 or later
*/
; (function ($) {
    var _version = '0.1';

    $.fn.extend({
        scrollableCanvas: function (options) {
            return this.each(function () {
                options = options || {};
                var opts = $.extend($.fn.scrollableCanvas.defaults, options);
                var canvas = $(this);
                var canvasContent = canvas.children(":first");
                var canvasContentPos = canvasContent.position();
                var scrollRightTotal = 0;
                var loadedContentBlocks = {
                    top: opts.scrollBlockSize,
                    right: -opts.scrollBlockSize,
                    bottom: -opts.scrollBlockSize,
                    left: opts.scrollBlockSize
                };
                var scrollTopTotal = 0;
                var windowSize = $.windowSize();
                var scrollRight = 0;
                var scrollTop = 0;
                var dispachedLoadBlocks = Array();
                var busy = false;

                canvas.css("position", "relative");
                canvasContent.css("position", "absolute");

                if (opts.initializeBlocks == true) {
                    refreshBlocks(true);
                }

                function dispatchLoadBlock(args) {
                    var signature = args.x + ":" + args.y;
                    if ($.inArray(signature, dispachedLoadBlocks) == -1) {
                        dispachedLoadBlocks.push(signature);
                        opts.scrollBlock(args);
                    }
                }
                
                function refreshBlocks(initial) {
                    if (busy == true) {
                        return;
                    }
                    busy = true;
                    if (scrollRight != 0 || scrollTop != 0 || initial == true) {
                        /*
                        canvasContent.animate({
                        left: "+=" + scrollRight,
                        top: "+=" + scrollTop
                        },
                        opts.scrollInterval,
                        'linear');
                        */
                        canvasContentPos.left += scrollRight;
                        canvasContentPos.top += scrollTop;
                        canvasContent.css("left", canvasContentPos.left);
                        canvasContent.css("top", canvasContentPos.top);

                        scrollRightTotal += scrollRight;
                        scrollTopTotal += scrollTop;

                        if (opts.scrollBlock != null) {
                            var blocksToLoad = Array();

                            var minY = -(Math.round(scrollTopTotal / opts.scrollBlockSize) * opts.scrollBlockSize) - opts.scrollBlockSize;
                            var maxY = -(Math.round((scrollTopTotal - windowSize.height) / opts.scrollBlockSize) * opts.scrollBlockSize) + opts.scrollBlockSize;

                            var minX = -(Math.round(scrollRightTotal / opts.scrollBlockSize) * opts.scrollBlockSize) - opts.scrollBlockSize;
                            var maxX = -(Math.round((scrollRightTotal - windowSize.width) / opts.scrollBlockSize) * opts.scrollBlockSize) + opts.scrollBlockSize;

                            for (var xIndexer = minX; xIndexer <= maxX; xIndexer += opts.scrollBlockSize) {
                                for (var yIndexer = minY; yIndexer <= maxY; yIndexer += opts.scrollBlockSize) {
                                    dispatchLoadBlock({
                                        x: xIndexer,
                                        y: yIndexer
                                    });
                                }
                            }

                            /*
                            if (scrollRightTotal > loadedContentBlocks.left) {
                            loadedContentBlocks.left += opts.scrollBlockSize;
                            dispatchLoadBlock({
                            x: -loadedContentBlocks.left,
                            y: -(Math.floor(scrollTopTotal / opts.scrollBlockSize) * opts.scrollBlockSize)
                            });
                            }
                            else if (scrollRightTotal < loadedContentBlocks.right) {
                            loadedContentBlocks.right -= opts.scrollBlockSize;
                            dispatchLoadBlock({
                            x: -loadedContentBlocks.right,
                            y: -(Math.floor(scrollTopTotal / opts.scrollBlockSize) * opts.scrollBlockSize)
                            });
                            }
                            if (scrollTopTotal > loadedContentBlocks.top) {
                            loadedContentBlocks.top += opts.scrollBlockSize;
                            dispatchLoadBlock({
                            x: -(Math.floor(scrollRightTotal / opts.scrollBlockSize) * opts.scrollBlockSize),
                            y: -loadedContentBlocks.top
                            });
                            }
                            else if (scrollTopTotal < loadedContentBlocks.bottom) {
                            loadedContentBlocks.bottom -= opts.scrollBlockSize;
                            dispatchLoadBlock({
                            x: -(Math.floor(scrollRightTotal / opts.scrollBlockSize) * opts.scrollBlockSize),
                            y: -loadedContentBlocks.bottom
                            });
                            }
                            */
                        }
                    }

                    busy = false;
                }

                setInterval(function () {
                    refreshBlocks(false);
                },
                        opts.scrollInterval);

                $(window).resize(function () {
                    windowSize = $.windowSize();
                });

                //canvas.mousemove(function (event) {
                $(document).mousemove(function (event) {
                    scrollRight = 0;
                    scrollTop = 0;
                    if (event.pageX < opts.scrollLeftDist) {
                        scrollRight = opts.scrollLeftDist - event.pageX;
                    }
                    if (event.pageX > (windowSize.width - opts.scrollRightDist)) {
                        scrollRight = ((windowSize.width - opts.scrollRightDist) - event.pageX) - 1;
                    }
                    if (event.pageY < opts.scrollTopDist) {
                        scrollTop = opts.scrollTopDist - event.pageY;
                    }
                    if (event.pageY > (windowSize.height - opts.scrollBottomDist)) {
                        scrollTop = ((windowSize.height - opts.scrollBottomDist) - event.pageY) - 1;
                    }

                    scrollTop *= opts.scrollSpeed;
                    scrollRight *= opts.scrollSpeed;
                });
            });
        }
    });

    $.fn.scrollableCanvas.defaults = {
        scrollLeftDist: 100,
        scrollTopDist: 100,
        scrollRightDist: 100,
        scrollBottomDist: 100,
        scrollInterval: 50,
        scrollSpeed: .3,
        scrollBlock: null,
        scrollBlockSize: 1200,
        initializeBlocks: false
    };

    $.fn.scrollableCanvas.version = function() {
        return _version;
    };

})(jQuery);

$.extend({
    windowSize: function () {
        var w = $(window);
        return {
            width: w.width(),
            height: w.height()
        };
    }
});
