'use strict';

const fs = require('fs');
const Promise = require('bluebird');
const path = require('path');
const parseUrl = require('url').parse;
const formatUrl = require('url').format;
const child_process = require('child_process');
const yaml = require('js-yaml');
const _ = require('lodash');
const NotImplemented = require('./errors').NotImplemented;
const CONST = require('./constants');
const filename = process.env.SETTINGS_PATH;

const ENV = process.env.NODE_ENV || 'development';
process.env.NODE_ENV = _
  .chain(ENV)
  .split(/[_-]/)
  .first()
  .value();
const buffer = fs.readFileSync(filename, 'utf8');
const context = {
  require: require,
  __filename: filename,
  __dirname: path.dirname(filename),
  base64_template: function (filePath) {
    const template = path.join(this.__dirname, filePath);
    return fs.readFileSync(template).toString('base64');
  },
  certificate: function (name) {
    const filename = path.join(this.__dirname, 'certs', name);
    return JSON.stringify(fs.readFileSync(filename).toString('ascii'));
  }
};
const config = yaml.safeLoad(_.template(buffer)(context))[ENV];
config.directors.forEach(director => completeDirectorConfig(director));
loadActionScripts(config.actions);
if (process.env.worker) {
  updateLogFileConfig(config.log_path);
}
completeDockerConfig(config.docker);
completeCloudFoundryConfig(config.cf);
if (config.enable_circuit_breaker) {
  //Tests fail because of circuits tripping because of negative scenarios.
  const hystrixConfig = require('hystrixjs').hystrixConfig;
  hystrixConfig.init({
    // any other hystrix options...
    'hystrix.promise.implementation': Promise
  });
  completeCircutBreakerConfig(config);
} else {
  console.log('circuit breaker is disabled');
}

function loadActionScripts(actions) {
  function ensureDirectoryExist(filePath) {
    const dirname = path.dirname(filePath);
    if (fs.existsSync(dirname)) {
      return true;
    }
    ensureDirectoryExist(dirname);
    fs.mkdirSync(dirname);
  }

  function writeActionFile(template, filePath) {
    ensureDirectoryExist(filePath);
    fs.writeFileSync(filePath, Buffer.from(template, 'base64'), {
      mode: CONST.FILE_PERMISSIONS.RWX_R__R__
    });
  }

  _.forEach(actions, (template, actionScriptName) => {
    let extension = actionScriptName.split('.').pop();
    if (extension === actionScriptName) {
      writeActionFile(template, path.join(__dirname, 'fabrik/actions/sh', `${actionScriptName}`));
    } else if (extension === 'js') {
      writeActionFile(template, path.join(__dirname, 'fabrik/actions/js', `${actionScriptName}`));
    } else {
      throw new NotImplemented(`file type ${extension} is not supported`);
    }
  });
}

function updateLogFileConfig(logPath) {
  const logSuffix = `-worker-${process.env.worker}.log`;
  config.log_path = logPath.indexOf('.log') !== -1 ? logPath.replace('.log', logSuffix) : `${logPath}-${logSuffix}`;
}

function completeDirectorConfig(director) {
  if (!director.uuid || !director.cpi) {
    const options = ['--connect-timeout 5', '-s'];
    if (director.skip_ssl_validation) {
      options.push('-k');
    }
    if (director.username) {
      options.push(`-u ${director.username}:${director.password}`);
    }
    const info = JSON.parse(child_process.execSync(`curl ${options.join(' ')} ${director.url}/info`));
    _.defaults(director, {
      uuid: info.uuid,
      cpi: info.cpi
    });
  }
}

function completeDockerConfig(docker) {
  const opts = {
    ip_local_port_range: ipLocalPortRange(docker.ip_local_port_range)
  };
  const dockerUrl = docker.url || process.env.DOCKER_HOST;
  if (dockerUrl) {
    const url = parseUrl(dockerUrl);
    if (!url.protocol || url.protocol === 'unix:') {
      opts.socketPath = url.pathname;
    } else {
      opts.host = url.hostname;
      opts.port = url.port;
      opts.protocol = url.protocol.replace(/:$/, '');
      if (opts.protocol === 'tcp') {
        if (process.env.DOCKER_TLS_VERIFY === '1' || opts.port === 2376) {
          opts.protocol = 'https';
        } else {
          opts.protocol = 'http';
        }
      }
    }
  }
  //const dockerCertPath = docker.cert_path || process.env.DOCKER_CERT_PATH;
  if (process.env.DOCKER_TLS_VERIFY === '1') {
    opts.ca = [
      docker.ssl.ca
    ];
    opts.cert = docker.ssl.cert;
    opts.key = docker.ssl.key;
  }
  _.defaults(docker, opts);
}

function completeCloudFoundryConfig(cf) {
  const endpoint = parseUrl(cf.url);
  endpoint.host = undefined;
  const domain = endpoint.hostname.split('.').slice(1).join('.');
  const authorization_endpoint = formatUrl(_.assign({}, endpoint, {
    hostname: `login.${domain}`
  })).replace(/\/$/, '');
  const token_endpoint = formatUrl(_.assign({}, endpoint, {
    hostname: `uaa.${domain}`
  })).replace(/\/$/, '');
  _.defaults(cf, {
    authorization_endpoint: authorization_endpoint,
    token_endpoint: token_endpoint
  });
}


function ipLocalPortRange(portRange) {
  if (_.isArray(portRange)) {
    return portRange;
  }
  if (!/^\s*\d+\s+\d+\s*$/.test(portRange)) {
    try {
      portRange = fs.readFileSync('/proc/sys/net/ipv4/ip_local_port_range', 'ascii');
    } catch (err) {
      portRange = '32768 61000';
    }
  }
  return _.compact(_.split(portRange, /\s+/));
}

function completeCircutBreakerConfig(config) {
  const configFileName = 'circuit-breaker-config.yml';
  const circuitBreakerConfigAbsPath = process.env.CONF_DIR ? path.join(process.env.CONF_DIR, configFileName) :
    path.join(__dirname, '..', 'config', configFileName);
  if (fs.existsSync(circuitBreakerConfigAbsPath)) {
    config.circuit_breaker = yaml.safeLoad(fs.readFileSync(circuitBreakerConfigAbsPath, 'utf8'));
  } else {
    console.log('Circuit break config not found. Hystrix will not be configured.');
  }
}

module.exports = config;
@@ -295,105 +295,8 @@
 ');%0A
-const NotImplemented = require('./errors').NotImplemented;%0Aconst CONST = require('./constants');%0A
 cons
@@ -335,16 +335,16 @@
 S_PATH;%0A
+
 %0Aconst E
@@ -1091,43 +1091,8 @@
 ));%0A
-loadActionScripts(config.actions);%0A
 if (
@@ -1562,16 +1562,16 @@
  else %7B%0A
+
   consol
@@ -1615,960 +1615,8 @@
 %0A%7D%0A%0A
-function loadActionScripts(actions) %7B%0A  function ensureDirectoryExist(filePath) %7B%0A    const dirname = path.dirname(filePath);%0A    if (fs.existsSync(dirname)) %7B%0A      return true;%0A    %7D%0A    ensureDirectoryExist(dirname);%0A    fs.mkdirSync(dirname);%0A  %7D%0A%0A  function writeActionFile(template, filePath) %7B%0A    ensureDirectoryExist(filePath);%0A    fs.writeFileSync(filePath, Buffer.from(template, 'base64'), %7B%0A      mode: CONST.FILE_PERMISSIONS.RWX_R__R__%0A    %7D);%0A  %7D%0A%0A  _.forEach(actions, (template, actionScriptName) =%3E %7B%0A    let extension = actionScriptName.split('.').pop();%0A    if (extension === actionScriptName) %7B%0A      writeActionFile(template, path.join(__dirname, 'fabrik/actions/sh', %60$%7BactionScriptName%7D%60));%0A    %7D else if (extension === 'js') %7B%0A      writeActionFile(template, path.join(__dirname, 'fabrik/actions/js', %60$%7BactionScriptName%7D%60));%0A    %7D else %7B%0A      throw new NotImplemented(%60file type $%7Bextension%7D is not supported%60);%0A    %7D%0A  %7D);%0A%7D%0A%0A
 func

Add config