if (live_data_on && typeof(STOMPClient) != 'undefined'){

var live_data = function() {
    var dashboard_topic = "/topic/live/"+dashboard_name+"/sensor/";

    stomp = new STOMPClient();
    stomp.onopen = function() {
    };
    stomp.onclose = function(c) { 
    // alert('Lost Connection, Code: ' + c);
    };
    stomp.onerror = function(error) {
//        alert("Error: " + error);
    };
    stomp.onerrorframe = function(frame) {
//        alert("Error: " + frame.body);
    };
    stomp.onconnectedframe = function() {
        //stomp.subscribe("/topic/graph");
        //stomp.subscribe(dashboard_topic)
//		alert('connected')
        stomp.subscribe(dashboard_topic)

        var connected_parameters = '{"type":"subscribed"}'
        stomp.send(connected_parameters, 
                   dashboard_topic, // dest 
                   {exchange:""})
    };
    
    var sensor_windows = [];
    var dpoints = {};
    var dpoints_max = 100;
    var forced_range = 30;
    var feeds = [];
    
    var calc_stats = function(list){
        if (list.length == 0)
        {
            return {max:0, min:0, range:0, mean:0}
        }
        var min=list[0]
        var max=min
        var total=min
        for (var i = 1; i < list.length; ++i)
        {
            var val = list[i]
            if (val > max) {
                max = val
            }
            else if (val < min) {
                min = val
            }
            total += val
        }
        return {max:max, min:min, range: max - min, mean:total / list.length }
    }
    
    var expand_range = function(stats, min_range){
        var min = stats.min
        var max = stats.max
        if (!min_range) {
            min_range = forced_range;
        }
        if (stats.range < forced_range)
        {
            var half_min_range = min_range/2
            //If the data only spans a small area, expand the graph range centred around the mean.
            var centre;
            if (stats.mean >= 0) {
                // Put 0 at the bottom of the graph
                centre = Math.max(stats.mean, half_min_range)
            }
            else {
                // Put 0 at the top of the graph.
                centre = Math.min(stats.mean, -half_min_range)
            }
            
            min = Math.min(centre - half_min_range, stats.min)
            max = Math.max(centre + half_min_range, stats.max) 
        }
        return {
            min: min,
            max: max
        }		
    }
    
    var get_sensor_windows = function(pk){
        if (!sensor_windows[pk]) {
            // Cache the results of the queries for components on the page
            sensor_windows[pk] = {
                "code": $("." + pk + "_json"),
                "reading": $("." + pk + "_instant"),
                "graph_data": []
            }
        }
        return sensor_windows[pk];
    }
    
    var update_realtime_data = function(data){
        var pk = ""+data["pk"]
        var details = dashboard_sensors[pk]
        if (!details){
            return
        }
        var sensor_panels = get_sensor_windows(pk)
        //sensor_panels.code.empty().append("<code>" + frame.body + "</code>")
        if (!dpoints[pk]) {
            dpoints[pk] = data.hist
        }
        
        var latest = data.latest; 
        if (details['rounding'])
        {
            latest = latest.toFixed(details['rounding'])
        }
        sensor_panels.reading.empty().append(latest)
        // If the nexus disconnects and then reconnects it will send many samples at once. This will
        //  lead to lots of new samples - we concatinate them all.
        dpoints[pk] = dpoints[pk].concat(data.hist.slice(-data.num_new))
        if (dpoints[pk].length > dpoints_max) {
            dpoints[pk].splice(0, dpoints[pk].length - dpoints_max);
        }
        var fill = details['colour'] 
        if (!fill) {
            fill = '#A4C8EF'
        }
        var stats = calc_stats(dpoints[pk])
        var graph_range = expand_range(stats, details['graph_range'])

        //$("." + pk + "_spark").sparkline(internal_points);
        $("." + pk + "_spark").html(" ").sparkline(dpoints[pk], 
                                                { /*width: dpoints[pk].length*2,*/ 
            fillColor: fill,
            lineColor: '#000',
            chartRangeMin: graph_range.min,
            chartRangeMax: graph_range.max
        });
            
        // Page can register callbacks for data. Call each of those with the latest reading.
        for (var i = 0; i < feeds.length; ++i){
            feeds[i](pk, data.latest)
        }
    }
    
    stomp.onmessageframe = function(frame) {
        // To handle multiple destinations we would have to check frame.headers.destination.
        try{
            data = JSON.parse(frame.body)
        }
        catch (err){
            if (console){
                console.log("JSON parsing error", err)
            }
            return;
        }
        
        if (data['type'] == 'data') {
            try {
                update_realtime_data(data);
            } 
            catch (err) {
                if (console) {
                    console.log("Processing live graph error", err)
                }
                return;
            }
        }
        else if (data['type'] == 'output') {
            var pk = data["pk"]
            $('#output-'+pk).attr('class',data["state"])
        }

    };

    return {
        set_light: function(output, state){
          //var d = $(output)
          //alert('Setting ' + output + ' to state ' + state)
          //d.classNames().set(state)
        
          //var post = 'output=' + output + ', state=' + state;
          //new Ajax.Request('/house/set/', {asynchronous:true, method:'post', postBody:post});
          var parameters = '{"type":"output", "state":"'+state+'", "pk":"'+ output +'"}'
          stomp.send(parameters, 
                     dashboard_topic, // dest 
                     {exchange:""})
          //new Ajax.Updater('result-output', '/house/set/', {asynchronous:true, method:'post', parameters:parameters});
          
          return false; // Block link action
        },
        
        get_sensors: function(){
            return sensor_windows
        },
        
        // Each feed is called like so feed(pk, latest_reading) whenever a new reading comes in for a sensor.
        register_feed: function(feed){
            feeds.push(feed)			
        },
        
        connect: function(){
            stomp.connect('localhost', 61613);
        },
        
        calc_stats:calc_stats
        
    };
};

    var live = live_data()
    
    $(document).ready(function() {
        live.connect()
    })    
} 

//===================================================================================

var sensor_stats = {};
$(function() {
	
	var graph_labels = null 
    
    $('#main_graph').removeAttr('style')
    var hidden = true;
    
    $('#pick_date').click(function(){
        if (hidden){
            $('#calendar_dialog').fadeIn();
            hidden = false;
        }
        else{
            $('#calendar_dialog').fadeOut();
            hidden = true;
        }
    });	

    log = function() {
      if (typeof(console) != 'undefined' && typeof(console['debug']) != 'undefined') {
          console.debug('dashboard:', arguments, arguments.callee.caller);
      }
    }

    var findDates = function(data, minDate, maxDate){
        var low = minDate;
        var high= maxDate;

        var firstIdx = null, lastIdx = null;
        for (var k = 0; k < data.length; k++) {
            if (data[k][0] >= low && firstIdx === null) {
              firstIdx = k;
            }
            if (data[k][0] <= high) {
              lastIdx = k;
            }
        }
        if (firstIdx === null) firstIdx = 0;
        if (lastIdx === null) lastIdx = data.length - 1;
        
        return [firstIdx, lastIdx]
    }
    
    var stats = function(data, start, end) {
        if (data.length == 0){
            return []
        }
            
        var numcolumns = data[0].length - 1; //The first column is the date, so we don't count that.
        var mins = []; 
        var maxs = [];
        var totals = [];
        for (var col = 0; col < numcolumns; ++col){
            //Deep copy
            var val = (data[start][col + 1]);
            if (val === null){
                mins.push(0); 
                maxs.push(0); 
            } else {
                mins.push(val); 
                maxs.push(val); 
            } 
            totals.push(0);
        }
        
        for (var row = start; row <= end; ++row){
            for (var col = 0; col < numcolumns; ++col){
                var val = data[row][col + 1]
                if (isNaN(val) || (val === null))
                    continue;
                if ((mins[col] > val || isNaN(mins[col]))){
                    mins[col] = val;
                }
                if ((maxs[col] < val || isNaN(maxs[col]))){
                    maxs[col] = val;
                }
                totals[col] += val;
            }
        }
        var means = [];
        for (var col = 0; col < numcolumns; ++col) {
            means.push(totals[col] * 1.0 / (end-start))
        }

        return {min: mins, max: maxs, mean: means, totals: totals}; 
    }
    
    var totalWattsToKwh = function(timeInSecs, numSamples, totalWatts){
        return (totalWatts * 1.0 / numSamples) * (timeInSecs / 3600.0) / 1000.0
    }
    
    var update_stats = function(headings, mins, maxs, means, totals, kwhs){
        if ( headings.length - 1 != mins.length
         ||  headings.length - 1 != maxs.length
         ||  headings.length - 1 != totals.length
         ||  headings.length - 1 != kwhs.length)
        {
            log("update_stats: expect the same number of columns in every one of the arguments", arguments)
            return;     
        }
        
        for (var col = 0; col < headings.length - 1; ++col ){
            var heading = headings[col + 1]
            var head_split = $.trim(heading).split('$')
            if (head_split.length < 2) {
                continue
            }
            
            var name = head_split[0];
            var pk = head_split[1];
            var column_stats;
            var sensor_setup = dashboard_sensors[pk]
            
            if (sensor_setup.unit == "watts") {
                column_stats = {
                    name: name,
                    min: mins[col].toFixed(1),
                    max: maxs[col].toFixed(1),
                    mean: means[col].toFixed(1),
                    total: totals[col].toFixed(1),
                    cost: (kwhs[col] * 20.0).toFixed(1),
                    co2: (kwhs[col] * 0.23).toFixed(2),
                    kwh: kwhs[col].toFixed(1),
                    col: col
                };
            } else {
                column_stats = {
                    name: name,
                    min: mins[col].toFixed(1),
                    max: maxs[col].toFixed(1),
                    mean: means[col].toFixed(1),
//                    total: "",
//                    cost: "",
//                    co2: "",
//                    kwh: "",
                    col: col
                };
            }
                                 
            for (stat in column_stats){
//                log ("update stat", pk + "_" + stat, column_stats[stat]);
                $("." + pk + "_" + stat).html(column_stats[stat])
            }                       
            
            sensor_stats[pk] = column_stats;        
        }
    }
     
    var graphZoomed = function(minDate, maxDate){
        var data=graph.rawData_;
        var indicies = findDates(data, minDate, maxDate)
//        log(indicies, data[indicies[0]], data[indicies[1]])
        var statistics = stats(data, indicies[0], indicies[1])
//        log(statistics.min, statistics.max, statistics.totals)
        
        /*        var num_datapoints = (indicies[1] - indicies[0]); 
        var num_datapoints_shown = num_datapoints / graph.rollPeriod_; 
        if (num_datapoints_shown > 200 || num_datapoints_shown < 100)
        {
            var bestRollPeriod = parseInt((num_datapoints / 150));
            if (bestRollPeriod < 1) {
                bestRollPeriod = 1
            }
            graph.adjustRoll(bestRollPeriod);
        } 
        */
        var kwh = []
        for (total in statistics.totals){
        	if (isNaN(Number(total))) {continue}
        	kwh.push(totalWattsToKwh((maxDate - minDate) / 1000, indicies[1] - indicies[0], statistics.totals[total]))
        }
//        log("totals", kwh)
        update_stats(graph_labels, statistics.min, statistics.max, statistics.mean, statistics.totals, kwh)
    }  
    
    
    var graphLoaded = function(){
        var data=graph.rawData_;
        var indicies = [0, data.length - 1]
        var statistics = stats(data, indicies[0], indicies[1])
        var kwh = []
        for (total in statistics.totals){
        	if (isNaN(Number(total))) {continue}
        	kwh.push(totalWattsToKwh((data[data.length - 1][0] - data[0][0]) / 1000, indicies[1] - indicies[0], statistics.totals[total]))
        }
/*        
        var headings = graph.attrs_.labels
        for (var col = 0; col < headings.length - 1; ++col ){
            var heading = headings[col + 1]
            var head_split = $.trim(heading).split('$')
            if (head_split.length < 2) {
                continue
            }

            var name = head_split[0];
            var pk = head_split[1];

            // Copy colours used elsewhere on the page to be used on the graph too.
            if (dashboard_sensors[pk] && dashboard_sensors[pk]['colour_dark']){
//                graph.colors_[col] = dashboard_sensors[pk]['colour_dark']
                graph.user_attrs_['colors'] = dashboard_sensors[pk]['colour_dark'];
            }            
        }
*/
        graph_labels = ["date"]
        for (var col = 0; col < graph.attrs_.labels.length - 1; ++col ){
            // Remove everything after the $ that seperates the id from the label.
        	var heading = graph.attrs_.labels[col + 1]
            var head_split = $.trim(heading).split('$')
            graph_labels.push(heading)
        	graph.attrs_.labels[col + 1] = head_split[0]
        }
        graph.updateOptions({})
        update_stats(graph_labels, statistics.min, statistics.max, statistics.mean, statistics.totals, kwh)
        $('#main_graph .loader').detach();

        for (sens in dashboard_sensors){
        	if (isNaN(Number(sens))) {continue}

        	var x = function(){
                var sensor = sens;
                $("." + sensor + "_hideshow").click(function(){
                    var column = sensor_stats[sensor]['col']
                    if (column != undefined) {
                        var newVis = !graph.visibility()[column]
                        if (console) {
                            console.log("set", sensor, "col", column, "to", newVis)
                        }
                        
                        graph.setVisibility(column, newVis)
                    }
                    
                })
            }()
        }
    }
    
    var sensor_colours_temp = []; 
    for (sensor in dashboard_sensors){
    	if (isNaN(Number(sensor))) {continue}
        sensor_colours_temp.push(dashboard_sensors[sensor]['colour_dark'])
    }

    interactive_graph = function(){
    	return {
    		zoomCallback: graphZoomed,
    		graphLoaded: graphLoaded,
    		drawCallback: function(graph_instance, is_initial){
							if (is_initial) {
								interactive_graph.graphLoaded();
							}
						  },
            create_graph: function(id, data_url, settings){
            	settings.zoomCallback = graphZoomed;
            	settings.drawCallback = function(graph_instance, is_initial){
									        if (is_initial) {
									            graphLoaded();
									        }
									    };
            	settings.colors = sensor_colours_temp;
            	
            	graph = new DateGraph(document.getElementById(id), data_url , settings);
            	return graph
            },
        };    
    }()
    
    /*
    if ($("demodiv")){
    	interactive_graph("demodiv", minute_data_url, {
		//	        customBars: true,
		//	        labelsDiv: document.getElementById('status'),
		    labelsSeparateLines: true,
		    labelsKMB: true,
		    padding: {left: 40, right: 30, top: 15, bottom: 15},
		    colors:sensor_colours_temp,
		    width: 580,
		    height: 320,
		    gridLineColor: "rgb(200,200,200)",
		    zoomCallback: graphZoomed,
		    drawCallback: function(graph_instance, is_initial){
		        if (is_initial) {
		            graphLoaded();
		        }
		    },
		    labelsDiv: $("#labelsDiv")[0]
		})
    }
    	
    graph = new DateGraph(document.getElementById("demodiv"),
    minute_data_url,
    {
//        customBars: true,
//        labelsDiv: document.getElementById('status'),
        labelsSeparateLines: true,
        labelsKMB: true,
        padding: {left: 40, right: 30, top: 15, bottom: 15},
        colors:sensor_colours_temp,
        width: 700,
        height: 320,
        gridLineColor: "rgb(200,200,200)",
        zoomCallback: graphZoomed,
        drawCallback: function(graph_instance, is_initial){
            if (is_initial) {
                graphLoaded();
            }
        },
        labelsDiv: $("#labelsDiv")[0]
    });
    */
    
})

