require('dotenv').config({ path: '.env' });
import { NestFactory } from '@nestjs/core';
import cloudConfigClient from 'cloud-config-client';
import { AppModule } from './app.module';
import { setupSwagger } from './swagger';
import { config } from './config';
import { Logger, ValidationPipe, BadRequestException } from '@nestjs/common';
<%_ if (!skipClient) { _%>
import * as fs from 'fs';
<%_ } _%>
<%_ if (authenticationType === 'oauth2') { _%>
import passport = require('passport');
import session = require('express-session');
<%_ } _%>
const logger: Logger = new Logger('Main');
const port = process.env.NODE_SERVER_PORT || config.get('server.port');
const useJHipsterRegistry = config.get('eureka.client.enabled');

async function bootstrap(): Promise<void> {
  loadCloudConfig();
  registerAsEurekaService();

  const appOptions = { cors: true };
  const app = await NestFactory.create(AppModule, appOptions);
  app.useGlobalPipes(
    new ValidationPipe({
      exceptionFactory: (): BadRequestException  => new BadRequestException('Validation error'),
      // https://github.com/nestjs/nest/issues/10683#issuecomment-1349614194
      forbidUnknownValues: false,
    }),
  );
  // Disable cache.
  app.getHttpAdapter().getInstance().set('etag', false);

  <%_ if (authenticationType === 'oauth2') { _%>
  app.use(
    session({
      secret: config.get('jhipster.security.session.secret'),
      resave: false,
      saveUninitialized: true,
      cookie: { secure: false, maxAge: 240000 }, // 4 minutes and session expires
    }),
  );

  app.use(passport.initialize());
  app.use(passport.session());

  app.use((req: any, res: any, next: any) => {
    if (req.session.user == null && req.path.indexOf(config.get('jhipster.swagger.path')) === 0) {
        return res.redirect('/oauth2/authorization/oidc');
    }
    next();
  });
  <%_ } _%>

  <%_ if (!skipClient) { _%>
  const staticClientPath = config.getClientPath();
  if (fs.existsSync(staticClientPath)) {
    logger.log(`Serving static client resources on ${staticClientPath}`);
  } else {
    logger.log(`No client it has been found`);
  }
  <%_ } else { _%>
    logger.log(`The client is not been generated`);
  <%_ } _%>
  setupSwagger(app);

  await app.listen(port);
  logger.log(`Application listening on port ${port}`);
}

async function loadCloudConfig(): Promise<void> {
  if (useJHipsterRegistry) {
    const endpoint = config.get('cloud.config.uri') || 'http://admin:admin@localhost:8761/config';
    logger.log(`Loading cloud config from ${endpoint}`);

    const cloudConfig = await cloudConfigClient.load({
      context: process.env,
      endpoint,
      name: config.get('cloud.config.name'),
      profiles: config.get('cloud.config.profile') || ['prod'],
      // auth: {
      //   user: config.get('jhipster.registry.username') || 'admin',
      //   pass: config.get('jhipster.registry.password') || 'admin'
      // }
    });
    config.addAll(cloudConfig.properties);
  }
}

function registerAsEurekaService(): void {
  if (useJHipsterRegistry) {
    logger.log(`Registering with eureka ${config.get('cloud.config.uri')}`);
    const Eureka = require('eureka-js-client').Eureka;
    const eurekaUrl = require('url').parse(config.get('cloud.config.uri'));
    const client = new Eureka({
      instance: {
        app: config.get('eureka.instance.appname'),
        instanceId: config.get('eureka.instance.instanceId'),
        hostName: config.get('ipAddress') || 'localhost',
        ipAddr: config.get('ipAddress') || '127.0.0.1',
        status: `UP`,
        port: {
           $: port,
          '@enabled': 'true',
        },
        vipAddress: config.get('ipAddress') || 'localhost',
        homePageUrl: `http://${config.get('ipAddress')}:${port}/`,
        dataCenterInfo: {
          '@class': 'com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo',
           name : 'MyOwn',
        },
      },
      eureka: {
        // eureka server host / port
        host: eurekaUrl.hostname || '127.0.0.1',
        port: eurekaUrl.port || 8761,
        servicePath: '/eureka/apps',
      },
      requestMiddleware: (requestOpts, done): any => {
        requestOpts.auth = {
          user: config.get('jhipster.registry.username') || 'admin',
          password: config.get('jhipster.registry.password') || 'admin',
        };
        done(requestOpts);
      },
    });
    client.logger.level('debug');
    client.start(error => logger.log(error || 'Eureka registration complete'));
  }
}

bootstrap();
