Get a configuration based on options.

@param  {Object} options  An optional object with optional parameters:
- dir: defaults to "config".
- env: defaults to "staging".
- base: defaults to "base".
@param  {Object} config   An optional object to populate.
@return {Object}          A fully populated configuration object.
function get (options, config) {
  options = options || found
  config = config || {}

  // Load options.
  var dir = options.dir || found.dir || 'config'
  var env = options.env || found.env || 'staging'
  var base = options.base || found.base || 'base'

  // Allow many "env" values.
  var key = env.toLowerCase()
    .replace(/^([gro]|ca)/, 'p')  // gamma, release, one, canary -> "production".
    .replace(/^(sa|[al])/, 'd')   // sandbox, alpha, local -> "development".
    .replace(/^[qtbcij]/, 's')[0] // qa, test, beta, ci, jenkins -> "staging".

  // Coerce to an expected environment.
  var environment = map[key] || map[key = 's']

  config.env = env
  config.environment = environment
  config.isDebug = /de?bu?g/i.test(env)
  config.isDevelopment = (key === 'd')
  config.isStaging = (key === 's')
  config.isProduction = (key === 'p')

  // Load files.
  hide(config, 'load', load)

  // Load configuration from files.
  config.load(dir, base)
  config.load(dir, environment)

  // Load any matching sub-environments.
  var subEnvironments = config.subEnvironments
  if (subEnvironments && subEnvironments.indexOf(env) > -1) {
    config.load(dir, env)
  }

  return config
}