// Load the Visualization API and the corechart package.
google.charts.load('current', {'packages':['corechart', 'table']});
 
colors = ['green', 'yellow', 'orange', 'red', 'maroon', '#AAAAAA', '#555555', 'black'];
 
Date.prototype.daysInMonth = function () {
    return new Date(this.getFullYear(), this.getMonth() + 1, 0).getDate();
}
 
Date.prototype.format = function (show_day) {
    var daystr = '';
    if (show_day) {
        daystr = "0" + this.getDate();
        daystr = '-' + daystr.substr(daystr.length - 2);
    }
    var monstr = "0" + (this.getMonth() + 1);
    monstr = monstr.substr(monstr.length - 2);
    return this.getFullYear() + '-' + monstr + daystr;
}
 
function draw_chart(func, city, year, month, months, data, id) {
    var msg;
    try {
        msg = func(city, year, month, months, data, id);
        if (msg)
            document.getElementById(id + '_a').innerHTML += msg;
    } catch(err) {
        document.getElementById(id + '_a').innerHTML = err.message;
    }
}
 
//////////////////////////////
//
// Chart functions
//
//////////////////////////////
 
function summary_data(in_data, year, month) {
    var titles = ["1-50", "51-100", "101-150", "151-200",
                  "201-300", "301-400", "401-500", "Over 500"];
    var cutoffs = [0, 50, 100, 150, 200, 300, 400, 500, 9999];
    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    titles.forEach(function (i) { data.addColumn('number', i);});
 
    var date = start = new Date(year, month, 1);
    var missing = 0;
    var stats = 0;
    var end_ptr = 0;
    for (var i = 0; true; i++) {
        if (i == end_ptr) {
            if (stats)
                data.addRow(stats);
            stats = [date, 0, 0, 0, 0, 0, 0, 0, 0];
            date = new Date(year, ++month, 1);
            end_ptr = (date - start)/3600000;
        }
        if (i >= in_data.length)
            break;
        if (!in_data[i])
            missing++;
        else {
            for (var j = 1; 1; j++) {
                if (in_data[i] < cutoffs[j]) {
                    stats[j]++;
                    break;
                }
            }
        }
    }
    return {data: data, missing: missing, total: in_data.length,
            start: start.format(), finish: stats[0].format()};
}
    
function summary_chart(city, year, month, months, data, id) {
    var dataobj = summary_data(data, year, month);
    // Set chart options
    var options = {title:'PM2.5 Summary for ' + city + ' from ' + dataobj.start + ' to ' + dataobj.finish,
                   width:1000,
                   height:600,
                   legend: {position: 'bottom'},
                   colors: colors,
                   isStacked: 'percent',
                   reverseCategories: true,
                   //'bar': {groupWidth: '90%'},
                   hAxis: {gridlines: {count: 10}},
                   vAxis: {gridlines: {count: months}},
                   chartArea: {left:90, width:'90%'}
                  };
    var chart = new google.visualization.BarChart(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return 'Total readings: ' + dataobj.total + ', Missed readings: ' + dataobj.missing;
}
 
function green_data(in_data) {
    var missing = 0;
    var cutoffs = [0, 50, 100, 150, 200, 300, 400, 500, 9999];
    var entries = cutoffs.map(function(e, i) { return [e.toString(), 0]; });
    entries[0] = [{label: 'Reading', type: 'string'}, {label: 'Days', type: 'number'}];
    in_data.forEach(function(i) {
        if (i[1]) {
            for (var j = 1; j < cutoffs.length; j++) {
                if (i[1] < cutoffs[j]) {
                    entries[j][1]++;
                    break;
                }
            }
        }
        else
            missing++;
    });
    var data = new google.visualization.arrayToDataTable(entries);
    return {data: data, days: in_data.length, missing: missing};
}
            
function green_chart(city, year, month, months, data, id) {
    var dataobj = green_data(data);
    var options = {title:'Green Air Days for ' + city
                   + ' from ' + new Date(year, month, 1).format() + ' to ' + new Date(year, month + months, 1).format(),
                   width:600,
                   pieSliceText: 'value',
                   height:600,
                   enableInteractivity: true,
                   chartArea: {left: 20, top: 50, width: '90%', height: '90%'},
                   legend: {alignment: 'center'},
                   colors: colors};
 
    var chart = new google.visualization.PieChart(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return 'Total days: ' + dataobj.days + ', No readings: ' + dataobj.missing;
}
 
 
function daily_data(in_data, year, month) {
    if (!in_data[0][0]) {
        var titles = [{label: 'Day', type: 'date'},
                      {label: 'High', type: 'number'},
                      {label: 'Average', type: 'number'},
                      {label: 'Low', type: 'number'}];
        
        var day = 1, count = 0, totals = [0, 0, 0];
        in_data.forEach(function(i) {
            if (!i[0])
                i[0] = new Date(year, month, day++);
            if (i[1]) {
                count++;
                totals[0] += i[1];
                totals[1] += i[2];
                totals[2] += i[3];
            }
            else
                i[1] = i[2] = i[3] = 0;
        });
        var data = new google.visualization.DataTable();
        titles.forEach(function (i) { data.addColumn(i); });
        data.addRows(in_data);
        _daily_data = {data: data,
                       total: in_data.length,
                       missing: in_data.length - count,
                       start: in_data[1][0].format(1),
                       finish: in_data[in_data.length - 1][0].format(1),
                       averages: [totals[0]/count, totals[1]/count, totals[2]/count]
                      };
    }
    return _daily_data;
}
 
function daily_chart(city, year, month, months, data, id) {
    var colors = ['red', 'yellow', 'green'];
    dataobj = daily_data(data, year, month);
    // Set chart options
    var options = {title:'PM2.5 Daily High/Average/Low for ' + city + ' from '
                   + dataobj.start + ' to ' + dataobj.finish,
                   width:1000,
                   height:600,
                   legend: {position: 'bottom'},
                   colors: colors,
                   areaOpacity: 1.0,
                   hAxis: {gridlines: {count: 12}},
                   vAxis: {ticks: [0, 100, 200, 300, 400, 500, 600, 700]},
                   chartArea: {left:90, width:'90%'}
                  };
    var chart = new google.visualization.AreaChart(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return 'Total days: ' + dataobj.total + ', No readings: ' + dataobj.missing
        + '\n<br>Average high: ' + dataobj.averages[0].toFixed(2)
        + '; Average average: '  + dataobj.averages[1].toFixed(2)
        + '; Average low: '  + dataobj.averages[2].toFixed(2);
}
 
function extremes_data(in_data, year, month) {
    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    var titles = ['High', 'Average', 'Low', 'Highest low', 'Lowest high', 'Missing'];
    titles.forEach(function(i) {data.addColumn('number', i); });
    if (typeof in_data[0][0] === 'string' || in_data[0][0] instanceof String)
        in_data.forEach(function (i) { i[0] = new Date(i[0] + '-01'); });
    data.addRows(in_data);
    var missing = 0;
    in_data.forEach(function(i) { missing += i[6]; });
    var start = new Date(year, month, 1);
    var finish = new Date(year, month + months, 1);
    return {data: data, total: (finish - start)/(3600*1000), missing: missing,
            start: start.format(), finish: finish.format()};
}
 
function extremes_chart(city, year, month, months, data, id) {
    var colors = ['red', 'blue', 'green', 'orange', 'purple', 'cyan'];
    var dataobj = extremes_data(data, year, month);
    // Set chart options
    var options = {title:'PM2.5 Daily Extremes for ' + city + ' from '
                   + dataobj.start + ' to ' + dataobj.finish,
                   width:1000,
                   height:600,
                   legend: {position: 'bottom'},
                   colors: colors,
                   areaOpacity: 1.0,
                   hAxis: {gridlines: {count: 12}},
                   vAxis: {ticks: [0, 100, 200, 300, 400, 500, 600, 700]},
                   chartArea: {left:90, width:'90%'}
                  };
    var chart = new google.visualization.LineChart(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return 'Total readings: ' + dataobj.total + ' (' + dataobj.total/24 + ' days), No readings: ' + dataobj.missing;
}
 
function table_data(in_data) {
    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Month');
    var titles = ['High', 'Average', 'Low', 'Highest low', 'Lowest high', 'Missing'];
    titles.forEach(function(i) {data.addColumn('number', i); });
    if (typeof in_data[0][0] === 'string' || in_data[0][0] instanceof String)
        in_data.forEach(function (i) { i[0] = new Date(i[0] + '-01'); });
    data.addRows(in_data);
    return {data: data, start: in_data[0][0].format(), finish: new Date(in_data[in_data.length - 1][0].format())};
}
 
function table_chart(city, year, month, months, data, id) {
    var dataobj = table_data(data);
    // Set chart options
    var options = {showRowNumber: true,
                   sortColumn: 2
                  };
    var chart = new google.visualization.Table(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return '';
}
 
function thresh_data(in_data, year, month, months) {
    var data = new google.visualization.DataTable();
    data.addColumn('date', 'Start date');
    var titles = ['Start hour', 'Hours', 'Readings', 'Highest', 'Lowest'];
    titles.forEach(function(i) {data.addColumn('number', i); });
    if (typeof in_data[0][0] === 'string' || in_data[0][0] instanceof String)
        in_data.forEach(function (i) { i[0] = new Date(i[0]); });
    data.addRows(in_data);
    var start = new Date(year, month, 1);
    var finish = new Date(year, month + months, 1);
    var total_hours = (finish - start)/3600000;
    var hours = 0;
    in_data.map(function (x) { hours += x[2]; return hours; });
    return {data: data, entries: in_data.length, hours: hours, percent: (100*hours/total_hours).toFixed(2)};
}
 
function thresh_chart(city, year, month, months, data, id) {
    var dataobj = thresh_data(data, year, month, months);
    // Set chart options
    var options = {showRowNumber: true,
                   sortColumn: 0
                  };
    var chart = new google.visualization.Table(document.getElementById(id));
    chart.draw(dataobj.data, options);
    return dataobj.entries + ' streaks totalling ' + dataobj.hours + ' hours (' + dataobj.percent + '% of the interval)';
}