var TsRGraph = Class.create(
{
    initialize : function(canvasId, dataURL) {
        this.canvasId = canvasId;
        this.dataURL = dataURL;
        this.seriesColors = ["#0099CC", "#0066CC", "#0033CC", "#0000CC", "#00CC99", "#8833EE", "#EE3388", "#99CC00", "#CC9900", "#FF3300", "#33FF00", "#0033FF", "#DDDD00", "#FF00FF", "#00FFFF", "#222222", "#777777", "#FF0033","#0022FF", "#22FF99", "#FFAA00"];
        this.numberSeparator = " ";
        this.decimalDigits = 0;
        this.backgroundColor = null;
        this.progressId = null;
        this.adjustend = null;
        
        if (this.dataURL !== undefined)
		{
			this.getData(this.dataURL);
		}
    },

    loadJSON : function(json)
    {
        var seriesList = json["seriesList"];
        var data = [];
        var labels = [];
        var tooltips = [];
        var keys = [];
        var colors = [];
        var keyColors = [];
        var type = json["type"];
        var showKeys = true;
        var maxKeyLength = 0;
        var numValues = 0;
        var urls = [];
        var clickableBars = false;
        var canvas = document.getElementById(this.canvasId);

        //Clear the context before drawing, so that calls to getData() do not draw on top of the existing chart.
        var ctx = canvas.getContext('2d');
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        if (this.backgroundColor)
        {
        	ctx.fillStyle = this.backgroundColor;
        	ctx.fillRect(0, 0, canvas.width, canvas.height);
        }
        
        for (var i = 0; i < seriesList.length; i++) {
            var series = [];

            if (seriesList[i].name == null || seriesList[i].name == "") {
                showKeys = false;
            }
            else {
                keys.push(seriesList[i].name);

                //Keys are shown to the right of the chart, so calculate how wide (in pixels) the text is. Keep track of the largest number.
                var hiddenElem = document.createElement("span");
                var idName = this.canvasId + i + 'Span';
                hiddenElem.setAttribute("id", idName);
                hiddenElem.setAttribute("style", "visibility:hidden; white-space:nowrap;");
                hiddenElem.appendChild(document.createTextNode(seriesList[i].name));
                document.body.appendChild(hiddenElem);

                if (hiddenElem.offsetWidth > maxKeyLength) {
                    maxKeyLength = hiddenElem.offsetWidth;
                }
            }

            keyColors.push(this.seriesColors[i % this.seriesColors.length]);
            var mod = Math.floor(seriesList[i].series.length / 10);
            if (mod < 1) { mod = 1; }

            for (var j = 0; j < seriesList[i].series.length; j++) {
                //Not pie: one colour per series.
                if (type != 'pie') {
                    colors.push(this.seriesColors[i % this.seriesColors.length]);
                }
                //Pie: one colour per slice.
                else {
                    colors.push(this.seriesColors[j % this.seriesColors.length]);
                }

                //Text may be used to make bars clickable.
                if (type == 'bar') {
                    var text = seriesList[i].series[j]["text"];

                    //if (text && text.lastIndexOf('http://', 0) === 0) {
                    if (text) {
                        clickableBars = true;
                        urls.push(text);
                    }
                    else {
                        urls.push("");
                    }
                }
                
                //Lines stack, so do not add more than one set of labels.
                if (type != 'line' || i == 0) {
                    if (j % mod == 0) {
                        labels.push(seriesList[i].series[j]["label"]);
                    }
                    else {
                        labels.push("");
                    }

                    ++numValues;
                }

                //If only one series, push directly to data to avoid having bars with no space between them.
                if (seriesList.length == 1) {
                    data.push(parseInt(seriesList[i].series[j]["value"]));
                }
                else {
                    series.push(parseInt(seriesList[i].series[j]["value"]));
                }

                var tip = seriesList[i].tip;
                tip = tip.replace(/#val#/, this.thousandSeparator(seriesList[i].series[j]["value"]));
                tip = tip.replace(/#x_label#/, seriesList[i].series[j]["label"]);
                tip = tip.replace("\n", "<br />");

                tooltips.push(tip);
            }

            if (seriesList.length > 1) {
                data.push(series);
            }
        }

        var graph;

        if (type == 'bar') {
            graph = new RGraph.Bar(this.canvasId, data);
            graph.Set('chart.colors', colors); //One color per bar.
            graph.Set('chart.strokecolor', colors);
            graph.Set('chart.strokestyle', '#FFFFFF'); //Stop Firefox from throwing a million warnings in the console log.
            graph.Set('chart.colors.sequential', 1);
            graph.Set('chart.tooltips.event', 'onmousemove');
        }
        else if (type == 'pie') {
            graph = new RGraph.Pie(this.canvasId, data);
            graph.Set('chart.colors', colors); //One color per slice.
        }
        else {
            graph = new RGraph.Line(this.canvasId, data);
            graph.Set('chart.colors', keyColors); //One color per line.
        }

        var title = json["title"];

        if (title != null && title != "") {
            graph.Set('chart.title', title);
            graph.Set('chart.title.color', '#222222');
            graph.Set('chart.title.vpos', 0.5);
        }

        graph.Set('chart.labels', labels);
        graph.Set('chart.text.angle', 45);
        graph.Set('chart.text.size', 8);
        graph.Set('chart.text.color', '#222222');

        if (type != 'pie' && showKeys && keys.length > 1) {
            graph.Set('chart.key', keys);
            graph.Set('chart.key.background', 'rgba(255, 255, 255, 0.5)');
            graph.Set('chart.key.colors', keyColors);
            graph.Set('chart.key.position.x', canvas.width - (maxKeyLength + 25));
            graph.Set('chart.gutter.right', maxKeyLength + 35);
            graph.Set('chart.key.interactive', true);
            graph.Set('chart.key.text.size', 7);
        }

        graph.Set('chart.gutter.left', 65);
        graph.Set('chart.gutter.bottom', 65);

        if (type == 'bar') {
            if (numValues < 20) {
                graph.Set('chart.labels.above', 1);
            }

            if (!clickableBars) {
                graph.Set('chart.adjustable', 1);
            }
        }
        else if (type == 'line') {
            graph.Set('chart.linewidth', 2);
            graph.Set('chart.tickmarks', 'circle');

            graph.Set('chart.adjustable', 1);
            
            if (this.adjustend) {
                RGraph.AddCustomEventListener(graph, 'onadjustend', this.adjustend);
            }
        }

        graph.Set('chart.axis.color', '#ddd');
        graph.Set('chart.tooltips', tooltips);
        //graph.Set('chart.background.image', '/images/tailsweep_watermark2.png');

        if (this.progressId)
        {
        	document.getElementById(this.progressId).style.display = 'none';
        }
        
        graph.Draw();
        
        //Possibly make bars clickable.
        if (type == 'bar' && clickableBars) {
            RGraph.Register(graph);
            
            graph.canvas.onclick = function(e)
            {
                RGraph.Redraw();
            
                var canvas   = e.target;
                var obj      = canvas.__object__;
                var barIndex = obj.getBar(e);
                
                //if (barIndex && urls[barIndex[5]].lastIndexOf('http://', 0) === 0) {
                if (barIndex) {
                    window.location = urls[barIndex[5]];
                }
            }
        }
    },
    getData : function(url) {
    	if (this.progressId)
        {
        	document.getElementById(this.progressId).style.display = 'block';
        }

		new Ajax.Request(url, {
			method : 'get',
			onComplete : this.handleAjaxResponse.bind(this)
		});

		return false;
	},
	handleAjaxResponse : function(res) {
		var resObj = null;
		try {
			var JSON = res.responseText.evalJSON();
			this.loadJSON(JSON);
		} catch (e) {
			//console.log(e);
		}
	},
    thousandSeparator : function(value)
    {
        //Separator Length. Here this is thousand separator.
        var separatorLength = 3;
        var tmpValue = "" + value;
        var newValue = "";

        //Add decimal point if it is not there.
        if (tmpValue.indexOf(".") == -1)
        {
            tmpValue += ".";
        }

        //Store digits before decimal.
        var dStr = tmpValue.substr(0, tmpValue.indexOf("."));

        //Store digits after decimal.
        var pStr = tmpValue.substr(tmpValue.indexOf("."))

        //Add “0″ for remaining digits after decimal point.
        while (pStr.length - 1 < this.decimalDigits)
        {
        	pStr += "0";
        }

        if (pStr == '.')
        {
            pStr = "";
        }

        if (dStr.length > separatorLength)
        {
            //Logic of separation.
            while (dStr.length > separatorLength)
            {
                newValue = this.numberSeparator + dStr.substr(dStr.length - separatorLength) + newValue;
                dStr = dStr.substr(0, dStr.length - separatorLength);
            }

            newValue = dStr + newValue;
        }
        else
        {
            newValue = dStr;
        }

        //Add decimal part.
        if (true || !pStr.match("^\.0*$"))
        {
        	newValue = newValue + pStr;
        }

        return newValue;
    }
});

