import express from 'express';
import bodyParser from 'body-parser';
import helmet from 'helmet';
import { Server as HTTPServer } from 'http';
import { Collection, ServerManagement, Route } from '.';

export default class Server {
  public app: express.Application;

  public routes: Collection<Route>;

  public parent: ServerManagement;

  public port: number;

  private root: string;

  protected parse: boolean;

  constructor(parent: ServerManagement, port: number, routeRoot: string, parse = true) {
    this.parent = parent;
    this.app = express();
    this.routes = new Collection<Route>();
    this.port = port;
    this.root = routeRoot;

    this.parse = parse;

    this.init();
    this.loadRoutes();
  }

  get client() {
    return this.parent.client;
  }

  public async loadRoutes() {
    const routes = Object.values<typeof Route>(require(this.root));
    for (const RouteFile of routes) {
      const route = new RouteFile(this);
      if (route.conf.deprecated) {
        route.deprecated();
      } else if (route.conf.maintenance) {
        route.maintenance();
      } else {
        route.init();
        route.bind();
      }
      this.parent.client.util.signale.success(`Successfully loaded route 'http://localhost:${this.port}/${route.conf.path}'.`);
      this.routes.add(route.conf.path, route);
      this.app.use(route.conf.path, route.router);
    }
    this.app.listen(this.port);
  }

  public init() {
    if (this.parse) {
      this.app.use(bodyParser.json());
      this.app.use(bodyParser.urlencoded({ extended: true }));
    }
    this.app.set('trust proxy', 'loopback');
    this.app.use(helmet({
      hsts: false,
      hidePoweredBy: false,
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
        },
      },
    }));
  }

  public listen(port: number): HTTPServer {
    return this.app.listen(port);
  }
}
