// RockUp
// Config -- Load, read, and manipulate deploy configuration files

var fs = require("fs");
var path = require("path");
var _ = require("underscore");

module.exports = Config;

/**
 * Create an instance of a configuration object for the given environment.
 * Constructing a Config object will search for properly path'ed and named
 * RockUp configuration file and attempt to load that file's configuration
 * into memory.
 *
 * @param {String} environment    Name of the target environment
 **/
function Config (environment) {
  this._environment = environment;
  this._filePath = this._getFilePath();
  this._rawConfig = this._loadFromFile();
  this._config = Config.mergeConfig(this._rawConfig);
}

/**
 * Create local base configuration files for the given application and
 * environment. Places a RockUp configuration 
 *
 * @param {String} appName        Name of the application
 * @param {String} environment    Name of the target environment
 * @param {String[]} files        Array of file types to generate. Valid
 *                                options include 'rockup', 'meteor'
 **/
Config.initialize = function (appName, environment, files) {
  files = _.isUndefined(files) ? ['rockup', 'meteor'] : files;
  var templateDir = path.resolve(__dirname, '..', 'templates');
  var targetDir = path.resolve(process.cwd(), 'deploy');
  var extMap = {
    rockup:   'rockup.json',
    meteor:   'settings.json',
    nginx:    'nginx.conf',
    upstart:  'upstart.conf'
  };

  // Make Directory:
  if ( fs.existsSync(targetDir) ) {
    console.log("Config directory already exists:".yellow, targetDir.cyan.bold);
  } else {
    console.log("Creating config directory:".yellow, targetDir.cyan.bold);
    fs.mkdirSync( targetDir );
  }

  // Copy desired template files into target directory:
  _.each(extMap, function( ext, type ) {
    if ( _.findWhere(files, type) ) {
      var basename = environment+"."+ext;                     // e.g., "staging.rockup.json"
      var source = path.resolve(templateDir, ext);
      var target = path.resolve(targetDir, basename);
      if ( fs.existsSync(target) ) {
        console.log("Config for", type, "already exists.".yellow, "Skipping.".red);
      } else {
        console.log("Creating config for", type, "from template".yellow, basename.cyan.bold);
        copyFile(source, target);
      }
    } else {
      console.log("Skipping", type, "configuration. Not requested.");
    }
  });

  console.log("Rockup project local config initialized".bold.green);

  function copyFile(src, dest) {
    var content = fs.readFileSync(src, 'utf8');
    fs.writeFileSync(dest, content);
  }

};

/**
 * Return path the RockUp configuration files directoy. This is expected to be
 * /deploy underneath the script invocation/working directory.
 **/
Config.prototype._getFileDir = function () {
  return path.resolve( process.cwd(), "deploy" );
};

/**
 * Return path to the RockUp configuration JSON file. The expected file naming
 * convention is "{environment}.rockup.json", so "production.rockup.json" for an
 * environment named production, "dev.rockup.json" for an environment named dev.
 **/
Config.prototype._getFilePath = function () {
  var basename = this._environment+".rockup.json";
  return path.resolve( this._getFileDir, basename );
};

/**
 * Loads the RockUp configuration for this environment from the expected source
 * location. Will throw exception if file cannot be found or if JSON parsing fails.
 **/
Config.prototype._loadFromFile = function () {
  var filePath = this._getFilePath();
  if ( fs.existsSync(filePath) ) {
    // Loan the JSON configuration:
    try {
      return require(filePath);
    } catch (jsonErr) {
      throw new Error("Error loading JSON config: "+jsonErr);
    }
  } else {
    throw new Error("RockUp configuration file not found. Run `rock init`.");
  }
};

/**
 * Builds the true configuration by merging defaults into the host- and
 * service-specific definitions.
 **/
Config.mergeConfig = function ( rawConfig ) {
  var config = _.extend({}, rawConfig);
  _.each(config.hosts, function(host, idx) {
    host = _.defaults(host, rawConfig.defaults.hosts);
    host.confs = _.defaults({}, host.confs, rawConfig.defaults.confs);
    _.each(host.services, function(service, idx) {
      service.env = _.defaults({}, service.env, rawConfig.defaults.env);
    });
  });
  delete config.defaults;
  return config;
};

/**
 * Return a list of hosts with fully populated configuration
 */
Config.prototype.hosts = function () {
  return this._config.hosts;
};

/**
 * Return a list of configured host names.
 **/
Config.prototype.hostNames = function () {
  return _.pluck(this.hosts(), 'name');
};

/**
 * Return a list of services for a specified host with a fully populated configuration
 **/
Config.prototype.services = function ( hostName ) {
  var host = _.findWhere(this.hosts(), {name: hostName});
  return host.services;
};

/**
 * Return a list of the service names for a given host.
 **/
Config.prototype.serviceNames = function ( hostName ) {
  return _.pluck(this.services(hostName), 'name');
};

/**
 * Return the specific configuration for the named service on the named host
 **/
Config.prototype.service = function ( hostName, serviceName ) {
  return _.where(this.services(hostName), {name: serviceName});
};

@@ -1024,13 +1024,15 @@
 te. 
-Valid
+Default
 %0A * 
@@ -1496,14 +1496,23 @@
  // 
-Make D
+Create deploy d
 irec
@@ -1864,25 +1864,23 @@
  if ( _.
-f
 ind
-Where
+exOf
 (files, 
@@ -1884,16 +1884,21 @@
 s, type)
+ %3E -1
  ) %7B%0A   
@@ -3293,16 +3293,18 @@
 tFileDir
+()
 , basena

Fix two bugs with file path and types for init