
function UsageGraph(container_id, url, width, height, target_samples) {

    this.url = url;
    this.plot = null;   // Plot object
    this.datasets = []; // All available datasets
    this.show = false;  // List of displayed dataset labels

    // Insert graph and legend divs into the container element
    this.containerDiv = $('#'+container_id);
    
    this.containerDiv.html(this.containerDiv.html()+'<div id="'+container_id+'-graph" style="width:'+width+';height:'+height+';float:left"></div><div id="'+container_id+'-legend"></div>');

    // Graph and Legend container elements
    this.graphDiv = this.containerDiv.children('#'+container_id+'-graph');
    this.legendDiv = this.containerDiv.children('#'+container_id+'-legend');

    this.update = function(start, end, labs) {

        if(start instanceof Date) {
            start = (start.getUTCMonth()+1)+'/'+start.getUTCDate()+'/'+start.getUTCFullYear();
        }

        if(end instanceof Date) {
            end = (end.getUTCMonth()+1)+'/'+end.getUTCDate()+'/'+end.getUTCFullYear();
        }

        if(!labs) {
            labs = this.labs;
        } else {
            this.labs = labs;
        }

        var self = this;
        
        var start_timestamp = (new Date(start + " UTC")).getTime();
        var end_timestamp = (new Date(end + " UTC")).getTime();
        var time_diff = end_timestamp - start_timestamp;

        var resolution = Math.max(1, (time_diff/1000/60/30)/target_samples);

        $.getJSON(this.url+'?start='+start+'&end='+end+'&labs='+labs+'&resolution='+resolution, function(json) {

            // Store the JSON response as the current dataset
            self.datasets = json;

            // If the show property not set, put all dataset labels into it
            if(!self.show) {
                self.show = [];
                for(var i in self.datasets) {
                    self.show.push(self.datasets[i].label);
                }
            }

            self.plot = $.plot(self.graphDiv, json, {
                legend: {
                    container: self.legendDiv,
                    labelFormatter: function(label) {

                        var label_id = label.toLowerCase().replace(/ /g, '_');

                        return '<a href="#" id="'+container_id+'-'+label_id+'">'+label+'</a>';
                    }
                },
                xaxis: {
                    mode: "time",
                    tickFormatter: function(tick) {

                        var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
                        var date = new Date(tick);

                        var month = months[date.getUTCMonth()];
                        var day = date.getUTCDate();

                        // If total timespan is less than one week
                        if(time_diff < 7*24*60*60*1000) {

                            var hour = date.getUTCHours();
                            var min = date.getUTCMinutes();
                            var suffix = (hour < 12) ? 'am' : 'pm';

                            hour = hour % 12;

                            if(hour == 0) {
                                hour = 12;
                            }

                            if(min < 10) {
                                min = '0'+min;
                            }

                            if(tick == end_timestamp && date.getUTCHours() == 0 && date.getUTCMinutes() == 0) {
                                
                                return '';

                            } else if(date.getUTCHours() == 0 && date.getUTCMinutes() == 0) {

                                return month+' '+day+'<br />'+hour+':'+min+suffix;

                            } else {

                                return hour+':'+min+suffix;
                            }

                        } else {

                            return month+' '+day;
                        }
                    },
                    ticks: function(axis) {

                        var interval = 60*60*1000; // 1 hour

                        while((axis.max - axis.min) / interval > 10) {

                            if(interval == 4*60*60*1000) {
                                interval *= 3;
                            } else if(interval >= 7*24*60*60*1000) {
                                interval += 7*24*60*60*1000;
                            } else {
                                interval *= 2;
                            }
                        }

                        var ticks = [];

                        for(var i = axis.min; i < axis.max; i += interval) {
                            ticks.push(i);
                        }

                        return ticks;
                    },

                    min: start_timestamp,
                    max: end_timestamp
                },
                yaxis: {
                    tickDecimals: 0
                },
                lines: {
                    show: true,
                    lineWidth: 1
                },
                shadowSize: 0
            });

            self.refreshPlotData();
            self.setClickHandlers();
        });
    }

    var onLegendClick = function(e) {

        var newShow = [];
        var found = false;

        for(var i in e.data.self.show) {

            if(e.data.self.show[i] != e.data.label) {
                newShow.push(e.data.self.show[i]);
            } else {
                found = true;
            }
        }

        if(!found) {
            newShow.push(e.data.label);
        }

        e.data.self.show = newShow;

        e.data.self.refreshPlotData();
        e.data.self.setClickHandlers();

        e.stopPropagation();

        return false;
    }

    this.setClickHandlers = function() {

        for(var i in this.datasets) {

            var sub_id = this.datasets[i].label.toLowerCase().replace(/ /g, "_");

            var element = $("#"+container_id+'-'+sub_id);

            element.bind("click", {self: this, element: element, label: this.datasets[i].label}, onLegendClick);
        }
    }

    this.refreshPlotData = function() {

        var data = [];

        for(var i in this.datasets) {

            var found = false;

            for(var j in this.show) {

                if(this.show[j] == this.datasets[i].label) {
                    found = true;
                }
            }

            if(found) {
                data.push(this.datasets[i]);
            } else {
                data.push({label: this.datasets[i].label, data: []});
            }
        }

        this.plot.setData(data);
        this.plot.draw();

        for(var k in this.datasets) {

            var sub_id = this.datasets[k].label.toLowerCase().replace(/ /g, "_")
            var element = $("#"+container_id+'-'+sub_id);

            found = false;
            for(var l in this.show) {
                if(this.show[l] == this.datasets[k].label) {
                    found = true;
                }
            }

            if(!found) {
                element.addClass("hidden-series");
            }
        }
    }

    return this;
}
