// Copyright (c) 2013, 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.sources;

import 'dart:async';

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

import '../entrypoint.dart';
import '../io.dart';
import '../package.dart';
import '../package_graph.dart';

/// Adds all of the source assets in the provided packages to barback and
/// then watches the public directories for changes.
///
/// [watcherFactory] should return a [DirectoryWatcher] watching the given
/// directory for changes.
///
/// Returns a Future that completes when the sources are loaded and the watchers
/// are active.
Future watchSources(PackageGraph graph, Barback barback,
    WatcherType watcherType) {
  return Future.wait(graph.packages.values.map((package) {
    // 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].shouldCache) {
      barback.updateSources(_listAssets(graph.entrypoint, package));
      return new Future.value();
    }

    // Watch the visible package directories for changes.
    return Future.wait(_getPublicDirectories(graph.entrypoint, package)
        .map((name) {
      var subdirectory = path.join(package.dir, name);
      if (!dirExists(subdirectory)) return new Future.value();

      // TODO(nweiz): close these watchers when [barback] is closed.
      var watcher = watcherType.create(subdirectory);
      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") || parts.contains("assets")) return;

        // Skip ".js" 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 this when the Editor no longer generates .js
        // files. See #15859.
        if (event.path.endsWith(".dart.js")) return;

        var id = new AssetId(package.name,
            path.relative(event.path, from: package.dir));
        if (event.type == ChangeType.REMOVE) {
          barback.removeSources([id]);
        } else {
          barback.updateSources([id]);
        }
      });
      return watcher.ready;
    })).then((_) {
      barback.updateSources(_listAssets(graph.entrypoint, package));
    });
  }));
}

/// Adds all of the source assets in the provided packages to barback.
void loadSources(PackageGraph graph, Barback barback) {
  for (var package in graph.packages.values) {
    barback.updateSources(_listAssets(graph.entrypoint, package));
  }
}

/// Lists all of the visible files in [package].
///
/// This is the recursive contents of the "asset" and "lib" directories (if
/// present). If [package] is the entrypoint package, it also includes the
/// contents of "web".
List<AssetId> _listAssets(Entrypoint entrypoint, Package package) {
  var files = <AssetId>[];

  for (var dirPath in _getPublicDirectories(entrypoint, package)) {
    var dir = path.join(package.dir, dirPath);
    if (!dirExists(dir)) continue;
    for (var entry in listDir(dir, recursive: true)) {
      // Ignore "packages" symlinks if there.
      if (path.split(entry).contains("packages")) continue;

      // Skip directories.
      if (!fileExists(entry)) continue;

      // Skip ".js" 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 this when the Editor no longer generates .js
      // files. See #15859.
      if (entry.endsWith(".dart.js")) continue;

      var id = new AssetId(package.name,
          path.relative(entry, from: package.dir));
      files.add(id);
    }
  }

  return files;
}

/// Gets the names of the top-level directories in [package] whose contents
/// should be provided as source assets.
Iterable<String> _getPublicDirectories(Entrypoint entrypoint, Package package) {
  var directories = ["asset", "lib"];
  if (package.name == entrypoint.root.name) directories.add("web");
  return directories;
}

/// 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";
}
