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

(function (ns) {

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

        spec = spec || {};
        spec.interactive = spec.interactive !== undefined ? spec.interactive : true;
        spec.drawLine = spec.drawLine !== undefined ? spec.drawLine : true;
        spec.radius = spec.radius || 117;
        spec.opacity = spec.opacity || 0.8;
        spec.elementId = 'dot';
        spec.colors = [
            '#fbffaf',
            '#ffebff',
            '#fdff1f',
            '#ff42ff',
            '#ffed00',
            '#b31cb3',
            '#cbc7af',
            '#c5a4d9',
            '#efffaf',
            '#00ff82',
            '#12b364',
            '#99c2ae',
            '#d6ffff',
            '#00ffff',
            '#5383ff',
            '#a9c5e0',
            '#f2e5ff',
            '#bb79ff',
            '#7a43b3',
            '#b3aedc',
            '#ffefe1',
            '#ffbb7f',
            '#c26847',
            '#c8afa6'
        ];
        spec.lineOptions = spec.lineOptions || {};

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

        my = my || {};
        my.logger = my.logger || gj.logging.getLogger('cmu.dot');

        // Important: inherit from canvasDrawer()
        that = gj.canvasDrawer(spec, my);

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

        my.initExtra = my.initExtra || function () {
            my.logger.debug('initExtra()');

            // Set the correct dimensions
            var diameter = spec.radius * 2;
            my.canvas.width = diameter;
            my.canvas.height = diameter;

            if (spec.interactive) {
                my.initTooltip();

                // FIXME (yvdm): try to unify with cmu.treasury code (make more DRY)
                my.$canvas.click(function () {
                    if (cmu._treasury) {
                        cmu._treasury.toggleBackground();
                    } else {
                        var $body = $('body');
                        var $content = $('#content, #footer');
                        var className = 'fullscreenMode';

                        $body.toggleClass(className);

                        if ($body.hasClass(className)) {
                            $content.hide();
                        } else {
                            $content.show();
                        }
                    }
                });
            }
        };

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

            my.drawDot();

            if (spec.drawLine) {
                my.drawLine();
            }
        };

        my.initTooltip = function () {
            my.logger.debug('initTooltip()');

            var $tooltip = $('<div class="tooltip"/>').append($('<div class="inner"/>').text(cmu.messages.dotTooltip));
            $tooltip.appendTo($('body'));
            var offset = [5, -14];
            var hideTimeout = null;

            my.$canvas.hover(
                function () {
                    hideTimeout && window.clearTimeout(hideTimeout);
                    // console.info('fading');
                    $tooltip.fadeIn(100);
                },
                function () {
                    hideTimeout && window.clearTimeout(hideTimeout);
                    hideTimeout = window.setTimeout(function () {
                        $tooltip.fadeOut(150);
                    }, 50);
                }
            );

            my.$canvas.add($tooltip).mousemove(function (e) {
                $tooltip.css({
                    left: e.pageX + offset[0],
                    top: e.pageY + offset[1]
                });
            });
        };

        my.drawDot = my.drawDot || function () {
            my.logger.debug('draw()');
            var ctx = my.ctx;

            my.clear();

            ctx.save();

            ctx.fillStyle = getFillStyle();

            // Use the canvas center as the origin
            ctx.translate(spec.radius, spec.radius);

            // Mid circle
            ctx.beginPath();
            ctx.arc(0, 0, spec.radius, 0, Math.PI * 2, true);
            ctx.fill();

            ctx.restore();
        };

        my.drawLine = my.drawLine || function () {
            my.logger.debug('drawLine()');
            cmu.line(spec.lineOptions);
        };

        var getFillStyle = function () {
            my.logger.debug('getFillStyle()');
            var randomIndex = Math.floor(Math.random() * spec.colors.length);
            var colorHex = spec.colors[randomIndex];
            my.logger.info(colorHex);
            var colorRgb = hex2rgb(colorHex);
            colorRgb.push(spec.opacity);
            return 'rgba(' + colorRgb.join(',') + ')';
        };

        var hex2rgb = function (hex){
            if (hex.charAt(0) == '#') {
                hex = hex.substring(1);
            }
            hex = parseInt(hex, 16);
            var r = (hex & 0xff0000) >> 16;
            var g = (hex & 0x00ff00) >> 8;
            var b = hex & 0x0000ff;
            return [r, g, b];
        }

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

        that.draw = my.draw;

        // ------------------------------------------------------------------
        // Constructor
        // ------------------------------------------------------------------

        my.init();
        return that;
    };

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

        spec = spec || {};

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

        my = my || {};
        my.logger = my.logger || gj.logging.getLogger('cmu.dotNonCanvas');

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

        my.init = function () {
            my.logger.debug('init()');

            my.createCanvas();
            my.initExtra && my.initExtra();
            my.draw();
        };

        my.createCanvas = function () {
            my.logger.debug('createCanvas()');

            my.$canvas = $('#' + spec.elementId);
            if (!my.$canvas.length) {
                my.$canvas = $('<div/>').attr('id', spec.elementId);
            }
            // Always make sure it is first in the body
            my.$canvas.prependTo(spec.container);
            my.canvas = my.$canvas.get(0);
        };

        my.initExtra = function () {
            my.logger.debug('initExtra()');

            // Set the correct dimensions
            var diameter = spec.radius * 2;
            my.$canvas.css({width: diameter, height: diameter});
            my.logger.debug(my.$canvas);

            if (spec.interactive) {
                my.initTooltip();

                // FIXME (yvdm): try to unify with cmu.treasury code (make more DRY)
                my.$canvas.click(function () {
                    if (cmu._treasury) {
                        cmu._treasury.toggleBackground();
                    } else {
                        var $body = $('body');
                        var $content = $('#content, #footer');
                        var className = 'fullscreenMode';

                        $body.toggleClass(className);

                        if ($body.hasClass(className)) {
                            $content.hide();
                        } else {
                            $content.show();
                        }
                    }
                });
            }
        };

        my.drawDot = function () {
            my.logger.debug('drawDot()');
            var imageIndex = Math.ceil(Math.random() * 4);
            var imagePath = cmu.mediaUrl + 'cmu/img/dotNonCanvas/dot' + imageIndex + '.png';
            my.$canvas.css({'background-image': 'url(' + imagePath + ')'});
        };

        my.drawLine = function () {
            my.logger.debug('drawLine()');
            cmu.lineNonCanvas(spec.lineOptions);
        };

        that = ns.dot(spec, my);


        return that;
    };

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

        spec = spec || {};

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

        my = my || {};
        my.logger = gj.logging.getLogger('cmu.lineNonCanvas');

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

        my.init = function () {
            my.logger.debug('init()');

            my.createCanvas();
            my.draw();
        };

        my.createCanvas = function () {
            my.logger.debug('createCanvas()');

            my.$canvas = $('#' + spec.elementId);
            if (!my.$canvas.length) {
                my.$canvas = $('<div/>').attr('id', spec.elementId);
            }
            // Always make sure it is first in the body
            my.$canvas.prependTo(spec.container);
            my.canvas = my.$canvas.get(0);
        };

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

            my.$canvas.css({width: 72, height: 116});
            var imagePath = cmu.mediaUrl + 'cmu/img/dotNonCanvas/line.png';
            my.$canvas.css({'background-image': 'url(' + imagePath + ')'});
        };

        that = cmu.line(spec, my);

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

        // ------------------------------------------------------------------
        // Constructor
        // ------------------------------------------------------------------

        return that;
    };


})(window.cmu);

