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

class _ChrootDirectory extends _ChrootFileSystemEntity<Directory, io.Directory>
    with ForwardingDirectory, common.DirectoryAddOnsMixin {
  _ChrootDirectory(ChrootFileSystem fs, String path) : super(fs, path);

  factory _ChrootDirectory.wrapped(
    ChrootFileSystem fs,
    Directory delegate, {
    bool relative: false,
  }) {
    String localPath = fs._local(delegate.path, relative: relative);
    return new _ChrootDirectory(fs, localPath);
  }

  @override
  FileSystemEntityType get expectedType => FileSystemEntityType.DIRECTORY;

  @override
  io.Directory _rawDelegate(String path) => fileSystem.delegate.directory(path);

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

  @override
  Future<Directory> rename(String newPath) async {
    if (_isLink) {
      if (await fileSystem.type(path) != expectedType) {
        throw common.notADirectory(path);
      }
      FileSystemEntityType type = await fileSystem.type(newPath);
      if (type != FileSystemEntityType.NOT_FOUND) {
        if (type != expectedType) {
          throw common.notADirectory(newPath);
        }
        if (!(await fileSystem
            .directory(newPath)
            .list(followLinks: false)
            .isEmpty)) {
          throw common.directoryNotEmpty(newPath);
        }
      }
      String target = await fileSystem.link(path).target();
      await fileSystem.link(path).delete();
      await fileSystem.link(newPath).create(target);
      return fileSystem.directory(newPath);
    } else {
      return wrap(await getDelegate(followLinks: true)
          .rename(fileSystem._real(newPath)));
    }
  }

  @override
  Directory renameSync(String newPath) {
    if (_isLink) {
      if (fileSystem.typeSync(path) != expectedType) {
        throw common.notADirectory(path);
      }
      FileSystemEntityType type = fileSystem.typeSync(newPath);
      if (type != FileSystemEntityType.NOT_FOUND) {
        if (type != expectedType) {
          throw common.notADirectory(newPath);
        }
        if (fileSystem
            .directory(newPath)
            .listSync(followLinks: false)
            .isNotEmpty) {
          throw common.directoryNotEmpty(newPath);
        }
      }
      String target = fileSystem.link(path).targetSync();
      fileSystem.link(path).deleteSync();
      fileSystem.link(newPath).createSync(target);
      return fileSystem.directory(newPath);
    } else {
      return wrap(
          getDelegate(followLinks: true).renameSync(fileSystem._real(newPath)));
    }
  }

  @override
  Directory get absolute => new _ChrootDirectory(fileSystem, _absolutePath);

  @override
  Directory get parent {
    try {
      return wrapDirectory(delegate.parent);
    } on _ChrootJailException {
      return this;
    }
  }

  @override
  Future<Directory> create({bool recursive: false}) async {
    if (_isLink) {
      switch (await fileSystem.type(path)) {
        case FileSystemEntityType.NOT_FOUND:
          throw common.noSuchFileOrDirectory(path);
        case FileSystemEntityType.FILE:
          throw common.fileExists(path);
        case FileSystemEntityType.DIRECTORY:
          // Nothing to do.
          return this;
        default:
          throw new AssertionError();
      }
    } else {
      return wrap(await delegate.create(recursive: recursive));
    }
  }

  @override
  void createSync({bool recursive: false}) {
    if (_isLink) {
      switch (fileSystem.typeSync(path)) {
        case FileSystemEntityType.NOT_FOUND:
          throw common.noSuchFileOrDirectory(path);
        case FileSystemEntityType.FILE:
          throw common.fileExists(path);
        case FileSystemEntityType.DIRECTORY:
          // Nothing to do.
          return;
        default:
          throw new AssertionError();
      }
    } else {
      delegate.createSync(recursive: recursive);
    }
  }

  @override
  Stream<FileSystemEntity> list({
    bool recursive: false,
    bool followLinks: true,
  }) {
    Directory delegate = this.delegate;
    String dirname = delegate.path;
    return delegate
        .list(recursive: recursive, followLinks: followLinks)
        .map((io.FileSystemEntity entity) => _denormalize(entity, dirname));
  }

  @override
  List<FileSystemEntity> listSync({
    bool recursive: false,
    bool followLinks: true,
  }) {
    Directory delegate = this.delegate;
    String dirname = delegate.path;
    return delegate
        .listSync(recursive: recursive, followLinks: followLinks)
        .map((io.FileSystemEntity entity) => _denormalize(entity, dirname))
        .toList();
  }

  FileSystemEntity _denormalize(io.FileSystemEntity entity, String dirname) {
    p.Context ctx = fileSystem.path;
    String relativePart = ctx.relative(entity.path, from: dirname);
    String entityPath = ctx.join(path, relativePart);
    if (entity is io.File) {
      return new _ChrootFile(fileSystem, entityPath);
    } else if (entity is io.Directory) {
      return new _ChrootDirectory(fileSystem, entityPath);
    } else if (entity is io.Link) {
      return new _ChrootLink(fileSystem, entityPath);
    }
    throw new FileSystemException('Unsupported type: $entity', entity.path);
  }
}
