// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library pub.barback.asset_environment;

import 'dart:async';
import 'dart:io';

import 'package:barback/barback.dart';
import 'package:path/path.dart' as path;
import 'package:watcher/watcher.dart';

import '../cached_package.dart';
import '../entrypoint.dart';
import '../exceptions.dart';
import '../io.dart';
import '../log.dart' as log;
import '../package.dart';
import '../package_graph.dart';
import '../sdk.dart' as sdk;
import '../source/cached.dart';
import '../utils.dart';
import 'admin_server.dart';
import 'barback_server.dart';
import 'dart_forwarding_transformer.dart';
import 'dart2js_transformer.dart';
import 'load_all_transformers.dart';
import 'pub_package_provider.dart';
import 'source_directory.dart';

/// The entire "visible" state of the assets of a package and all of its
/// dependencies, taking into account the user's configuration when running pub.
///
/// Where [PackageGraph] just describes the entrypoint's dependencies as
/// specified by pubspecs, this includes "transient" information like the mode
/// that the user is running pub in, or which directories they want to
/// transform.
class AssetEnvironment {
  /// Creates a new build environment for working with the assets used by
  /// [entrypoint] and its dependencies.
  ///
  /// HTTP servers that serve directories from this environment will be bound
  /// to [hostname] and have ports based on [basePort]. If omitted, they
  /// default to "localhost" and "0" (use ephemeral ports), respectively.
  ///
  /// Loads all used transformers using [mode] (including dart2js if
  /// [useDart2JS] is true).
  ///
  /// This will only add the root package's "lib" directory to the environment.
  /// Other directories can be added to the environment using [serveDirectory].
  ///
  /// If [watcherType] is not [WatcherType.NONE] (the default), watches source
  /// assets for modification.
  ///
  /// If [packages] is passed, only those packages' assets are loaded and
  /// served.
  ///
  /// If [entrypoints] is passed, only transformers necessary to run those
  /// entrypoints are loaded. Each entrypoint is expected to refer to a Dart
  /// library.
  ///
  /// Returns a [Future] that completes to the environment once the inputs,
  /// transformers, and server are loaded and ready.
  static Future<AssetEnvironment> create(Entrypoint entrypoint,
      BarbackMode mode, {WatcherType watcherType, String hostname, int basePort,
      Iterable<String> packages, Iterable<AssetId> entrypoints,
      bool useDart2JS: true}) {
    if (watcherType == null) watcherType = WatcherType.NONE;
    if (hostname == null) hostname = "localhost";
    if (basePort == null) basePort = 0;

    return entrypoint.loadPackageGraph().then((graph) {
      log.fine("Loaded package graph.");
      graph = _adjustPackageGraph(graph, mode, packages);
      var barback = new Barback(new PubPackageProvider(graph));
      barback.log.listen(_log);

      var environment = new AssetEnvironment._(graph, barback, mode,
          watcherType, hostname, basePort);

      return environment._load(entrypoints: entrypoints, useDart2JS: useDart2JS)
          .then((_) => environment);
    });
  }

  /// Return a version of [graph] that's restricted to [packages] (if passed)
  /// and loads cached packages (if [mode] is [BarbackMode.DEBUG]).
  static PackageGraph _adjustPackageGraph(PackageGraph graph,
      BarbackMode mode, Iterable<String> packages) {
    if (mode != BarbackMode.DEBUG && packages == null) return graph;
    packages = (packages == null ? graph.packages.keys : packages).toSet();

    return new PackageGraph(graph.entrypoint, graph.lockFile,
        new Map.fromIterable(packages, value: (packageName) {
      var package = graph.packages[packageName];
      if (mode != BarbackMode.DEBUG) return package;
      var cache = path.join('.pub/deps/debug', packageName);
      if (!dirExists(cache)) return package;
      return new CachedPackage(package, cache);
    }));
  }

  /// The server for the Web Socket API and admin interface.
  AdminServer _adminServer;

  /// The public directories in the root package that are included in the asset
  /// environment, keyed by their root directory.
  final _directories = new Map<String, SourceDirectory>();

  /// The [Barback] instance used to process assets in this environment.
  final Barback barback;

  /// The root package being built.
  Package get rootPackage => graph.entrypoint.root;

  /// The graph of packages whose assets and transformers are loaded in this
  /// environment.
  ///
  /// This isn't necessarily identical to the graph that's passed in to the
  /// environment. It may expose fewer packages if some packages' assets don't
  /// need to be loaded, and it may expose some [CachedPackage]s.
  final PackageGraph graph;

  /// The mode to run the transformers in.
  final BarbackMode mode;

  /// The [Transformer]s that should be appended by default to the root
  /// package's transformer cascade. Will be empty if there are none.
  final _builtInTransformers = <Transformer>[];

  /// How source files should be watched.
  final WatcherType _watcherType;

  /// The hostname that servers are bound to.
  final String _hostname;

  /// The starting number for ports that servers will be bound to.
  ///
  /// Servers will be bound to ports starting at this number and then
  /// incrementing from there. However, if this is zero, then ephemeral port
  /// numbers will be selected for each server.
  final int _basePort;

  /// The modified source assets that have not been sent to barback yet.
  ///
  /// The build environment can be paused (by calling [pauseUpdates]) and
  /// resumed ([resumeUpdates]). While paused, all source asset updates that
  /// come from watching or adding new directories are not sent to barback.
  /// When resumed, all pending source updates are sent to barback.
  ///
  /// This lets pub serve and pub build create an environment and bind several
  /// servers before barback starts building and producing results
  /// asynchronously.
  ///
  /// If this is `null`, then the environment is "live" and all updates will
  /// go to barback immediately.
  Set<AssetId> _modifiedSources;

  AssetEnvironment._(this.graph, this.barback, this.mode,
        this._watcherType, this._hostname, this._basePort);

  /// Gets the built-in [Transformer]s that should be added to [package].
  ///
  /// Returns `null` if there are none.
  Iterable<Transformer> getBuiltInTransformers(Package package) {
    // Built-in transformers only apply to the root package.
    if (package.name != rootPackage.name) return null;

    // The built-in transformers are for dart2js and forwarding assets around
    // dart2js.
    if (_builtInTransformers.isEmpty) return null;

    return _builtInTransformers;
  }

  /// Starts up the admin server on an appropriate port and returns it.
  ///
  /// This may only be called once on the build environment.
  Future<AdminServer> startAdminServer([int port]) {
    // Can only start once.
    assert(_adminServer == null);

    // The admin server is bound to one before the base port by default, unless
    // it's ephemeral in which case the admin port is too.
    if (port == null) port = _basePort == 0 ? 0 : _basePort - 1;

    return AdminServer.bind(this, _hostname, port)
        .then((server) => _adminServer = server);
  }

  /// Binds a new port to serve assets from within [rootDirectory] in the
  /// entrypoint package.
  ///
  /// Adds and watches the sources within that directory. Returns a [Future]
  /// that completes to the bound server.
  ///
  /// If [rootDirectory] is already being served, returns that existing server.
  Future<BarbackServer> serveDirectory(String rootDirectory) {
    // See if there is already a server bound to the directory.
    var directory = _directories[rootDirectory];
    if (directory != null) {
      return directory.server.then((server) {
        log.fine('Already serving $rootDirectory on ${server.url}.');
        return server;
      });
    }

    // See if the new directory overlaps any existing servers.
    var overlapping = _directories.keys.where((directory) =>
        path.isWithin(directory, rootDirectory) ||
        path.isWithin(rootDirectory, directory)).toList();

    if (overlapping.isNotEmpty) {
      return new Future.error(
          new OverlappingSourceDirectoryException(overlapping));
    }

    var port = _basePort;

    // If not using an ephemeral port, find the lowest-numbered available one.
    if (port != 0) {
      var boundPorts = _directories.values.map((directory) => directory.port)
          .toSet();
      while (boundPorts.contains(port)) {
        port++;
      }
    }

    var sourceDirectory = new SourceDirectory(
        this, rootDirectory, _hostname, port);
    _directories[rootDirectory] = sourceDirectory;

    return _provideDirectorySources(rootPackage, rootDirectory)
        .then((subscription) {
      sourceDirectory.watchSubscription = subscription;
      return sourceDirectory.serve();
    });
  }

  /// Binds a new port to serve assets from within the "bin" directory of
  /// [package].
  ///
  /// Adds the sources within that directory and then binds a server to it.
  /// Unlike [serveDirectory], this works with packages that are not the
  /// entrypoint.
  ///
  /// Returns a [Future] that completes to the bound server.
  Future<BarbackServer> servePackageBinDirectory(String package) {
    return _provideDirectorySources(graph.packages[package], "bin").then(
        (_) => BarbackServer.bind(this, _hostname, 0, package: package,
            rootDirectory: "bin"));
  }

  /// Precompiles all of [packageName]'s executables to snapshots in
  /// [directory].
  ///
  /// If [executableIds] is passed, only those executables are precompiled.
  ///
  /// Returns a map from executable name to path for the snapshots that were
  /// successfully precompiled.
  Future<Map<String, String>> precompileExecutables(String packageName,
      String directory, {Iterable<AssetId> executableIds}) async {
    if (executableIds == null) {
      executableIds = graph.packages[packageName].executableIds;
    }

    log.fine("Executables for $packageName: $executableIds");
    if (executableIds.isEmpty) return [];

    var package = graph.packages[packageName];
    var server = await servePackageBinDirectory(packageName);
    try {
      var precompiled = {};
      await waitAndPrintErrors(executableIds.map((id) async {
        var basename = path.url.basename(id.path);
        var snapshotPath = path.join(directory, "$basename.snapshot");
        var result = await runProcess(Platform.executable, [
          '--snapshot=$snapshotPath',
          server.url.resolve(basename).toString()
        ]);
        if (result.success) {
          log.message("Precompiled ${_formatExecutable(id)}.");
          precompiled[path.withoutExtension(basename)] = snapshotPath;
        } else {
          throw new ApplicationException(
              log.yellow("Failed to precompile ${_formatExecutable(id)}:\n") +
              result.stderr.join('\n'));
        }
      }));

      return precompiled;
    } finally {
      // Don't await this future, since we have no need to wait for the server
      // to fully shut down.
      server.close();
    }
  }

  /// Returns the executable name for [id].
  ///
  /// [id] is assumed to be an executable in a bin directory. The return value
  /// is intended for log output and may contain formatting.
  String _formatExecutable(AssetId id) =>
      log.bold("${id.package}:${path.basenameWithoutExtension(id.path)}");

  /// Stops the server bound to [rootDirectory].
  ///
  /// Also removes any source files within that directory from barback. Returns
  /// the URL of the unbound server, of `null` if [rootDirectory] was not
  /// bound to a server.
  Future<Uri> unserveDirectory(String rootDirectory) {
    log.fine("Unserving $rootDirectory.");
    var directory = _directories.remove(rootDirectory);
    if (directory == null) return new Future.value();

    return directory.server.then((server) {
      var url = server.url;
      return directory.close().then((_) {
        _removeDirectorySources(rootDirectory);
        return url;
      });
    });
  }

  /// Gets the source directory that contains [assetPath] within the entrypoint
  /// package.
  ///
  /// If [assetPath] is not contained within a source directory, this throws
  /// an exception.
  String getSourceDirectoryContaining(String assetPath) =>
      _directories.values
          .firstWhere((dir) => path.isWithin(dir.directory, assetPath))
          .directory;

  /// Return all URLs serving [assetPath] in this environment.
  Future<List<Uri>> getUrlsForAssetPath(String assetPath) {
    // Check the three (mutually-exclusive) places the path could be pointing.
    return _lookUpPathInServerRoot(assetPath).then((urls) {
      if (urls.isNotEmpty) return urls;
      return _lookUpPathInPackagesDirectory(assetPath);
    }).then((urls) {
      if (urls.isNotEmpty) return urls;
      return _lookUpPathInDependency(assetPath);
    });
  }

  /// Look up [assetPath] in the root directories of servers running in the
  /// entrypoint package.
  Future<List<Uri>> _lookUpPathInServerRoot(String assetPath) {
    // Find all of the servers whose root directories contain the asset and
    // generate appropriate URLs for each.
    return Future.wait(_directories.values
        .where((dir) => path.isWithin(dir.directory, assetPath))
        .map((dir) {
      var relativePath = path.relative(assetPath, from: dir.directory);
      return dir.server.then((server) =>
          server.url.resolveUri(path.toUri(relativePath)));
    }));
  }

  /// Look up [assetPath] in the "packages" directory in the entrypoint package.
  Future<List<Uri>> _lookUpPathInPackagesDirectory(String assetPath) {
    var components = path.split(path.relative(assetPath));
    if (components.first != "packages") return new Future.value([]);
    if (!graph.packages.containsKey(components[1])) return new Future.value([]);
    return Future.wait(_directories.values.map((dir) {
      return dir.server.then((server) =>
          server.url.resolveUri(path.toUri(assetPath)));
    }));
  }

  /// Look up [assetPath] in the "lib" or "asset" directory of a dependency
  /// package.
  Future<List<Uri>> _lookUpPathInDependency(String assetPath) {
    for (var packageName in graph.packages.keys) {
      var package = graph.packages[packageName];
      var libDir = package.path('lib');
      var assetDir = package.path('asset');

      var uri;
      if (path.isWithin(libDir, assetPath)) {
        uri = path.toUri(path.join('packages', package.name,
            path.relative(assetPath, from: libDir)));
      } else if (path.isWithin(assetDir, assetPath)) {
        uri = path.toUri(path.join('assets', package.name,
            path.relative(assetPath, from: assetDir)));
      } else {
        continue;
      }

      return Future.wait(_directories.values.map((dir) {
        return dir.server.then((server) => server.url.resolveUri(uri));
      }));
    }

    return new Future.value([]);
  }

  /// Given a URL to an asset served by this environment, returns the ID of the
  /// asset that would be accessed by that URL.
  ///
  /// If no server can serve [url], completes to `null`.
  Future<AssetId> getAssetIdForUrl(Uri url) {
    return Future.wait(_directories.values.map((dir) => dir.server))
        .then((servers) {
      var server = servers.firstWhere((server) {
        if (server.port != url.port) return false;
        return isLoopback(server.address.host) == isLoopback(url.host) ||
            server.address.host == url.host;
      }, orElse: () => null);
      if (server == null) return null;
      return server.urlToId(url);
    });
  }

  /// Determines if [sourcePath] is contained within any of the directories in
  /// the root package that are visible to this build environment.
  bool containsPath(String sourcePath) {
    var directories = ["lib"];
    directories.addAll(_directories.keys);
    return directories.any((dir) => path.isWithin(dir, sourcePath));
  }

  /// Pauses sending source asset updates to barback.
  void pauseUpdates() {
    // Cannot pause while already paused.
    assert(_modifiedSources == null);

    _modifiedSources = new Set<AssetId>();
  }

  /// Sends any pending source updates to barback and begins the asynchronous
  /// build process.
  void resumeUpdates() {
    // Cannot resume while not paused.
    assert(_modifiedSources != null);

    barback.updateSources(_modifiedSources);
    _modifiedSources = null;
  }

  /// Loads the assets and transformers for this environment.
  ///
  /// This transforms and serves all library and asset files in all packages in
  /// the environment's package graph. It loads any transformer plugins defined
  /// in packages in [graph] and re-runs them as necessary when any input files
  /// change.
  ///
  /// If [useDart2JS] is `true`, then the [Dart2JSTransformer] is implicitly
  /// added to end of the root package's transformer phases.
  ///
  /// If [entrypoints] is passed, only transformers necessary to run those
  /// entrypoints will be loaded.
  ///
  /// Returns a [Future] that completes once all inputs and transformers are
  /// loaded.
  Future _load({Iterable<AssetId> entrypoints, bool useDart2JS}) {
    return log.progress("Initializing barback", () async {
      // If the entrypoint package manually configures the dart2js
      // transformer, don't include it in the built-in transformer list.
      //
      // TODO(nweiz): if/when we support more built-in transformers, make
      // this more general.
      var containsDart2JS = graph.entrypoint.root.pubspec.transformers
          .any((transformers) =>
              transformers.any((config) => config.id.package == '\$dart2js'));

      if (!containsDart2JS && useDart2JS) {
        _builtInTransformers.addAll([
          new Dart2JSTransformer(this, mode),
          new DartForwardingTransformer(mode)
        ]);
      }

      // Bind a server that we can use to load the transformers.
      var transformerServer = await BarbackServer.bind(this, _hostname, 0);

      var errorStream = barback.errors.map((error) {
        // Even most normally non-fatal barback errors should take down pub if
        // they happen during the initial load process.
        if (error is! AssetLoadException) throw error;

        log.error(log.red(error.message));
        log.fine(error.stackTrace.terse);
      });

      await _withStreamErrors(() {
        return log.progress("Loading source assets", _provideSources);
      }, [errorStream, barback.results]);

      log.fine("Provided sources.");

      errorStream = barback.errors.map((error) {
        // Now that we're loading transformers, errors they log shouldn't be
        // fatal, since we're starting to run them on real user assets which
        // may have e.g. syntax errors. If an error would cause a transformer
        // to fail to load, the load failure will cause us to exit.
        if (error is! TransformerException) throw error;

        var message = error.error.toString();
        if (error.stackTrace != null) {
          message += "\n" + error.stackTrace.terse.toString();
        }

        _log(new LogEntry(error.transform, error.transform.primaryId,
                LogLevel.ERROR, message, null));
      });

      await _withStreamErrors(() async {
        return log.progress("Loading transformers", () async {
          await loadAllTransformers(this, transformerServer,
              entrypoints: entrypoints);
          transformerServer.close();
        }, fine: true);
      }, [errorStream, barback.results, transformerServer.results]);
    }, fine: true);
  }

  /// Provides the public source assets in the environment to barback.
  ///
  /// If [watcherType] is not [WatcherType.NONE], enables watching on them.
  Future _provideSources() async {
    // Just include the "lib" directory from each package. We'll add the
    // other build directories in the root package by calling
    // [serveDirectory].
    await Future.wait(graph.packages.values.map((package) async {
      if (graph.isPackageStatic(package.name)) return;
      await _provideDirectorySources(package, "lib");
    }));
  }

  /// Provides all of the source assets within [dir] in [package] to barback.
  ///
  /// If [watcherType] is not [WatcherType.NONE], enables watching on them.
  /// Returns the subscription to the watcher, or `null` if none was created.
  Future<StreamSubscription<WatchEvent>> _provideDirectorySources(
      Package package, String dir) {
    log.fine("Providing sources for ${package.name}|$dir.");
    // TODO(rnystrom): Handle overlapping directories. If two served
    // directories overlap like so:
    //
    // $ pub serve example example/subdir
    //
    // Then the sources of the subdirectory will be updated and watched twice.
    // See: #17454
    if (_watcherType == WatcherType.NONE) {
      _updateDirectorySources(package, dir);
      return new Future.value();
    }

    // Watch the directory before listing is so we don't miss files that
    // are added between the initial list and registering the watcher.
    return _watchDirectorySources(package, dir).then((_) {
      _updateDirectorySources(package, dir);
    });
  }

  /// Updates barback with all of the files in [dir] inside [package].
  void _updateDirectorySources(Package package, String dir) {
    var ids = _listDirectorySources(package, dir);
    if (_modifiedSources == null) {
      barback.updateSources(ids);
    } else {
      _modifiedSources.addAll(ids);
    }
  }

  /// Removes all of the files in [dir] in the root package from barback.
  void _removeDirectorySources(String dir) {
    var ids = _listDirectorySources(rootPackage, dir);
    if (_modifiedSources == null) {
      barback.removeSources(ids);
    } else {
      _modifiedSources.removeAll(ids);
    }
  }

  /// Lists all of the source assets in [dir] inside [package].
  ///
  /// For large packages, listing the contents is a performance bottleneck, so
  /// this is optimized for our needs in here instead of using the more general
  /// but slower [listDir].
  Iterable<AssetId> _listDirectorySources(Package package, String dir) {
    // This is used in some performance-sensitive paths and can list many, many
    // files. As such, it leans more havily towards optimization as opposed to
    // readability than most code in pub. In particular, it avoids using the
    // path package, since re-parsing a path is very expensive relative to
    // string operations.
    return package.listFiles(beneath: dir).map((file) {
      // From profiling, path.relative here is just as fast as a raw substring
      // and is correct in the case where package.dir has a trailing slash.
      var relative = package.relative(file);

      if (Platform.operatingSystem == 'windows') {
        relative = relative.replaceAll("\\", "/");
      }

      var uri = new Uri(pathSegments: relative.split("/"));
      return new AssetId(package.name, uri.toString());
    });
  }

  /// Adds a file watcher for [dir] within [package], if the directory exists
  /// and the package needs watching.
  Future<StreamSubscription<WatchEvent>> _watchDirectorySources(
      Package package, String dir) {
    // If this package comes from a cached source, its contents won't change so
    // we don't need to monitor it. `packageId` will be null for the
    // application package, since that's not locked.
    var packageId = graph.lockFile.packages[package.name];
    if (packageId != null &&
        graph.entrypoint.cache.sources[packageId.source] is CachedSource) {
      return new Future.value();
    }

    var subdirectory = package.path(dir);
    if (!dirExists(subdirectory)) return new Future.value();

    // TODO(nweiz): close this watcher when [barback] is closed.
    var watcher = _watcherType.create(subdirectory);
    var subscription = watcher.events.listen((event) {
      // Don't watch files symlinked into these directories.
      // TODO(rnystrom): If pub gets rid of symlinks, remove this.
      var parts = path.split(event.path);
      if (parts.contains("packages")) return;

      // Skip files that were (most likely) compiled from nearby ".dart"
      // files. These are created by the Editor's "Run as JavaScript"
      // command and are written directly into the package's directory.
      // When pub's dart2js transformer then tries to create the same file
      // name, we get a build error. To avoid that, just don't consider
      // that file to be a source.
      // TODO(rnystrom): Remove these when the Editor no longer generates
      // .js files and users have had enough time that they no longer have
      // these files laying around. See #15859.
      if (event.path.endsWith(".dart.js")) return;
      if (event.path.endsWith(".dart.js.map")) return;
      if (event.path.endsWith(".dart.precompiled.js")) return;

      var idPath = package.relative(event.path);
      var id = new AssetId(package.name, path.toUri(idPath).toString());
      if (event.type == ChangeType.REMOVE) {
        if (_modifiedSources != null) {
          _modifiedSources.remove(id);
        } else {
          barback.removeSources([id]);
        }
      } else if (_modifiedSources != null) {
        _modifiedSources.add(id);
      } else {
        barback.updateSources([id]);
      }
    });

    return watcher.ready.then((_) => subscription);
  }

  /// Returns the result of [futureCallback] unless any stream in [streams]
  /// emits an error before it's done.
  ///
  /// If a stream does emit an error, that error is thrown instead.
  /// [futureCallback] is a callback rather than a plain future to ensure that
  /// [streams] are listened to before any code that might cause an error starts
  /// running.
  Future _withStreamErrors(Future futureCallback(), List<Stream> streams) {
    var completer = new Completer.sync();
    var subscriptions = streams.map((stream) =>
        stream.listen((_) {}, onError: completer.completeError)).toList();

    new Future.sync(futureCallback).then((_) {
      if (!completer.isCompleted) completer.complete();
    }).catchError((error, stackTrace) {
      if (!completer.isCompleted) completer.completeError(error, stackTrace);
    });

    return completer.future.whenComplete(() {
      for (var subscription in subscriptions) {
        subscription.cancel();
      }
    });
  }
}

/// Log [entry] using Pub's logging infrastructure.
///
/// Since both [LogEntry] objects and the message itself often redundantly
/// show the same context like the file where an error occurred, this tries
/// to avoid showing redundant data in the entry.
void _log(LogEntry entry) {
  messageMentions(text) =>
      entry.message.toLowerCase().contains(text.toLowerCase());

  messageMentionsAsset(id) =>
      messageMentions(id.toString()) ||
      messageMentions(path.fromUri(entry.assetId.path));

  var prefixParts = [];

  // Show the level (unless the message mentions it).
  if (!messageMentions(entry.level.name)) {
    prefixParts.add("${entry.level} from");
  }

  // Show the transformer.
  prefixParts.add(entry.transform.transformer);

  // Mention the primary input of the transform unless the message seems to.
  if (!messageMentionsAsset(entry.transform.primaryId)) {
    prefixParts.add("on ${entry.transform.primaryId}");
  }

  // If the relevant asset isn't the primary input, mention it unless the
  // message already does.
  if (entry.assetId != entry.transform.primaryId &&
      !messageMentionsAsset(entry.assetId)) {
    prefixParts.add("with input ${entry.assetId}");
  }

  var prefix = "[${prefixParts.join(' ')}]:";
  var message = entry.message;
  if (entry.span != null) {
    message = entry.span.message(entry.message);
  }

  switch (entry.level) {
    case LogLevel.ERROR:
      log.error("${log.red(prefix)}\n$message");
      break;

    case LogLevel.WARNING:
      log.warning("${log.yellow(prefix)}\n$message");
      break;

    case LogLevel.INFO:
      log.message("${log.cyan(prefix)}\n$message");
      break;

    case LogLevel.FINE:
      log.fine("${log.gray(prefix)}\n$message");
      break;
  }
}

/// Exception thrown when trying to serve a new directory that overlaps one or
/// more directories already being served.
class OverlappingSourceDirectoryException implements Exception {
  /// The relative paths of the directories that overlap the one that could not
  /// be served.
  final List<String> overlappingDirectories;

  OverlappingSourceDirectoryException(this.overlappingDirectories);
}

/// An enum describing different modes of constructing a [DirectoryWatcher].
abstract class WatcherType {
  /// A watcher that automatically chooses its type based on the operating
  /// system.
  static const AUTO = const _AutoWatcherType();

  /// A watcher that always polls the filesystem for changes.
  static const POLLING = const _PollingWatcherType();

  /// No directory watcher at all.
  static const NONE = const _NoneWatcherType();

  /// Creates a new DirectoryWatcher.
  DirectoryWatcher create(String directory);

  String toString();
}

class _AutoWatcherType implements WatcherType {
  const _AutoWatcherType();

  DirectoryWatcher create(String directory) =>
    new DirectoryWatcher(directory);

  String toString() => "auto";
}

class _PollingWatcherType implements WatcherType {
  const _PollingWatcherType();

  DirectoryWatcher create(String directory) =>
    new PollingDirectoryWatcher(directory);

  String toString() => "polling";
}

class _NoneWatcherType implements WatcherType {
  const _NoneWatcherType();

  DirectoryWatcher create(String directory) => null;

  String toString() => "none";
}
