const url = require("url");
const express = require("express");

import Arena from 'bull-arena';
import { TF_APPLY_QUEUE, TF_APPLY_QSEOK_QUEUE, TF_DESTROY_QUEUE, STOP_CONTAINER_QUEUE } from 'qmi-cloud-common/queues';

const app = express();
const routesApiScenarios = require('./routes/api-scenarios');
const routesApiUsers = require('./routes/api-users');
const routesApiProvisions = require('./routes/api-provisions');
const routesApiDestroyProvisions = require('./routes/api-destroyprovisions');
const routesApiNotifications = require('./routes/api-notifications');
const routesApiDivvy = require('./routes/api-divvy');
const routesApiDeployOpts = require('./routes/api-deployopts')
const routesApiApikeys = require('./routes/api-apikeys')
const routesApiStats = require('./routes/api-stats')
const swaggerUi = require('swagger-ui-express');
const swaggerJsdoc = require('swagger-jsdoc');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const https = require('https');
const fs = require('fs');
const path = require('path');

const passport = require('./passport');

function _getRedisConfig(redisUrl) {
  const redisConfig = url.parse(redisUrl);
  return {
    host: redisConfig.hostname || 'localhost',
    port: Number(redisConfig.port || 6379),
    database: (redisConfig.pathname || '/0').substr(1) || '0',
    password: redisConfig.auth ? redisConfig.auth.split(':')[1] : undefined
  };
}


app.use('/arena', Arena(
  {
    queues: [
      {
        name: TF_APPLY_QUEUE,
        hostId: 'Worker',
        redis: _getRedisConfig(process.env.REDIS_URL)
      },
      {
        name: TF_APPLY_QSEOK_QUEUE,
        hostId: 'Worker',
        redis: _getRedisConfig(process.env.REDIS_URL)
      },
      {
        name: TF_DESTROY_QUEUE,
        hostId: 'Worker',
        redis: _getRedisConfig(process.env.REDIS_URL)
      },
      {
        name: STOP_CONTAINER_QUEUE,
        hostId: 'Worker',
        redis: _getRedisConfig(process.env.REDIS_URL)
      }
    ]
  },
  {
    basePath: '/',
    disableListen: true
  }
));


//-----------------------------------------------------------------------------
// Config the app, include middlewares
//-----------------------------------------------------------------------------
//app.set('views', __dirname + '/views');
//app.set('view engine', 'ejs');
app.use(cookieParser());
// parse application/json
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())

app.use('/',express.static(__dirname + '/../dist/qmi-cloud'));

passport.init(app);

app.use("/api/v1/scenarios", routesApiScenarios);
app.use("/api/v1/users", routesApiUsers);
app.use("/api/v1/provisions", routesApiProvisions);
app.use("/api/v1/destroyprovisions", routesApiDestroyProvisions);
app.use("/api/v1/notifications", routesApiNotifications);
app.use("/api/v1/divvy", routesApiDivvy);
app.use("/api/v1/deployopts", routesApiDeployOpts);
app.use("/api/v1/apikeys", routesApiApikeys);
app.use("/api/v1/stats", routesApiStats);

function _isAllowedPath(path){
  const allowedPaths = [ '/api-docs', '/arena', '/costexport', '/backendlogs', '/photos/user/' ];
  let isAllowed = false;
  for (let i=0; i<allowedPaths.length; i++) {
    if ( path.startsWith( allowedPaths[i]) ) {
      isAllowed = true;
      break;
    }
  }
  return isAllowed;
}

/* Checking allowedPaths */
app.get('/*',(req, res, next) =>{  
  if ( _isAllowedPath(req.originalUrl) ) {
    return next();
  } else {
    res.sendFile(path.join(__dirname,'/../dist/qmi-cloud/index.html'));
  }
});
/* -----------------------*/

app.get('/login', passport.ensureAuthenticatedDoLogin, function(req, res) {
  res.redirect("/");
});

app.get('/logout', function(req, res) {
  res.redirect("/");
});

app.get('/backendlogs', function (req, res) {
  res.redirect(process.env.BACKEND_LOGS_URL);
})


const options = {
  definition: {
    openapi: "3.0.3",
    // Like the one described here: https://swagger.io/specification/#infoObject
    info: {
      title: 'QMI Cloud  - API',
      version: '1.0.0',
      description: 'REST API for QMI Cloud solutions',
      contact: {
        "name": "Qlik GEAR",
        "email": "DL-Enterprise-ArchitectsGEAR@qlik.com"
      }
    },
    servers: [{
        "url": "/api/v1",
        "description": "Production Server"
    }],
    components: {
      securitySchemes: {
        ApiKeyAuth: {
          type: "apiKey",
          name: "apiKey",
          in: "query"
        } 
      }
    },
    security: [{
        ApiKeyAuth: []
    }]
  },
  // List of files to be processes. You can also set globs './routes/*.js'
  apis: [
    'server/routes/api-*.js'
  ]
};


app.use('/costexport*', passport.ensureAuthenticatedAndAdmin, function(req, res){
  if ( !req.query.file ) {
    res.status(404).send("Not found");
  } else {
    res.header("Content-Type",'application/json');
    res.sendFile(path.resolve(__dirname, '..', 'costexport', req.query.file ));
  }
} );


app.use('/photos/user/:oid', passport.ensureAuthenticated, function(req, res){
  if ( !req.params.oid ) {
    res.status(404).send("Not found");
  } else {   
    var pic = path.resolve(__dirname, '..', 'photos', `${req.params.oid}.jpg` ); 
    if (fs.existsSync(pic)){
      res.sendFile(pic);
    } else {
      res.status(404).send();
    }
  }
} );

const specs = swaggerJsdoc(options);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));

/**
 * Create necessary folders
 */

var dirs = ['/logs', '/logs/provision', '/logs/destroy', '/costexports', '/photos'];
dirs.forEach(d => {
  if (!fs.existsSync(d)){
    console.log(`--- Creating folder '${d}' since it does not exist`);
    fs.mkdirSync(d);
  }
});


/**
 * Start App
 */
app.listen(3000, () => {
  console.log(`Server listening on port 3000`)
});

if ( process.env.CERT_PFX_PASSWORD && process.env.CERT_PFX_FILENAME) {
  var optionsHttps = {
    pfx: fs.readFileSync(path.resolve(__dirname, 'certs', process.env.CERT_PFX_FILENAME)),
    passphrase: process.env.CERT_PFX_PASSWORD
  };

  https.createServer(optionsHttps, app).listen(3100, function(){
    console.log(`Secure server listening on port 3100`);
  });
}


