// server.js

// env variables
require('dotenv').config();
// fs
var fs = require('fs');
// Async
var async = require("async");
// Express etc
var sslRedirect = require('heroku-ssl-redirect');
var express = require('express');
var path = require('path');
var serveStatic = require('serve-static');
var request = require('request');
var cors = require('cors');
var bodyParser = require('body-parser');
// Cron
var CronJob = require('cron').CronJob;
// Github API
var octokit = require('@octokit/rest')();
if(typeof process.env.GITHUB_OAUTH_TOKEN != 'undefined') {
  octokit.authenticate({
    type: 'oauth',
    token: process.env.GITHUB_OAUTH_TOKEN
  });
}
// Redis
var redis = require("redis"),
redisClient = redis.createClient(process.env.REDISCLOUD_URL);
// Slack
if(typeof process.env.SLACK_WEBHOOK_URL != 'undefined') {
  var Slack = require('slack-node');
  var slack = new Slack();
  slack.setWebhook(process.env.SLACK_WEBHOOK_URL);
}

app = express();

// enable ssl redirect
app.use(sslRedirect());

app.use(serveStatic(__dirname + "/content/.vuepress/dist"));

app.use(cors());

var textParser = bodyParser.text({
  limit: '256kb'
});

var jsonParser = bodyParser.json();

app.post('/forward', jsonParser, function(req, res) {

  var allowedMethods = ["wallet_send", "resolve", "publish"];

  if(typeof req.body.method != "undefined") {

    if(allowedMethods.includes(req.body.method)) {

      // We should whitelist the query parameters here

      if(req.body.method == "wallet_send") {

        // Hardcode the wallet_send amount to be always 0.01 always
        req.body.amount = 0.01;

        // Whitelist claim ids
        var allowedClaims = ["fbdcd44a97810522d23d5f1335b8ca04be9d776c", "de7f7fa33e8d879b2bae7238d2bdf827a39f9301", "5b7c7a202201033d99e1be2930d290c127c0f4fe", "a1372cf5523885f5923237bfe522f02f5f054362"];

        if(!allowedClaims.includes(req.body.claim_id)) {
          res.json({});
        }

      }

      if(req.body.method == "publish") {

        // Hardcode the publish amount to be always 0.001 always
        req.body.bid = 0.001;

        // Fix the internal image path in daemon
        req.body.file_path = process.env.LBRY_DAEMON_IMAGES_PATH + req.body.file_path;

      }

      req.body.access_token = process.env.LBRY_DAEMON_ACCESS_TOKEN;

      request({
        url: "http://daemon.lbry.tech",
        qs: req.body
      }, function(error, response, body) {
        // Should we filter the body parameters before forwarding to user?
        body = JSON.parse(body);
        if(typeof body.error != "undefined") {
          logSlackError('ERROR: Got error from daemon: ' + JSON.stringify(body.error));
        }
        res.json(body);
      });

    }

  }

});

app.get('/github-feed', function(req, res) {

  redisClient.zrevrange('events', 0, 9, function(err, reply) {

    var events = [];

    reply.forEach(function(item) {
      events.push(JSON.parse(item));
    });
    
    res.json(events);

  });

});

app.post('/upload-image', textParser, function(req, res) {

  request({
    method: "PUT",
    url: "http://daemon.lbry.tech/images.php",
    headers: {
      'Content-Type': 'text/plain'
    },
    qs: {
      access_token: process.env.LBRY_DAEMON_ACCESS_TOKEN
    },
    body: req.body,
  }, function(error, response, body) {
    body = JSON.parse(body);
    res.json(body);
  });

});

app.get('/*', function(req, res) {

  if(fs.existsSync(__dirname + "/content/.vuepress/dist" + req.path + ".html")) {
    res.redirect(req.path + ".html");
  } else {
    res.status(404);
    res.send('Not found');
  }

});

var port = process.env.PORT || 8080;
app.listen(port);

logSlackError('Server started at port ' + port);

function updateGithubFeed() {

  octokit.activity.getEventsForOrg({
    org: 'lbryio',
    per_page: 20,
    page: 1
  }).then(function({data}) {

    async.eachSeries(data, function(item, callback) {

      var eventString = JSON.stringify(item);

      redisClient.zrank('events', eventString, function(err, reply) {
        
        if(reply == null) {

          redisClient.zadd('events', item.id, eventString, callback);

        } else {

          callback();

        }

      });

    }, function() {

      // Keep the latest 50 events
      redisClient.zremrangebyrank('events', 0, -51);

      console.log('Updated Github feed');

    });

  }).catch(function(err) {

    logSlackError('ERROR: Couldnt update Github feed: ' + JSON.stringify(err));

  });

}

function logSlackError(text) {

  if(typeof slack != 'undefined') {

    slack.webhook({
      channel: 'dottech-errors',
      username: 'lbrytech-bot',
      text: text
    }, function(err, response) {

    });

  }

}

// Update Github feed every minute
new CronJob("0 * * * * *", updateGithubFeed, null, true, 'America/Los_Angeles');

module.exports = app;