var express = require("express");
var hbs = require('express-hbs');
require('handlebars-form-helpers').register(hbs.handlebars);
var bodyParser = require("body-parser");
var app = express();
var winston = require('winston');
winston.add(winston.transports.File, { filename: './logs/notes.kaplon.us.log', maxsize: 5000000 });  // 5MB
var fileSystem = require('fs');
var passport = require('passport');
var Strategy = require('passport-local').Strategy;
var db = require('./db');

// Configure the local strategy for use by Passport.
// The local strategy require a `verify` function which receives the credentials
// (`username` and `password`) submitted by the user.  The function must verify
// that the password is correct and then invoke `cb` with a user object, which
// will be set at `req.user` in route handlers after authentication.
passport.use(new Strategy(
  function(username, password, cb) {
    db.users.findByUsername(username, function(err, user) {
      winston.info('trying to lookup user.');
      if (err) { winston.info('db.users.findByUsername error.'); return cb(err); }
      if (!user) { winston.info('bad user'); return cb(null, false); }
      if (user.password != password) { winston.info('bad pw'); return cb(null, false); }
      return cb(null, user);
    });
  }));
// Configure Passport authenticated session persistence.
//
// In order to restore authentication state across HTTP requests, Passport needs
// to serialize users into and deserialize users out of the session.  The
// typical implementation of this is as simple as supplying the user ID when
// serializing, and querying the user record by ID from the database when
// deserializing.
passport.serializeUser(function(user, cb) {
  cb(null, user.id);
});
passport.deserializeUser(function(id, cb) {
  db.users.findById(id, function (err, user) {
    if (err) { return cb(err); }
    cb(null, user);
  });
});


// 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.use(express.static('assets'));
app.use(require('cookie-parser')());
app.use(bodyParser.text());   // Use defaults for now, size limit is 100kb.
app.use(bodyParser.urlencoded({ extended: true }));   // Also need url encoding to handle login form.
app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false }));
var notePath = __dirname + '/note-data/allNotes.txt';

// Initialize Passport and restore authentication state, if any, from the session.
app.use(passport.initialize());
app.use(passport.session());

// As with any middleware it is quintessential to call next() if the user is authenticated
var isAuthenticated = function (req, res, next) {
    if (req.isAuthenticated()) {
        return next();
        res.redirect('/');
    } else {
        // If user NOT authenticated, redirect to login page, do not call next().
        res.redirect('/login');
    }
}

app.get('/', isAuthenticated, function(req, res){
    winston.info("GET /");
    // Get curent text from allNotes.txt and pass that data to handlebars template.
    fileSystem.readFile(notePath, {encoding: 'utf-8'}, function(err,data){
        if (!err){
            winston.info('successful file read');
            res.render('index', {notetxt: data}, function(err, html) {
                if(err !== null) {
                    winston.error(err);
                } else {
                    res.send(html);
                }
            });
        }else{
            winston.error(err);
        }
    });
});

app.post('/', isAuthenticated, function(req, res){
    winston.info('POST received');
    var now = Date.now();
    // quick/dirty poc is to do a fileSystem.write to create a new file w/contents of req.body!
    //fileSystem.writeFile(__dirname + '/note-data/test-' + now + '.txt', req.body, function(err){
        //if (err) { winston.error(err); }
        //winston.info('new test file written');
    //});
    // Overwrite allNotes.txt with new contents from client.
    fileSystem.readFile(notePath, 'utf-8', function(err, data){
        if (err) { 
            winston.error(err); 
        } else {
            fileSystem.writeFile(notePath, req.body, 'utf-8', function(err) {
                if (err) { winston.error(err); }
                winston.info('new contents from client written to allNotes.txt');
                var exec = require('child_process').exec;
                var cmd = 'cd note-data && git commit -am "Notes modified via POST request, ' + now + '"';
                winston.info(cmd);
                exec(cmd, function(error, stdout, stderr) {
                    if (error) { winston.error(error); }
                    winston.info(stdout);
                });
            });
        }
    });
    // Stage and commit changes to allNotes.txt.
    res.status(204).send('POST received');
});

app.get('/login', function(req, res){
    winston.info('GET /login');
    res.render('login');
});
  
app.post('/login', 
  passport.authenticate('local', { failureRedirect: '/login' }),
  function(req, res) {
    winston.info('sucessful login');
    res.redirect('/');
});
  
app.get('/logout', function(req, res){
    req.logout();
    res.redirect('/');
});

app.listen(3000, function() {
    winston.info("Started on PORT 3000");
});