// 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.

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 entry represents a directory or file. It may be a file or directory
  /// that was explicitly added, or a parent directory that was implicitly
  /// added in order to add a child.
  final _Entry _entries = new _Entry();

  PathSet(this.root);

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

    var parts = p.split(path);
    var entry = _entries;
    for (var part in parts) {
      entry = entry.contents.putIfAbsent(part, () => new _Entry());
    }

    entry.isExplicit = true;
  }

  /// 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(p.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].
    Set<String> 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.contents[part];
        if (entry == null || entry.contents.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.contents.isEmpty && !entry.isExplicit) {
          dir.contents.remove(part);
        }
        return paths;
      }

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

      if (entry.contents.isEmpty) {
        return new Set.from([p.join(root, path)]);
      }

      var set = _explicitPathsWithin(entry, path);
      if (entry.isExplicit) {
        set.add(p.join(root, path));
      }

      return set;
    }

    return recurse(_entries, root);
  }

  /// Recursively lists all of the explicit paths within [dir].
  ///
  /// [dirPath] should be the path to [dir].
  Set<String> _explicitPathsWithin(_Entry dir, String dirPath) {
    var paths = new Set<String>();
    recurse(dir, path) {
      dir.contents.forEach((name, entry) {
        var entryPath = p.join(path, name);
        if (entry.isExplicit) paths.add(p.join(root, entryPath));

        recurse(entry, entryPath);
      });
    }

    recurse(dir, dirPath);
    return paths;
  }

  /// 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) {
    path = _normalize(path);
    var entry = _entries;

    for (var part in p.split(path)) {
      entry = entry.contents[part];
      if (entry == null) return false;
    }

    return entry.isExplicit;
  }

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

    for (var part in p.split(path)) {
      entry = entry.contents[part];
      if (entry == null) return false;
    }

    return !entry.contents.isEmpty;
  }

  /// All of the paths explicitly added to this set.
  List<String> get paths {
    var result = <String>[];

    recurse(dir, path) {
      for (var name in dir.contents.keys) {
        var entry = dir.contents[name];
        var entryPath = p.join(path, name);
        if (entry.isExplicit) result.add(entryPath);
        recurse(entry, entryPath);
      }
    }

    recurse(_entries, root);
    return result;
  }

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

  /// 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) {
    assert(p.isWithin(root, path));

    return p.relative(p.normalize(path), from: root);
  }
}

/// A virtual file system entity tracked by the [PathSet].
///
/// It may have child entries in [contents], which implies it's a directory.
class _Entry {
  /// The child entries contained in this directory.
  final Map<String, _Entry> contents = {};

  /// If this entry was explicitly added as a leaf file system entity, this
  /// will be true.
  ///
  /// Otherwise, it represents a parent directory that was implicitly added
  /// when added some child of it.
  bool isExplicit = false;
}
