// 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 watcher.path_dart;

import 'dart:collection';

import 'package:path/path.dart' as p;

/// A set of paths, organized into a directory hierarchy.
///
/// When a path is [add]ed, it creates an implicit directory structure above
/// that path. Directories can be inspected using [containsDir] and removed
/// using [remove]. If they're removed, their contents are removed as well.
///
/// The paths in the set are normalized so that they all begin with [root].
class PathSet {
  /// The root path, which all paths in the set must be under.
  final String root;

  /// The path set's directory hierarchy.
  ///
  /// Each level of this hierarchy has the same structure: a map from strings to
  /// other maps, which are further levels of the hierarchy. A map with no
  /// elements indicates a path that was added to the set that has no paths
  /// beneath it. Such a path should not be treated as a directory by
  /// [containsDir].
  final _entries = new Map<String, Map>();

  /// The set of paths that were explicitly added to this set.
  ///
  /// This is needed to disambiguate a directory that was explicitly added to
  /// the set from a directory that was implicitly added by adding a path
  /// beneath it.
  final _paths = new Set<String>();

  PathSet(this.root);

  /// Adds [path] to the set.
  void add(String path) {
    path = _normalize(path);
    _paths.add(path);

    var parts = _split(path);
    var dir = _entries;
    for (var part in parts) {
      dir = dir.putIfAbsent(part, () => {});
    }
  }

  /// Removes [path] and any paths beneath it from the set and returns the
  /// removed paths.
  ///
  /// Even if [path] itself isn't in the set, if it's a directory containing
  /// paths that are in the set those paths will be removed and returned.
  ///
  /// If neither [path] nor any paths beneath it are in the set, returns an
  /// empty set.
  Set<String> remove(String path) {
    path = _normalize(path);
    var parts = new Queue.from(_split(path));

    // Remove the children of [dir], as well as [dir] itself if necessary.
    //
    // [partialPath] is the path to [dir], and a prefix of [path]; the remaining
    // components of [path] are in [parts].
    recurse(dir, partialPath) {
      if (parts.length > 1) {
        // If there's more than one component left in [path], recurse down to
        // the next level.
        var part = parts.removeFirst();
        var entry = dir[part];
        if (entry.isEmpty) return new Set();

        partialPath = p.join(partialPath, part);
        var paths = recurse(entry, partialPath);
        // After removing this entry's children, if it has no more children and
        // it's not in the set in its own right, remove it as well.
        if (entry.isEmpty && !_paths.contains(partialPath)) dir.remove(part);
        return paths;
      }

      // If there's only one component left in [path], we should remove it.
      var entry = dir.remove(parts.first);
      if (entry == null) return new Set();

      if (entry.isEmpty) {
        _paths.remove(path);
        return new Set.from([path]);
      }

      var set = _removePathsIn(entry, path);
      if (_paths.contains(path)) {
        _paths.remove(path);
        set.add(path);
      }
      return set;
    }

    return recurse(_entries, root);
  }

  /// Recursively removes and returns all paths in [dir].
  ///
  /// [root] should be the path to [dir].
  Set<String> _removePathsIn(Map dir, String root) {
    var removedPaths = new Set();
    recurse(dir, path) {
      dir.forEach((name, entry) {
        var entryPath = p.join(path, name);
        if (_paths.remove(entryPath)) removedPaths.add(entryPath);
        recurse(entry, entryPath);
      });
    }

    recurse(dir, root);
    return removedPaths;
  }

  /// Returns whether [this] contains [path].
  ///
  /// This only returns true for paths explicitly added to [this].
  /// Implicitly-added directories can be inspected using [containsDir].
  bool contains(String path) => _paths.contains(_normalize(path));

  /// Returns whether [this] contains paths beneath [path].
  bool containsDir(String path) {
    path = _normalize(path);
    var dir = _entries;

    for (var part in _split(path)) {
      dir = dir[part];
      if (dir == null) return false;
    }

    return !dir.isEmpty;
  }

  /// Returns a [Set] of all paths in [this].
  Set<String> toSet() => _paths.toSet();

  /// Removes all paths from [this].
  void clear() {
    _paths.clear();
    _entries.clear();
  }

  String toString() => _paths.toString();

  /// Returns a normalized version of [path].
  ///
  /// This removes any extra ".." or "."s and ensure that the returned path
  /// begins with [root]. It's an error if [path] isn't within [root].
  String _normalize(String path) {
    var relative = p.relative(p.normalize(path), from: root);
    var parts = p.split(relative);
    // TODO(nweiz): replace this with [p.isWithin] when that exists (issue
    // 14980).
    if (!p.isRelative(relative) || parts.first == '..' || parts.first == '.') {
      throw new ArgumentError('Path "$path" is not inside "$root".');
    }
    return p.join(root, relative);
  }

  /// Returns the segments of [path] beneath [root].
  List<String> _split(String path) => p.split(p.relative(path, from: root));
}
