const express = require('express');
const app = express();
const path = require('path');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const config = require('./config');
const base58 = require('./base58.js');
const log4js = require('log4js');
const logger = log4js.getLogger();
const compression = require('compression');
const favicon = require('express-favicon');

logger.level = 'debug';

// grab the url model
const Url = require('./models/url');

let isProduction = false;
let sitePath = 'public/v2';
let indexView = 'index.html';
const listView = 'views/list.html';

process.env.NODE_ENV = process.env.NODE_ENV || 'dev';

if (process.env.NODE_ENV === 'prod') {
  isProduction = true;
  sitePath = 'public/v2';
  indexView = 'index.html';
  config.webhost = 'http://nurl.co/';
}

logger.warn(`isProduction:${isProduction}`);

mongoose.connect(`mongodb://${ config.db.host }/${ config.db.name}`);
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ 'extended': true }));

app.use(express.static(path.join(__dirname, sitePath)));
// app.use(favicon(`${__dirname }/live/favicon-16x16.png`));

app.all('/*', (req, res, next) => {
  // CORS headers
  res.header('Access-Control-Allow-Origin', '*'); // restrict it to the required domain
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  // Set custom headers for CORS
  res.header('Access-Control-Allow-Headers', 'Content-type,Accept,X-Access-Token,X-Key');
  if (req.method === 'OPTIONS')
    res.status(200).end();
  else 
    next();
});

app.use('/.well-known/acme-challenge', express.static('.well-known/acme-challenge'));

app.get('/', function(req, res) {
  res.sendFile(path.join(__dirname, indexView));
});

app.get('/admin/list', function(req, res) {
  res.sendFile(path.join(__dirname, listView));
});

function postShort(req, res) {
  const longUrl = req.body.url;
  let shortUrl = '';
  console.log('Shortening...', longUrl);

  // check if url already exists in database
  Url.findOne({ 'long_url': longUrl }, (err, doc) => {
    if(err) 
      console.error('findone error', err);
    
    if (doc) {
      shortUrl = config.webhost + base58.encode(doc._id);

      // the document exists, so we return it without creating a new entry
      res.send({ 'shortUrl': shortUrl });
    }
    else {
      // since it doesn't exist, let's go ahead and create it:
      const newUrl = Url({
        'long_url': longUrl
      });

      // save the new link
      newUrl.save(function (err) {
        if (err)
          logger.error(err);

        shortUrl = config.webhost + base58.encode(newUrl._id);

        res.send({ 'shortUrl': shortUrl });
      });
    }
  });
}

function getList(req, res) {
  Url.find({}, (err, doc) => {
    if (doc)
      logger.debug(doc);
  });
}

function getEncodedID(req, res) {
  const base58Id = req.params.encoded_id;
  const id = base58.decode(base58Id);

  // check if url already exists in database
  Url.findOneAndUpdate({ '_id': id }, { '$inc': { 'visits': 1 } }, (err, doc) => {
    if (doc) {
      logger.debug(`Redirect: ${doc.long_url}`);
      res.redirect(doc.long_url);
    }
    else
      res.redirect(config.webhost);
  });
}

app.post('/api/v1/shorten', postShort);
app.get('/api/v1/list', getList);
app.get('/:encoded_id', getEncodedID);

// Old pre letsencrypt
const server = app.listen(config.port, () => {
  logger.info(`Server listening on port ${config.port}`);
});


/*

if (require.main === module) 
  app.listen(config.port, () => {
    logger.info(`Server listening on port ${config.port}`);
  });

// Instead do export the app:
module.exports = app;
*/
