// @ts-nocheck
process.env.TZ = "Etc/GMT";

console.log("Loading ketr.ketran");

import express from "express";
import bodyParser from "body-parser";
import config from "config";
import session from 'express-session';
import basePath from "./basepath";
import cookieParser from "cookie-parser";
import fs from 'fs';
import http from "http";

const app = express();

const server = http.createServer(app);

app.use(cookieParser());

// Simple request logger for debugging base-path routing issues. Logs method
// and URL for requests under the configured basePath so we can trace which
// service (server or dev proxy) is handling requests and their returned
// status during debugging. Keep this lightweight.
app.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
  try {
    const bp = app.get("basePath") || '/';
    if (req.url && req.url.indexOf(bp) === 0) {
      console.log(`[server] ${req.method} ${req.url}`);
      // also log after response finishes
      res.on('finish', () => {
        console.log(`[server] ${req.method} ${req.url} -> ${res.statusCode}`);
      });
    }
  } catch (e) {
    // ignore logging errors
  }
  next();
});

import expressWs from 'express-ws';
expressWs(app, server);

require("./console-line"); /* Monkey-patch console.log with line numbers */

const frontendPath = (config.get("frontendPath") as string).replace(/\/$/, "") + "/",
  serverConfig = config.get("server") as any;

console.log("Hosting server from: " + basePath);

let userDB: any, gameDB: any;

app.use(bodyParser.json());

/* App is behind an nginx proxy which we trust, so use the remote address
 * set in the headers */
app.set("trust proxy", true);

app.set("basePath", basePath);
app.use(basePath, require("./routes/basepath.js"));

// Temporary debug routes
try {
  app.use(basePath, require("./routes/debug.js"));
} catch (e) {
  console.error('Failed to mount debug routes:', e && e.stack || e);
}

/* Handle static files first so excessive logging doesn't occur */
app.use(basePath, express.static(frontendPath, { index: false }));

const index = require("./routes/index");

if (config.has("admin")) {
  const admin = config.get("admin");
  app.set("admin", admin);
}

/* Allow loading of the app w/out being logged in */
app.use(basePath, index);

/* /games loads the default index */
app.use(basePath + "games", index);

/* Allow access to the 'users' API w/out being logged in */
/*
const users = require("./routes/users");
app.use(basePath + "api/v1/users", users.router);
*/

app.use(function(err: any, req: express.Request, res: express.Response, next: express.NextFunction) {
  console.error(err.message);
  res.status(err.status || 500).json({
    message: err.message,
    error: {}
  });
});

app.use(`${basePath}api/v1/games`, require("./routes/games"));

/* Declare the "catch all" index route last; the final route is a 404 dynamic router */
app.use(basePath, index);

/**
 * Create HTTP server and listen for new connections
 */
app.set("port", serverConfig.port);

process.on('SIGINT', () => {
  console.log("Gracefully shutting down from SIGINT (Ctrl-C) in 2 seconds");
  setTimeout(() => process.exit(-1), 2000);
  server.close(() => process.exit(1));
});

import { initGameDB } from './routes/games/store';

initGameDB().then(function(db) {
  gameDB = db;
}).then(function() {
  return require("./db/users").then(function(db) {
    userDB = db;
  });
}).then(function() {
  console.log("DB connected. Opening server.");
  server.listen(serverConfig.port, () => {
    console.log(`http/ws server listening on ${serverConfig.port}`);
  });
}).catch(function(error) {
  console.error(error);
  process.exit(-1);
});

server.on("error", function(error: any) {
  if (error.syscall !== "listen") {
    throw error;
  }

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case "EACCES":
      console.error(serverConfig.port + " requires elevated privileges");
      process.exit(1);
      break;
    case "EADDRINUSE":
      console.error(serverConfig.port + " is already in use");
      process.exit(1);
      break;
    default:
      throw error;
  }
});

export { app, server };
