const path = require('path');
const isRoot = require('is-root');
const hostile = require('hostile');
const colors = require('colors');
const docker = require('docker-compose');
const log = require('../inc/log');
const ProjectEnvironment = require('../classes/ProjectEnvironment');

const installHosts = (hosts) => {
  if (!isRoot()) {
    log.warn('Unable to set hosts because you need root privileges');
  } else {
    for (var ip in hosts) {
      const hostsString = hosts[ip].join(' ');

      log.log('Installing hosts for %s: %s', ip, hostsString);
      hostile.set(ip, hostsString);
    }
  }
};

const runServiceStart = (service, projectEnv) => {
  const env = projectEnv.getEnv();
  const scripts = [
    'start.before',
    `start.before.${env}`,
    'start',
    `start.${env}`,
    'start.after',
    `start.after.${env}`,
  ];

  let chain = Promise.resolve();

  scripts.forEach(script => {
    chain = chain.then(() => {
      return new Promise(resolve => {
        try {
          const start = require(path.join(projectEnv.getCwd(), service, script));
          log.log(`\nExecuting %s script for %s...`, colors.bold(script), colors.bold(service));

          Promise
            .all([start({
              exec: (command, options) => {
                const opts = { ...projectEnv.getDockerOptions(), ...options };
                return docker.exec(service, command, opts);
              },
              log: (message) => {
                log.log('%s - %s', colors.bold(service), message);
              },
              env: projectEnv.getEnv()
            })])
            .catch(() => {

            })
            .then(() => {
              resolve();
            });

        } catch (ex) {
          resolve();
        }
      });
    });
  });

  return chain.then(() => {

  });
};

const runServices = async (projectEnv) => {
  await docker.buildAll(projectEnv.getDockerOptions());
  await docker.upAll(projectEnv.getDockerOptions());
  const services = await projectEnv.getServices();
  let promises = [];
  services.forEach(service => {
    promises.push(runServiceStart(service, projectEnv));
  });
  await Promise.all(promises);
};

module.exports = (env) => {
  try {
    const projectEnv = new ProjectEnvironment(process.cwd(), env);

    log.log("Starting project (%s environment)...", colors.bold(env));

    // Install hosts
    installHosts(projectEnv.getHosts());

    // Docker up services
    runServices(projectEnv);

  } catch (ex) {
    log.error(...ex);
  }
};