// generate sparklines on the fly
// XBM image version: 2005-05-12 karsten schmidt (v0.2)
// based original SVG version, (c) 2005 Jesse Andrews
// Licensed under GPL v2 or later

// REQUIRES: http://toxi.co.uk/dev/sparklines/xbminimal.js
// PLEASE DON'T LINK TO THIS FILE DIRECTLY, COPY IT TO YOUR SERVER BEFORE USING. THANKS!

// constructor params:
// data: array of raw data values to display
// w: width of image
// h: height of image
// conf: optional object to customize bitmap:
//          name: name of image (if omitted, a random name is created)
//          style: set to "bar" to show bargraph variant of sparkline (default: "line")
//          auto_width: only used if style="bar", adjusts bar width based on amount of data (default: false)
//          show_avg: flag to toggle display of average value (default: false)
//          dotted: if true, average value line is being drawn dotted (default: false)

// usage:
// var mySparkline = new SparkLine([23,42,128,64],128,16); or
// var mySparkline = new SparkLine([23,42,128,64],128,32,{show_avg: true, dotted: true} );
// var mySparkline = new SparkLine([23,42,128,64],64,8,{name: "foo", show_avg: true} );
//
// <img src="javascript:mySparkline.getImage();" />

function SparkLine(data,w,h,conf) {
    this.xbm=new XBMImage(w,h,(conf.name==undefined ? "sparkline_"+Math.floor(Math.random()*1000000) : conf.name));
    this.data=data;
    
    var chart = [];    
    var total = 0;
    var min = max = data[0];
    
    for (var i=0; i<data.length; i++) { 
        total += data[i];
        if (data[i] > max) max = data[i];
        if (data[i] < min) min = data[i];
    }
    imax=1/max;    
    this.data_avg = total/data.length;    
    
    if (conf.style!='bar') {
        // draw "real" sparkline
        var scale = (h-1)>>1;
        var translate = (h-1)>>1;
        var xscl=w/(data.length-1);
        this.chart_avg = Math.floor((scale-scale*((this.data_avg-min)*imax))+translate);
        for (var i=0; i<data.length; i++) chart[i] = Math.floor((scale-scale*((data[i]-min)*imax))+translate);
        for (var i=0; i<chart.length-1; i++) this.xbm.line(i*xscl,chart[i],(i+1)*xscl,chart[i+1]);
        
    } else {
        // draw alternate version using bar graphs
        // see config settings above...
        var scale=h/(max-min);
        var translate=h-1;
        var xscl=Math.floor(w/data.length);
        this.chart_avg=0;
        for (var i=0; i<data.length; i++) this.chart_avg+=(chart[i] = Math.floor(translate-(data[i]-min)*scale));
        this.chart_avg=Math.floor(this.chart_avg/data.length);
        if (conf.auto_width && xscl>1) {
            for (var i=0; i<chart.length; i++) {
                for (var j=0,x=i*xscl; j<xscl-1; j++) this.xbm.lineV(x+j,chart[i],translate);
            }
        } else for (var i=0; i<chart.length; i++) this.xbm.lineV(i*xscl,chart[i],translate);
    }
    
    if (conf.show_avg) {
        if (conf.dotted) for(var x=0; x<w; x+=2) this.xbm.set(x,this.chart_avg); // show avg as dotted line
        else this.xbm.lineH(0,this.chart_avg,w); // show avg as full line
    }
}

SparkLine.prototype.getImage = function() {
    return this.xbm.getImage();
};

SparkLine.prototype.toString = function () {
    var s='avg: '+Math.round(this.data_avg)+' [';
    for(var i=0; i<this.data.length; i++) s+=Math.round(this.data[i])+(i!=this.data.length-1 ? ',' : ']');
    return s;
};
