var gauge = new Gauge($('#gauge')[0]);
var websock;
var timeseries = {};
var charts = {};

$(document).ready(function(event) {
    setupGauge('staticZones');
    //setupGauge('percentColors');
    startWebsocket();
});

var metrics = {
    "iaq": {name: "IAQ", has_accuracy: true, decimals: 0},
    "siaq": {name: "Static IAQ", has_accuracy: true, decimals: 0},
    "eco2": {name: "CO2", unit: " ppm", has_accuracy: true, decimals: 0},
    "bvoc": {name: "Breath VOC", unit: " ppm", has_accuracy: true, decimals: 3},
    "pm1": {name: "PM ≤1.0µm", unit: " μg/m³"},
    "pm2p5": {name: "PM ≤2.5µm", unit: " μg/m³"},
    "pm10": {name: "PM ≤10µm", unit: " μg/m³"},
    "nc0p3": {name: "NC ≥0.3µm", unit: "/100cm³"},
    "nc0p5": {name: "NC ≥0.5µm", unit: "/100cm³"},
    "nc1": {name: "NC ≥1.0µm", unit: "/100cm³"},
    "nc2p5": {name: "NC ≥2.5µm", unit: "/100cm³"},
    "nc5": {name: "NC ≥5.0µm", unit: "/100cm³"},
    "nc10": {name: "NC ≥10µm", unit: "/100cm³"},
    "temperature": {name: "Temperature", unit: " °C", decimals: 1},
    "humidity": {name: "Humidity", unit: "%", decimals: 1},
    "pressure": {name: "Pressure", unit: " hPa", decimals: 0}
}

var accuracyStatus = {
    0: {name: "Stabilizing", class: "danger"},
    1: {name: "Uncertain", class: "warning"},
    2: {name: "Calibrating", class: "primary"},
    3: {name: "Calibrated", class: "success"}
}

var gaugeOptions = {
    angle: 0, // The span of the gauge arc
    lineWidth: 0.45, // The line thickness
    radiusScale: 1, // Relative radius
    pointer: {
        length: 0.5, // // Relative to gauge radius
        strokeWidth: 0.100, // The thickness
        color: '#000000' // Fill color
    },
    colorStart: '#6F6EA0',   // Colors
    colorStop: '#C0C0DB',    // just experiment with them
    strokeColor: '#EEEEEE',  // to see which ones work best for you
    generateGradient: true,
    highDpiSupport: true,     // High resolution support
    staticLabels: {
      font: "10px sans-serif",  // Specifies font
      labels: [50, 100, 150, 200, 250, 350, 500],  // Print labels at these values
      color: "#000000",  // Optional: Label text color
      fractionDigits: 0  // Optional: Numerical precision. 0=round off.
    }
};

var gaugeModes = {
    staticZones: [
       {strokeStyle: "#01E400", min: 0, max: 50}, // Bright Green
       {strokeStyle: "#92D050", min: 51, max: 100}, // Green 
       {strokeStyle: "#FFFF00", min: 101, max: 150}, // Yellow
       {strokeStyle: "#FF7E00", min: 151, max: 200}, // Orange
       {strokeStyle: "#FF0000", min: 201, max: 250}, // Red
       {strokeStyle: "#99004C", min: 251, max: 350}, // Violet
       {strokeStyle: "#663300", min: 351, max: 500}  // Brown
    ],
    percentColors: [
        [0.0, "#01E400" ],
        [0.1, "#92D050" ],
        [0.2, "#FFFF00"],
        [0.3, "#FF7E00"],
        [0.4, "#FF0000"],
        [0.5, "#99004C"],
        [0.7, "#663300"]
    ]
}

var chartOptions = {
    responsive: true,
    millisPerPixel: 100,
    grid: {
        fillStyle:'rgba(255,255,255, 1)',
        strokeStyle:'rgba(128,128,128, 0.10)',
        verticalSections: 5
    },
    labels: {
        fillStyle:'rgba(0,0,0,0.75)'
    }
}

var lineOptions = {
    lineWidth: 2,
    strokeStyle:'#00ff00'
}

function setupGauge(mode) {
    var objColor = {}
    objColor[mode] = gaugeModes[mode];
    var opt = Object.assign(gaugeOptions, objColor);
    gauge.setOptions(opt);
    gauge.setMinValue(0);
    gauge.maxValue = 500;
    gauge.animationSpeed = 128;
    gauge.set(0);
}

function startWebsocket() {
    websock = new WebSocket('ws://' + window.location.hostname + ':81/');
    websock.onopen = function(evt) {
        console.log('websock open');
        $('#wsSpinner').invisible();
    };
    websock.onclose = function(evt) {
        console.log('websock close');
        websock = null;
        $('#wsSpinner').visible();
        setTimeout(startWebsocket, 1000);
    };
    websock.onerror = function(evt) {
        console.log(evt);
    };
    websock.onmessage = function(evt) {
        data = JSON.parse(evt.data);
        //console.log(data);
        if (data !== null) {
            handleWebsocketMessage(data);
        }
    };
}

function handleWebsocketMessage(data) {
    if ('siaq' in data) {
        gauge.set(data.siaq);
    }
    $.each(metrics, function(name, sensor) {
        if ('has_accuracy' in metrics[name]) {
            updateMetric(name, data[name], data[name+'_acc']);
        } else {
            updateMetric(name, data[name], false);
        }
    });
}

function updateMetric(name, value, accuracy) {
    var numericValue = value;
    if ('decimals' in metrics[name]) {
        value = value.toFixed(metrics[name].decimals);
    }
    if ('unit' in metrics[name]) {
        value += metrics[name].unit;
    }
    if (accuracy !== false && accuracy < 3) {
        value = '<span class="badge bg-'+accuracyStatus[accuracy].class+'">'+accuracyStatus[accuracy].name+'</span> '+value;
    }
    if(!$('#metric_'+name).length && name in metrics) {
        timeseries[name] = new TimeSeries();
        timeseries[name].append(new Date().getTime(), numericValue);
        var metric = $('<li class="list-group-item list-group-item-action" id="metric_'+name+'">'+
            '<div class="row rowMetric">'+
                '<div class="d-flex w-100 justify-content-between">'+
                    '<div class="sensorName">'+metrics[name].name+'</div>'+
                    '<div class="sensorValue">'+value+'</div>'+
                '</div>'+
            '</div>'+
          '</li>)');
        metric.find('.rowMetric').on('click', function() {
            toggleChart(name);
        });
        $('#metrics').append(metric);        
    } else {
        $('#metric_'+name+' .sensorValue').html(value);
        timeseries[name].append(new Date().getTime(), numericValue);
    }
}

function toggleChart(name) {
    if(!$('#chart_'+name).length) {
        charts[name] = new SmoothieChart(chartOptions);
        charts[name].addTimeSeries(timeseries[name], lineOptions);
        $('#metric_'+name).append($('<div class="row rowChart">'+
            '<div class="chart mt-2"><canvas id="chart_'+name+'"></canvas></div>'+
        '</div>'));
        charts[name].streamTo(document.getElementById("chart_"+name), 1000);
    } else {
        charts[name].removeTimeSeries(timeseries[name]);
        charts[name].stop();
        delete charts[name];
        $('#metric_'+name+' .rowChart').remove();
    }
}

jQuery.fn.visible = function() {
    return this.css('visibility', 'visible');
};

jQuery.fn.invisible = function() {
    return this.css('visibility', 'hidden');
};