window.cmu = window.cmu || {};

(function (ns) {

    ns.objectGrid = function (spec, my) {
        var that = {};

        spec = spec || {};
        spec.dataCallback = spec.dataCallback || function () {};
        spec.raiseErrors = spec.raiseErrors !== undefined ? spec.raiseErrors : true;
        spec.randomBackgroundInt = spec.randomBackgroundInt !== undefined ? spec.randomBackgroundInt : false;

        // ------------------------------------------------------------------
        // Shared properties
        // ------------------------------------------------------------------

        my = my || {};
        my.logger = gj.logging.getLogger('cmu.objectGrid');
        my.gridSelector = 'body > .treasuryGrid';
        my.context = {};
        my.currentBackgroundUrl = null;
        my.currentWindowDimensions = {};

        my.backgroundsAvailable = {
            page: function () {
                return my.context.url;
            },
            searchResults: function () {
                // return cmu.urls.bgObjectSearch + document.location.search;
                return this.objectDetail();
            },
            objectDetail: function () {
                var match;
                var re = {
                    objectDetail: /\/object\/(\d+)/,
                    exhibition: /\/exhibition\/(\d+)/,
                    set: /\/set\/(\d+)/
                };

                if (my.context.url) {
                    // Check if it is an object detail URL
                    match = my.context.url.match(re.objectDetail);
                    if (match) {
                        return cmu.urls.bgObjectMlt.replace('0', match[1]);
                    }

                    // Check if it is an exhibition URL
                    match = my.context.url.match(re.exhibition);
                    if (match) {
                        return cmu.urls.bgExhibition.replace('0', match[1]);
                    }

                    // Check if it is a set URL
                    match = my.context.url.match(re.set);
                    if (match) {
                        return cmu.urls.bgSet.replace('0', match[1]);
                    }
                }

                if (spec.randomBackgroundInt) {
                    var randomInt = Math.ceil(Math.random() * 5);
                    return cmu.urls.bgRandom + '?i=' + randomInt;
                } else {
                    return cmu.urls.bgRandom;
                }
            }
        };

        // ------------------------------------------------------------------
        // Private properties
        // ------------------------------------------------------------------

        var pendingXhr = null;

        // ------------------------------------------------------------------
        // Private methods
        // ------------------------------------------------------------------

        var draw = function () {
            my.logger.debug('draw()');
            drawBackground();
        };

        var drawBackground = function () {
            my.logger.debug('drawBackground()');
            var url = getUrlForContext();

            // my.logger.info({'current': my.currentBackgroundUrl || '<empty>', 'new': url});
            var windowWidthChanged = $(window).width() !== my.currentWindowDimensions.width;
            if (url === my.currentBackgroundUrl && !windowWidthChanged) {
                my.logger.info('Background URL did not change, nothing to do');
                return;
            }

            // If no URL was returned, remove the background and cancel any outstanding request
            if (!url) {
                clearGrid();
                cancelLoading();
                return;
            }

            // If a background URL was previously set, refresh the dot as well
            if (my.currentBackgroundUrl) {
                cmu._dot && cmu._dot.draw();
            }

            my.currentBackgroundUrl = url;
            url = addClientDimensions(url);
            loadData(url);
        };

        var clearGrid = function () {
            my.logger.debug('clearGrid()');
            var existingGrid = $(my.gridSelector);
            existingGrid.remove();
        };

        var loadData = function (url) {
            my.logger.debug('loadData()', {'url': url})
            clearGrid();
            cancelLoading();

            pendingXhr = cmu.communicationController.ajax({
                url: url,
                type: 'GET',
                data: null,
                success: function (data, status, xhr) {
                    pendingXhr = null;

                    var newGrid = $(data);
                    // $('body').prepend(newGrid.fadeIn());
                    $('body').prepend(newGrid);

                    spec.dataCallback.apply(newGrid);
                },
                // Fail silently for background loading errors
                error: function () {}
            });
        };

        var cancelLoading = function () {
            my.logger.debug('cancelLoading()');

            if (pendingXhr) {
                my.logger.info('Aborting pending request');
                pendingXhr.abort();
            } else {
                my.logger.info('No pending request to abort');
            }
        };

        var getUrlForContext = function () {
            if (my.context && my.context.type in my.backgroundsAvailable) {
                return my.backgroundsAvailable[my.context.type]();
            }

            return null;
        };

        var addClientDimensions = function (url) {
            var params = [];
            var dimensions = {'width': null, 'height': null};
            var dimension, value;
            for (dimension in dimensions) {
                value = $(window)[dimension]();
                my.currentWindowDimensions[dimension] = value;
                params.push(dimension + '=' + Math.round(value / 100) * 100);
            }

            var paramString = params.join('&');
            var joinChar = (url.indexOf('?') == -1) ? '?' : '&';
            return url + joinChar + paramString;
        };

        // ------------------------------------------------------------------
        // Public methods
        // ------------------------------------------------------------------

        that.setContext = function (newContext, redraw) {
            my.logger.debug('setContext()', newContext);
            my.context = newContext;

            if (redraw !== false) {
                that.draw();
            }
        };

        that.draw = draw;

        that.addClientDimensions = addClientDimensions;

        // ------------------------------------------------------------------
        // Event handlers
        // ------------------------------------------------------------------

        var resizeTimeout = null;
        $(window).resize(function () {
            if (resizeTimeout) {
                window.clearTimeout(resizeTimeout);
                resizeTimeout = null;
            }
            resizeTimeout = window.setTimeout(function () {
                that.draw();
            }, 200);
        });

        var reachedEndOfDocument = function () {
            return $(window).scrollTop() === $(document).height() - $(window).height();
        };

        if (cmu.isIpad()) {
            $(window).scroll(function () {
                if (!$('body').hasClass('fullscreenMode')) {
                    return; // Only do something when showing background
                }
                if (reachedEndOfDocument()) {
                    $('.treasuryGrid .pager .next a').click();
                }
            });
        }

        // ------------------------------------------------------------------
        // Constructor
        // ------------------------------------------------------------------
        my.logger.debug('Initialized');

        return that;
    };

})(window.cmu);

