               next()
         , (err) ->
           callback err, roots
+
+# Convenience wrapper for constructing paths to subdirectories of
+# `~/Library`.
+libraryPath = (args...) ->
+  path.join process.env.HOME, "Library", args...
+
+# Strip a trailing `domain` from the given `host`, then generate a
+# sorted array of possible entry names for finding which application
+# should serve the host. For example, a `host` of
+# `asset0.37s.basecamp.test` will produce `["asset0.37s.basecamp",
+# "37s.basecamp", "basecamp"]`, and `basecamp.test` will produce
+# `["basecamp"]`.
+getFilenamesForHost = (host, domain) ->
+  if host.slice(-domain.length - 1) is ".#{domain}"
+    parts  = host.slice(0, -domain.length - 1).split "."
+    length = parts.length
+    for i in [0...length]
+      parts.slice(i, length).join "."
+  else
+    []

fs       = require "fs"
path     = require "path"
async    = require "async"
Logger   = require "./logger"
{mkdirp} = require "./util"

getFilenamesForHost = (host, domain) ->
  if host.slice(-domain.length - 1) is ".#{domain}"
    parts  = host.slice(0, -domain.length - 1).split "."
    length = parts.length
    for i in [0...length]
      parts.slice(i, length).join "."
  else
    []

libraryPath = (args...) ->
  path.join process.env.HOME, "Library", args...

module.exports = class Configuration
  constructor: (options = {}) ->
    @dstPort  = options.dstPort  ? 80
    @httpPort = options.httpPort ? 20559
    @dnsPort  = options.dnsPort  ? 20560
    @timeout  = options.timeout  ? 15 * 60 * 1000
    @workers  = options.workers  ? 2
    @domain   = options.domain   ? "test"
    @hostRoot = options.hostRoot ? libraryPath "Application Support", "Pow", "Hosts"
    @logRoot  = options.logRoot  ? libraryPath "Logs", "Pow"
    @loggers  = {}

  getLogger: (name) ->
    @loggers[name] ||= new Logger path.join @logRoot, name + ".log"

  findApplicationRootForHost: (host, callback) ->
    @gatherApplicationRoots (err, roots) =>
      return callback err if err

          return callback null, root
      callback null

  # Asynchronously build a mapping of entries in `hostRoot` to
  # application root paths. For each symlink, store the symlink's name
  # and the real path of the application it points to. For each
  # directory, store the directory's name and its full path. The
  # mapping is passed as an object to the second argument of
  # `callback`. If an error is raised, `callback` is called with the
  # error as its first argument.
  #
  # The mapping object will look something like this:
  #
  #     {
  #       "basecamp":  "/Volumes/37signals/basecamp",
  #       "launchpad": "/Volumes/37signals/launchpad",
  #       "37img":     "/Volumes/37signals/portfolio"
  #     }
  gatherApplicationRoots: (callback) ->
    roots = {}
    mkdirp @hostRoot, (err) =>
