var express = require("express");
var hbs = require('express-hbs');
require('handlebars-form-helpers').register(hbs.handlebars);
var nodemailer = require('nodemailer');
var moment = require('moment-timezone');
var fs = require("fs");
var bodyParser = require("body-parser");
var app = express();
var logfile = fs.createWriteStream('./db/log.log', {flags: 'a'});

// Setup email
var transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
        user: 'alertmonitorfl@gmail.com',
        pass: '6g*hkvVc%91oo3#$'
    }
});
var mailOptions = {
    from: 'Alert Monitor <alertmonitorfl@gmail.com>',
    to: 'jody@kaplon.us,don@gettner.com',
    subject: 'Alert received',
    text: 'test alert'  // Get custom text in here with device info.
};


var file = "./db/test.db";
var exists = fs.existsSync(file);

if(!exists) {
    console.log("Creating DB file.");
    fs.openSync(file, "w");
}

var sqlite3 = require("sqlite3").verbose();
var db = new sqlite3.Database(file);

db.serialize(function() {
    if(!exists) {
        db.run(
            "CREATE TABLE Alerts (" +
                "origJSON TEXT," +
                "coreId TEXT," +
                "status TEXT," +
                "published_at TEXT) " +
            "CREATE TABLE Cores (" +
                "coreId TEXT PRIMARY KEY," +
                "coreName TEXT," +
                "locationDesc TEXT)" +
        );
    }
});

app.use(bodyParser.json());                             // Needed for JSON POST requests from Particle Cores.
app.use(bodyParser.urlencoded({ extended: false }));    // Needed for web POST requests from edit form.

// Use `.hbs` for extensions and find partials in `views/partials`.
app.engine('hbs', hbs.express4({
    partialsDir: __dirname + '/views/partials'
}));
app.set('view engine', 'hbs');
app.set('views', __dirname + '/views');

app.get('/', function(req, res){
    var d = new Date();
    console.log("GET /, " + JSON.stringify(d, 4));
    var devIndexQry = 
        "select al.coreId, max(co.coreName) as coreName, max(co.locationDesc) as locationDesc, max(published_at) as MaxPub, max(status) as MaxStatus " +
        "from Alerts al " +
        "left join Cores co on al.coreId = co.coreId " +
        "group by al.coreId;";
    db.all(devIndexQry, function(err, rows){
        if(err !== null) {
            console.log(err);
        } else {
            //console.log(rows);

            // Loop over elements in rows array, convert ugly UTC times to pretty local times.
            rows.forEach(function(row){
                var localDtTm = moment.utc(new Date(row.MaxPub));
                localDtTm = moment(localDtTm).tz('America/New_York').format('MM-DD-YYYY HH:mm:ss');
                row.MaxPub = localDtTm;
                row.MaxPubDate = moment(localDtTm).format('MM-DD-YYYY');
                row.MaxPubTime = moment(localDtTm).format('h:mm:ss a');
            });

            res.render('index', {cores: rows}, function(err, html) {
                if(err !== null) {
                    console.log(err);
                } else {
                    res.send(html);
                }
            });
        }
    });
});

app.get('/core/edit/:id', function(req, res){
    var d = new Date();
    var coreId = req.params.id;
    console.log("GET /core/edit/" + coreId + ", " + JSON.stringify(d, 4));

    db.all("select coreName, locationDesc from Cores where coreId = ?;", coreId, function(err, rows){
    if(err !== null) {
        console.log(err);
    } else {
        res.render('core-edit', {values: rows}, function(err, html) {
            if(err !== null) {
                console.log(err);
            } else {
                res.send(html);
            }
        });
    }
    });
});

app.post('/core/edit/:id', function(req, res){
    var d = new Date();
    var coreId = req.params.id;
    console.log("POST /core/edit/" + coreId + "body: " + JSON.stringify(req.body) + ", " + JSON.stringify(d, 4));
    if (!req.body) {
        return res.sendStatus(400);
    } else {
        // check existence of row in Cores table, if there update, otherwise insert. 
        var existQry = "SELECT coreId FROM Cores WHERE coreId = ?;"
        db.get(existQry, coreId, function(err, row){
            if(err) throw err;
            console.log(typeof row);
            console.log(row);
            if(typeof row == "undefined") {
                var insStmt = db.prepare("INSERT INTO Cores (coreId, coreName, locationDesc) VALUES (?, ?, ?);");
                insStmt.run(
                    coreId,
                    req.body.deviceName,
                    req.body.locationDesc
                );
                insStmt.finalize();
            } else {
                if (req.body.deviceName !== "") {
                    var stmt = db.prepare("UPDATE Cores SET coreName = ? WHERE coreId = ?");
                    stmt.run(
                        req.body.deviceName,
                        coreId
                    );
                    stmt.finalize();
                }

                if (req.body.locationDesc !== "") {
                    var stmt = db.prepare("UPDATE Cores SET locationDesc = ? WHERE coreId = ?");
                    stmt.run(
                        req.body.locationDesc,
                        coreId
                    );
                    stmt.finalize();
                }
            }
        });
        
        res.redirect('https://particle.kaplon.us/');
    }
});

app.get('/core/:id', function(req, res){
    //res.sendFile("/usr/src/app/index.html");
    //fs.createReadStream('./log.log').pipe(res);
    var d = new Date();
    var coreId = req.params.id;
    console.log("GET /core/" + coreId + ", " + JSON.stringify(d, 4));
    var coreMsgQry = "SELECT al.coreId, al.published_at, al.status, co.coreName " +
        "FROM Alerts al left join Cores co on al.coreId = co.coreId " +
        "WHERE al.coreId = ? ORDER BY al.published_at DESC LIMIT 30;"
    db.all(coreMsgQry, coreId, function(err, rows){
        if(err !== null) {
            console.log(err);
        } else {
            //console.log("SELECT coreId, published_at FROM Alerts WHERE coreId = '" + coreId + "' ORDER BY published_at DESC LIMIT 30;");
            //console.log(rows);

            // Loop over elements in rows array, convert ugly UTC times to pretty local times.
            rows.forEach(function(row){
                var localDtTm = moment.utc(new Date(row.published_at));
                localDtTm = moment(localDtTm).tz('America/New_York').format('MM-DD-YYYY HH:mm:ss');
                row.published_at = localDtTm;
                row.pubDate = moment(localDtTm).format('MM-DD-YYYY');
                row.pubTime = moment(localDtTm).format('h:mm:ss a');
            });

            res.render('core', {alerts: rows}, function(err, html) {
                res.send(html);
            });
        }
    });
    //res.send;
});

app.post('/', function(req, res){
    var postEvent = req.body.postEvent;
    var source = req.body.source;
    console.log(req.body);

    var innerDataJSON = JSON.parse(req.body.data);
    var status = JSON.stringify(innerDataJSON.status, null, 4);
    var stmt = db.prepare("INSERT INTO Alerts (OrigJSON, coreid, published_at, status) VALUES (?, ?, ?, ?)");
    stmt.run(   // Use .slice to get rid of leading and trailing double quotes.
        JSON.stringify(req.body, null, 4),
        JSON.stringify(req.body.coreid, null, 4).slice(1,-1),
        JSON.stringify(req.body.published_at, null, 4).slice(1,-1),
        status.slice(1,-1)
    );
    stmt.finalize();

    // Send emails on alerts only
    if(status.toLowerCase().indexOf('alert') > -1){
        mailOptions.text = status;
        transporter.sendMail(mailOptions, function(error, info){
            if(error){
                console.log(error);
            }else{
                console.log('Message sent: ' + info.response);
            }
        });
    }

    //res.send(JSON.stringify(req.body, null, 4));
});

app.listen(3000, function() {
    console.log("Started on PORT 3000");
})