/*
    PlotKit Sweet Canvas Renderer
    =============================
    Canvas Renderer for PlotKit which looks pretty!

    Copyright
    ---------
    Copyright 2005,2006 (c) Alastair Tse <alastair^liquidx.net>
    For use under the BSD license. <http://www.liquidx.net/plotkit>
*/

// -------------------------------------------------------------------------
// Check required components
// -------------------------------------------------------------------------

try {    
    if (typeof(PlotKit.CanvasRenderer) == 'undefined')
    {
        throw "";    
    }
} 
catch (e) {    
    throw "SweetCanvas depends on MochiKit.{Base,Color,DOM,Format} and PlotKit.{Layout, Canvas}";
}


if (typeof(PlotKit.SweetCanvasRenderer) == 'undefined') {
    PlotKit.SweetCanvasRenderer = {};
}

PlotKit.SweetCanvasRenderer = function(element, layout, options) {
    if (arguments.length > 0) {
        this.__init__(element, layout, options);
    }
};

PlotKit.SweetCanvasRenderer.NAME = "PlotKit.SweetCanvasRenderer";
PlotKit.SweetCanvasRenderer.VERSION = PlotKit.VERSION;

PlotKit.SweetCanvasRenderer.__repr__ = function() {
    return "[" + this.NAME + " " + this.VERSION + "]";
};

PlotKit.SweetCanvasRenderer.toString = function() {
    return this.__repr__();
};

// ---------------------------------------------------------------------
// Subclassing Magic
// ---------------------------------------------------------------------

PlotKit.SweetCanvasRenderer.prototype = new PlotKit.CanvasRenderer();
PlotKit.SweetCanvasRenderer.prototype.constructor = PlotKit.SweetCanvasRenderer;
PlotKit.SweetCanvasRenderer.__super__ = PlotKit.CanvasRenderer.prototype;

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

PlotKit.SweetCanvasRenderer.prototype.__init__ = function(el, layout, opts) { 
    var moreOpts = PlotKit.Base.officeBlue();
    MochiKit.Base.update(moreOpts, opts);
    PlotKit.SweetCanvasRenderer.__super__.__init__.call(this, el, layout, moreOpts);
};

// ---------------------------------------------------------------------
// Extended Plotting Functions
// ---------------------------------------------------------------------

PlotKit.SweetCanvasRenderer.prototype._renderBarChart = function() {
    var bind = MochiKit.Base.bind;
    var shadowColor = Color.blackColor().colorWithAlpha(0.1).toRGBString();

    var prepareFakeShadow = function(context, x, y, w, h) {
        context.fillStyle = shadowColor;
        context.fillRect(x-2, y-2, w+4, h+2); 
        context.fillStyle = shadowColor;
        context.fillRect(x-1, y-1, w+2, h+1); 
    };

    var colorCount = this.options.colorScheme.length;
    var colorScheme =  this.options.colorScheme;
    var setNames = MochiKit.Base.keys(this.layout.datasets);
    var setCount = setNames.length;

    var chooseColor = function(name) {
        for (var i = 0; i < setCount; i++) {
            if (name == setNames[i])
                return colorScheme[i%colorCount];
        }
        return colorScheme[0];
    };

    var drawRect = function(context, bar) {
        var x = this.area.w * bar.x + this.area.x;
        var y = this.area.h * bar.y + this.area.y;
        var w = this.area.w * bar.w;
        var h = this.area.h * bar.h;

        if ((w < 1) || (h < 1))
            return;        

        context.save();

        context.shadowBlur = 5.0;
        context.shadowColor = Color.fromHexString("#888888").toRGBString();

        if (this.isIE) {
            context.save();
            context.fillStyle = "#cccccc";
            context.fillRect(x-2, y-2, w+4, h+2); 
            context.restore();
        }
        else {
            prepareFakeShadow(context, x, y, w, h);
        }

        context.fillStyle = chooseColor(bar.name).toRGBString();
        context.fillRect(x, y, w, h);

        context.shadowBlur = 0;
        context.strokeStyle = Color.whiteColor().toRGBString();
        context.lineWidth = 2.0;

        context.strokeRect(x, y, w, h);                

        context.restore();

    };
    this._renderBarChartWrap(this.layout.bars, bind(drawRect, this));
};

PlotKit.CanvasRenderer.prototype._renderLineChart = function() {
    var context = this.element.getContext("2d");
    var colorCount = this.options.colorScheme.length;
    var colorScheme = this.options.colorScheme;
    var setNames = MochiKit.Base.keys(this.layout.datasets);
    var setCount = setNames.length;
    var bind = MochiKit.Base.bind;


    for (var i = 0; i < setCount; i++) {
        var setName = setNames[i];
        var color = colorScheme[i%colorCount];
        var strokeX = this.options.strokeColorTransform;

        // setup graphics context
        context.save();
        
        // create paths
        var makePath = function() {
            context.beginPath();
            context.moveTo(this.area.x, this.area.y + this.area.h);
            var addPoint = function(context, point) {
            if (point.name == setName)
                context.lineTo(this.area.w * point.x + this.area.x,
                               this.area.h * point.y + this.area.y);
            };
            MochiKit.Iter.forEach(this.layout.points, partial(addPoint, context), this);
            context.lineTo(this.area.w + this.area.x,
                           this.area.h + this.area.y);
            context.lineTo(this.area.x, this.area.y + this.area.h);
            context.closePath();
        };

        // faux shadow for firefox
        context.save();
        if (this.isIE) {
            context.fillStyle = "#cccccc";
        }
        else {
            context.fillStyle = Color.blackColor().colorWithAlpha(0.2).toRGBString();
        }

        context.translate(-1, -2);
        bind(makePath, this)();        
        context.fill();
        context.restore();

        context.shadowBlur = 5.0;
        context.shadowColor = Color.fromHexString("#888888").toRGBString();
        context.fillStyle = color.toRGBString();
        context.lineWidth = 2.0;
        context.strokeStyle = Color.whiteColor().toRGBString();

        bind(makePath, this)();
        context.fill();
        bind(makePath, this)();
        context.stroke();

        context.restore();
    }
};

PlotKit.CanvasRenderer.prototype._renderPieChart = function() {
    var context = this.element.getContext("2d");

    var colorCount = this.options.colorScheme.length;
    var slices = this.layout.slices;

    var centerx = this.area.x + this.area.w * 0.5;
    var centery = this.area.y + this.area.h * 0.5;
    var radius = Math.min(this.area.w * this.options.pieRadius, 
                          this.area.h * this.options.pieRadius);

    if (this.isIE) {
        centerx = parseInt(centerx);
        centery = parseInt(centery);
        radius = parseInt(radius);
    }

	// NOTE NOTE!! Canvas Tag draws the circle clockwise from the y = 0, x = 1
	// so we have to subtract 90 degrees to make it start at y = 1, x = 0

    if (!this.isIE) {
        context.save();
        var shadowColor = Color.blackColor().colorWithAlpha(0.2);
        context.fillStyle = shadowColor.toRGBString();
        context.shadowBlur = 5.0;
        context.shadowColor = Color.fromHexString("#888888").toRGBString();
        context.translate(1, 1);
        context.beginPath();
        context.moveTo(centerx, centery);
        context.arc(centerx, centery, radius + 2, 0, Math.PI*2, false);
        context.closePath();
        context.fill();
        context.restore();
    }

    context.save();
    context.strokeStyle = Color.whiteColor().toRGBString();
    context.lineWidth = 2.0;    
    for (var i = 0; i < slices.length; i++) {
        var color = this.options.colorScheme[i%colorCount];
        context.fillStyle = color.toRGBString();

        var makePath = function() {
            context.beginPath();
            context.moveTo(centerx, centery);
            context.arc(centerx, centery, radius, 
                        slices[i].startAngle - Math.PI/2,
                        slices[i].endAngle - Math.PI/2,
                        false);
            context.lineTo(centerx, centery);
            context.closePath();
        };

        if (Math.abs(slices[i].startAngle - slices[i].endAngle) > 0.0001) {
            makePath();
            context.fill();
            makePath();
            context.stroke();
        }
    }
    context.restore();
};

PlotKit.SweetCanvasRenderer.prototype._renderBackground = function() {
    var context = this.element.getContext("2d");
   
    if (this.layout.style == "bar" || this.layout.style == "line") {
        context.save();
        context.fillStyle = this.options.backgroundColor.toRGBString();
        context.fillRect(this.area.x, this.area.y, this.area.w, this.area.h);
        context.strokeStyle = Color.whiteColor().toRGBString();
        context.lineWidth = 1.0;
        for (var i = 0; i < this.layout.yticks.length; i++) {
            var y = this.layout.yticks[i][0] * this.area.h + this.area.y;
            var x = this.area.x;
            context.beginPath();
            context.moveTo(x, y);
            context.lineTo(x + this.area.w, y);
            context.closePath();
            context.stroke();
        }
        context.restore();
    }
    else {
        PlotKit.SweetCanvasRenderer.__super__._renderBackground.call(this);
    }
};
