// Copyright (c) 2017, 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.

part of file.src.backends.memory;

class _MemoryDirectory extends _MemoryFileSystemEntity
    with common.DirectoryAddOnsMixin
    implements Directory {
  static int _tempCounter = 0;

  _MemoryDirectory(MemoryFileSystem fileSystem, String path)
      : super(fileSystem, path);

  @override
  io.FileSystemEntityType get expectedType => io.FileSystemEntityType.DIRECTORY;

  @override
  Uri get uri => new Uri.directory(path);

  @override
  bool existsSync() => _backingOrNull?.stat?.type == expectedType;

  @override
  Future<Directory> create({bool recursive: false}) async {
    createSync(recursive: recursive);
    return this;
  }

  @override
  void createSync({bool recursive: false}) {
    _Node node = _createSync(
      followTailLink: true,
      visitLinks: true,
      createChild: (_DirectoryNode parent, bool isFinalSegment) {
        if (recursive || isFinalSegment) {
          return new _DirectoryNode(parent);
        }
        return null;
      },
    );
    if (node.type != expectedType) {
      // There was an existing non-directory node at this object's path
      throw common.notADirectory(path);
    }
  }

  @override
  Future<Directory> createTemp([String prefix]) async => createTempSync(prefix);

  @override
  Directory createTempSync([String prefix]) {
    prefix = (prefix ?? '') + 'rand';
    String fullPath = fileSystem.path.join(path, prefix);
    String dirname = fileSystem.path.dirname(fullPath);
    String basename = fileSystem.path.basename(fullPath);
    _DirectoryNode node = fileSystem._findNode(dirname);
    _checkExists(node, () => dirname);
    _checkIsDir(node, () => dirname);
    String name() => '$basename$_tempCounter';
    while (node.children.containsKey(name())) {
      _tempCounter++;
    }
    _DirectoryNode tempDir = new _DirectoryNode(node);
    node.children[name()] = tempDir;
    return new _MemoryDirectory(
        fileSystem, fileSystem.path.join(dirname, name()));
  }

  @override
  Future<Directory> rename(String newPath) async => renameSync(newPath);

  @override
  Directory renameSync(String newPath) => _renameSync(
        newPath,
        validateOverwriteExistingEntity: (_DirectoryNode existingNode) {
          if (existingNode.children.isNotEmpty) {
            throw common.directoryNotEmpty(newPath);
          }
        },
      );

  @override
  Directory get parent =>
      (_backingOrNull?.isRoot ?? false) ? this : super.parent;

  @override
  Directory get absolute => super.absolute;

  @override
  Stream<FileSystemEntity> list({
    bool recursive: false,
    bool followLinks: true,
  }) =>
      new Stream<FileSystemEntity>.fromIterable(listSync(
        recursive: recursive,
        followLinks: followLinks,
      ));

  @override
  List<FileSystemEntity> listSync({
    bool recursive: false,
    bool followLinks: true,
  }) {
    _DirectoryNode node = _backing;
    List<FileSystemEntity> listing = <FileSystemEntity>[];
    List<_PendingListTask> tasks = <_PendingListTask>[
      new _PendingListTask(
        node,
        path.endsWith(_separator) ? path.substring(0, path.length - 1) : path,
        new Set<_LinkNode>(),
      ),
    ];
    while (tasks.isNotEmpty) {
      _PendingListTask task = tasks.removeLast();
      task.dir.children.forEach((String name, _Node child) {
        Set<_LinkNode> breadcrumbs = new Set<_LinkNode>.from(task.breadcrumbs);
        String childPath = fileSystem.path.join(task.path, name);
        while (followLinks && _isLink(child) && breadcrumbs.add(child)) {
          _Node referent = (child as _LinkNode).referentOrNull;
          if (referent != null) {
            child = referent;
          }
        }
        if (_isDirectory(child)) {
          listing.add(new _MemoryDirectory(fileSystem, childPath));
          if (recursive) {
            tasks.add(new _PendingListTask(child, childPath, breadcrumbs));
          }
        } else if (_isLink(child)) {
          listing.add(new _MemoryLink(fileSystem, childPath));
        } else if (_isFile(child)) {
          listing.add(new _MemoryFile(fileSystem, childPath));
        }
      });
    }
    return listing;
  }

  @override
  Directory _clone(String path) => new _MemoryDirectory(fileSystem, path);

  @override
  String toString() => "MemoryDirectory: '$path'";
}

class _PendingListTask {
  final _DirectoryNode dir;
  final String path;
  final Set<_LinkNode> breadcrumbs;
  _PendingListTask(this.dir, this.path, this.breadcrumbs);
}
