// 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 = _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, _Entry.new);
    }

    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 = Queue.of(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(_Entry dir, String 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 <String>{};

        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 <String>{};

      if (entry.contents.isEmpty) {
        return {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 = <String>{};
    void recurse(_Entry dir, String 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 set contains [path].
  ///
  /// This only returns true for paths explicitly added to this set.
  /// 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)) {
      var child = entry.contents[part];
      if (child == null) return false;
      entry = child;
    }

    return entry.isExplicit;
  }

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

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

    return entry.contents.isNotEmpty;
  }

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

    void recurse(_Entry dir, String path) {
      for (var mapEntry in dir.contents.entries) {
        var entry = mapEntry.value;
        var entryPath = p.join(path, mapEntry.key);
        if (entry.isExplicit) result.add(entryPath);
        recurse(entry, entryPath);
      }
    }

    recurse(_entries, root);
    return result;
  }

  /// Removes all paths from this set.
  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;
}
