// Example NodeJS API Server.
// Type 'npm run dev' to compile is watch mode.
// Type 'npm run devwatch' to run Server.

// Testing API Server
// curl SERVER_ADDRESS:3000/
// curl SERVER_ADDRESS:3000/dfjfdsklj
// curl -X POST --data 'My test message' SERVER_ADDRESS:3000/test

// Log files can be found under the 'logs' directory.
'use strict';
import express from 'express';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import log from './util/logger';

import {connectToDB} from './database/connect-pg';
import {
  initStudentModel,
  createStudentTable,
  getAllStudents,
} from './database/model/student.model';

import {requestLogger} from './middleware/request-logger';
import {ErrorHandler1, ErrorHandler2} from './middleware/error-handlers';
import {AppError} from './util/utils';
import {routerJWT} from './controller/jwt-example';

const SERVER_PORT = Number(process.env.PORT) || 3100;
const SERVER_ADDRESS = '127.0.0.1';
const app = express();

(async () => {
  app.locals.db = await connectToDB('dev', 'yadav', 'yadav');
  initStudentModel(app.locals.db);
  await createStudentTable(app.locals.db);
  await getAllStudents();
})();

log.info(`NODE ENV: ${app.get('env')}`);

// Hide announcing app type to hackers.
app.disable('x-powered-by');

// Middleware: Allow CORS.
app.use(cors());
// Body parsers middleware.
// app.use(express.text());
app.use(express.json());
app.use(express.urlencoded({extended: true}));
app.use(cookieParser());

// Middleware request logger.
app.use(requestLogger);

/* eslint-disable */
app.get('/error', (req, res) => {
  throw new AppError('Throw an error', 400);
});
/* eslint-enable */

app.get('/', (req, res) => {
  res.send('GET: Hello World');
});
app.post('/', (req, res) => {
  res.send('POST: Hello World');
});
app.put('/', (req, res) => {
  res.send('PUT: Hello World');
});
app.delete('/', (req, res) => {
  res.send('DELETE: Hello World');
});

app.use('/api/v1', routerJWT);

// Make sure to define as the last route handler.
// Handle undefined path.
app.all('*', (req, res) => {
  const message = `Interface ${req.originalUrl} not defined`;
  res.status(404).json({
    message: message,
  });
  log.error(message);
});

// Application level error middleware, make sure to define at the end.
app.use(ErrorHandler1);
app.use(ErrorHandler2);

// Start server to put into listen mode.
const server = app.listen(SERVER_PORT, SERVER_ADDRESS, () => {
  process.stdout.write(`Server listening on ${SERVER_ADDRESS}:${SERVER_PORT}`);
  log.info(`Server started, listening ${SERVER_ADDRESS}:${SERVER_PORT}`);
});

// Handling graceful shutdown.
// Perform clean-up here.
process.on('SIGTERM', () => {
  log.error('SIGTERM signal received: shutting down HTTP server');
  process.stderr.write('SIGTERM signal received: shutting down HTTP server');
  server.close(() => {
    log.error('HTTP server closed');
  });
});
