/*
 * Copyright (C) 2019 StApps
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
import {Logger, SMTP} from '@openstapps/logger';
import config from 'config';
import {existsSync} from 'fs';

// set transport on logger
Logger.setTransport(SMTP.getInstance());

/**
 * A representation of the file paths of the needed ssl certificates
 */
export interface SSLFilePaths {
  /**
   * Path to SSL certificate
   */
  certificate: string;
  /**
   * Path to SSL certificate chain
   */
  certificateChain: string;
  /**
   * Path to SSL certificate key
   */
  certificateKey: string;
  /**
   * Path to SSL DHParam
   */
  dhparam: string;
}

/**
 * Supported log formats for config
 */
type SupportedLogFormatsKeys = 'default' | 'combined' | 'json';

/**
 * Map supported formats to stings used in template view
 */
export const SupportedLogFormats: {[key in SupportedLogFormatsKeys]: string} = {
  default: 'combined',
  combined: 'combined',
  json: 'json',
};

/**
 * A representation of the config file
 */
export interface ConfigFile {
  /**
   * List of active version
   */
  activeVersions: string[];
  /**
   * List of hidden routes
   */
  hiddenRoutes: string[];
  /**
   * Sets log format (default or json)
   */
  logFormat: SupportedLogFormatsKeys;
  /**
   * Enables metrics on /metrics route
   */
  metrics?: boolean;
  /**
   * List of outdated versions
   */
  outdatedVersions: string[];
  /**
   * Path the generated config will be written to
   */
  output: string;
  /**
   * Allow list for rate limiting
   */
  rateLimitAllowList: string[];
  /**
   * SSL file paths
   */
  sslFilePaths: SSLFilePaths;
}

/**
 * A view object to render the nginx config template
 */
export interface TemplateView {
  /**
   * Docker version map
   */
  dockerVersionMap: string;
  /**
   * Hidden routes
   */
  hiddenRoutes: string;
  /**
   * Listener
   */
  listener: string;
  /**
   * Log format to use
   */
  logFormat: string;
  /**
   * Custom Log formatters
   */
  logFormatters: string;
  /**
   * Local server with listener for /metrics route
   */
  metrics: string;
  /**
   * Allow list for rate limiting
   */
  rateLimitAllowList: string;
  /**
   * Static route
   */
  staticRoute: string;
  /**
   * Visible routes
   */
  visibleRoutes: string;
}

/**
 * Nginx protocol parameters to harden serverside settings
 */
export const protocolHardeningParameters = `
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains;";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";`;

// tslint:disable:max-line-length
/**
 * Nginx ssl parameters to harden serverside settings
 */
export const sslHardeningParameters = `
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519:secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;`;

/**
 * Config file
 */
export const configFile: ConfigFile = config.util.toObject();

/**
 * Check if path is a specific file type
 */
export function isFileType(path: string, fileType: string) {
  const regExp = new RegExp(`.*\.${fileType}$`);

  return existsSync(path) && regExp.test(path);
}
