import http = require('http');
import { ImportSystem } from './import-system.class';
import { wait, generateId } from "./lib";
import { $Middleware, $Route, $Handler, $ErrorHandler } from './models.lib';

export class Application extends ImportSystem {

  constructor(params) {
    super();

    this.readonly([
      'init',
      'run',
      'rest',
      'route',
      'routes',
      'baseDir',
      'root'
    ]);

    this.name = params.name;
    this.root = params.root;
    this.filepath = params.path;
    let path = params.path.split('/');

    path.pop();

    this.baseDir = path.join('/');

    this.controllersManager.set('path', `${this.baseDir}/controllers`); // set path to controllers
    this.modelsManager.set('path', `${this.baseDir}/models`); // set path to models
    this.router.set('path', `${this.baseDir}/routes`); // set path to routes
    this.router.set('basePath', this.filepath);

    global['AZTEC']['APPS'][this.name] = this;

    this.init();
  }

  run(): void {
    this.controllers = this.requireAndCreate(this, 'controllers', true,);
    this.models = this.requireAndCreate(this, 'models', true,);
    this.require('routes');
    this.router.mergeAppRoutes(this.root);
    this.router.mergeRoutes();
  }

  rest(path: string, handler: $Handler): this {
    this.router.rest(path, handler);
    return this;
  }

  route(route: $Route): this {
    this.router.useRoute(route);
    return this;
  }

  routes(rootPath: string, routes: $Route[]): this {
    this.router.useRoutes(rootPath, routes);
    return this;
  }

  private init() {
    wait('for options', () => {
      if (require(this.filepath)) this.run();
    });
  }

  protected id: string = generateId();
  protected name: string;
  protected root: string;
  protected filepath: string;
  protected baseDir: string;
  protected guardian: $Middleware;

  protected ['error-handler']: $ErrorHandler;

}