'use strict';

var Conductor = require('./Conductor/Conductor.js');

const path = require('path');
const File = require('atom').File;
const Project = require('atom').Project;
const Directory = require('atom').Directory;
const Docker = require('dockerode');

const DOCKER_COMPOSE_FILE = 'docker-compose.yml';

const PROTOCOLS = {
  SOCKET: 'unix socket / IPC',
  HTTP: 'http',
  HTTPS: 'https'
};

/**
 * Displays the configuration error which includes a button to go to the package settings.
 */
let showConfigError = () => {
  atom.notifications.addError('Set up your docker variables!', {
    dismissable: true,
    buttons: [
      {
        text: 'Package Settings',
        onDidClick: (context, notification) => {
          atom.workspace.open("atom://config/packages/overture"); // yeah i got this code from `atom-community sync-settings`
        }
      }
    ]
  });
};

/**
 * Shows an error with a message
 * @param  {String} message - the message to include.
 */
let showDockerError = (message) => {
  console.error(message); 
  atom.notifications.addError('There was an error connecting to docker. ' + message);
};

let getDocker = () => {
  let dockerConfig = {
  };

  let socket    = atom.config.get('overture.dockerSocketPath');
  let host      = atom.config.get('overture.dockerHost');
  let port      = atom.config.get('overture.dockerPort');
  let protocol  = atom.config.get('overture.dockerProtocol')
  let key       = atom.config.get('overture.dockerMachineKeyPath');
  let cert      = atom.config.get('overture.dockerMachineCertPath');
  let ca        = atom.config.get('overture.dockerMachineCaPath');

  let isBadDockerConfig = false;

  if(protocol === PROTOCOLS.SOCKET) {
    if(socket) {
      dockerConfig.socketPath = socket;
    }
  } else {
    // need at least port and ip
    if(!host && !port) {
      isBadDockerConfig = true;
    }

    dockerConfig.host = host;
    dockerConfig.port = port;

    if(protocol === 'https') {
      dockerCOnfig.protocol = protocol;
      // https requires SSL certificate
      if(key) {
        if(fs.statSync(key).isFile()) {
          dockerConfig.ca = fs.readFileSync(key);
        }
      }

      if(cert) {
        if(fs.statSync(cert).isFile()) {
          dockerConfig.cert = fs.readFileSync(cert);
        }
      }

      if(ca) {
        if(fs.statSync(dockerConfig.key).isFile()) {
          dockerConfig.key = fs.readFileSync(ca);
        }
      }

      // make sure the files opened...
      if(!(dockerConfig.ca && dockerConfig.cert && dockerConfig.key)) {
        isBadDockerConfig = true;
      }
    }
  }

  if(isBadDockerConfig) {
    showConfigError();
    return null;
  } else {
    console.log(dockerConfig);
    return new Docker(dockerConfig);
  }
};

/**
* Overture is a tool for creating docker workspaces.  Docker workspaces allow users to create isolated instances of applications such as Apache, PHP, Nginx, Redis, and MySQL for development.
* This project focuses on the development aspect of this.  The isolated instances that Docker creates are beneficial to development because working on multiple projects using these same applications
* can become increidbly tedious when dealing with so many different configuration files.
* @constructor
*/
let Overture = function(workspacePath) {
  if(workspacePath === 'undefined' || workspacePath === null) throw "Overture requires a workspace path.";

  /**
  * An instance of dockerode.
  * @type {Object}
  * @see Dockerode
  */
  this.docker = getDocker();
  /**
  * Defines whether this is a workspace or not.  This is determined by the contents (or even existence) of `docker-compose.yml` in the project directory.
  * @type {Boolean}
  */
  this.isWorkspace = false;

  /**
  * The prefix name of the workspace.  This is important for naming our docker containers.  This is determined from docker-compose.yml.  If it is not determined by docker-compose.yml, then a random name is generated.  Probably an unhelpful one.
  * Hopefully you don't kill the wrong container you devops nightmaire.
  * @type {String}
  */
  this.workspaceName = (new Directory(workspacePath)).getBaseName();

  /**
   * The absolute filepath for this workspace.
   * @type {String}
   */
  this.workspacePath = workspacePath;

  /**
  * The file object representing docker-compose.yml
  * @type {Object}
  */
  this.composeFile = null;

  /**
  * The conductor is what actually manages docker-compose and the docker-compose.yml file.
  * @type {Object}
  * @see Conductor
  */
  this.conductor = null;

  /**
  * Initializes overture.  Outside of the prototype so that its not publically exposed.
  * @private
  */
  (() => {
    console.log(path.join(this.workspacePath, DOCKER_COMPOSE_FILE));
    this.composeFile = new File(path.join(this.workspacePath, DOCKER_COMPOSE_FILE));

    if(this.composeFile.existsSync()) {
      this.isWorkspace = true;
      try {
        this.conductor = new Conductor({
          composeFile: this.composeFile,
          prefix: this.workspaceName,
          docker: this.docker,
          onError: showDockerError
        });
      }
      catch(message) {
        showDockerError(message);
      }
    }
  })();
};


module.exports = Overture;
