window.gj = window.gj || {};

(function (ns) {

    /* Generic base class for drawing on canvas elements */
    ns.canvasDrawer = function (spec, my) {
        var that;

        spec.elementId = spec.elementId;
        spec.container = spec.container;

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

        my = my || {};
        my.canvas = my.canvas || null;
        my.$canvas = my.$canvas || null;
        my.ctx = my.ctx || null;

        that = {};

        // ------------------------------------------------------------------
        // Shared methods
        // ------------------------------------------------------------------

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

            my.createCanvas();

            initializeCanvas(function () {
                setupContext();
                my.initExtra && my.initExtra();
                my.draw();
            }, 0);
        };

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

            my.$canvas = $('#' + spec.elementId);
            if (!my.$canvas.length) {
                my.$canvas = $('<canvas/>').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.clear = function () {
            my.logger.debug('clear()');
            my.ctx.clearRect(0, 0, my.canvas.width, my.canvas.height);
        };

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

        var initializeCanvas = function (callback, vmlTimeout) {
            var initVmlCanvas = function () {
                window.G_vmlCanvasManager.initElement(my.canvas);
            };

            if (window.G_vmlCanvasManager) {
                if (vmlTimeout !== undefined && typeof vmlTimeout === 'number') {
                    window.setTimeout(function () {
                        initVmlCanvas()
                        callback()
                    }, vmlTimeout);
                } else {
                    initVmlCanvas()
                    callback();
                }
            } else {
                callback()
            }
        };

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

            if (!my.canvas.getContext) {
                my.logger.warning('No context available');
                return null;
            }
            my.ctx = my.canvas.getContext('2d');
        };

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

        that.getViewNode = function () {
            return my.$canvas;
        };

        return that;
    };

})(window.gj);

