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

abstract class _ChrootFileSystemEntity<T extends FileSystemEntity,
    D extends io.FileSystemEntity> extends ForwardingFileSystemEntity<T, D> {
  @override
  final ChrootFileSystem fileSystem;

  @override
  final String path;

  _ChrootFileSystemEntity(this.fileSystem, this.path);

  @override
  String get dirname => fileSystem.path.dirname(path);

  @override
  String get basename => fileSystem.path.basename(path);

  @override
  D get delegate => getDelegate();

  /// Gets the delegate file system entity in the underlying file system that
  /// corresponds to this entity's local file system path.
  ///
  /// If [followLinks] is true and this entity's path references a symbolic
  /// link, then the path of the delegate entity will reference the ultimate
  /// target of that symbolic link. Symbolic links in the middle of the path
  /// will always be resolved in the delegate entity's path.
  D getDelegate({bool followLinks: false}) =>
      _rawDelegate(fileSystem._real(path, followLinks: followLinks));

  /// Returns the expected type of this entity, which may differ from the type
  /// of the entity that's found at the path specified by this entity.
  FileSystemEntityType get expectedType;

  /// Returns a delegate entity at the specified [realPath] (the path in the
  /// underlying file system).
  D _rawDelegate(String realPath);

  /// Gets the path of this entity as an absolute path (unchanged if the
  /// entity already specifies an absolute path).
  String get _absolutePath => fileSystem.path.absolute(path);

  /// Tells whether this entity's path references a symbolic link.
  bool get _isLink =>
      fileSystem.typeSync(path, followLinks: false) ==
      FileSystemEntityType.LINK;

  @override
  Directory wrapDirectory(io.Directory delegate) =>
      new _ChrootDirectory.wrapped(fileSystem, delegate, relative: !isAbsolute);

  @override
  File wrapFile(io.File delegate) =>
      new _ChrootFile.wrapped(fileSystem, delegate, relative: !isAbsolute);

  @override
  Link wrapLink(io.Link delegate) =>
      new _ChrootLink.wrapped(fileSystem, delegate, relative: !isAbsolute);

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

  @override
  Future<bool> exists() => getDelegate(followLinks: true).exists();

  @override
  bool existsSync() => getDelegate(followLinks: true).existsSync();

  @override
  Future<String> resolveSymbolicLinks() async => resolveSymbolicLinksSync();

  @override
  String resolveSymbolicLinksSync() =>
      fileSystem._resolve(path, notFound: _NotFoundBehavior.throwError);

  @override
  Future<FileStat> stat() {
    D delegate;
    try {
      delegate = getDelegate(followLinks: true);
    } on FileSystemException {
      return new Future<FileStat>.value(const _NotFoundFileStat());
    }
    return delegate.stat();
  }

  @override
  FileStat statSync() {
    D delegate;
    try {
      delegate = getDelegate(followLinks: true);
    } on FileSystemException {
      return const _NotFoundFileStat();
    }
    return delegate.statSync();
  }

  @override
  Future<T> delete({bool recursive: false}) async {
    String path = fileSystem._resolve(this.path,
        followLinks: false, notFound: _NotFoundBehavior.throwError);

    String real(String path) => fileSystem._real(path, resolve: false);
    Future<FileSystemEntityType> type(String path) =>
        fileSystem.delegate.type(real(path), followLinks: false);

    if (await type(path) == FileSystemEntityType.LINK) {
      if (expectedType == FileSystemEntityType.LINK) {
        await fileSystem.delegate.link(real(path)).delete();
      } else {
        String resolvedPath = fileSystem._resolve(p.basename(path),
            from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
        if (!recursive && await type(resolvedPath) != expectedType) {
          throw expectedType == FileSystemEntityType.FILE
              ? common.isADirectory(path)
              : common.notADirectory(path);
        }
        await fileSystem.delegate.link(real(path)).delete();
      }
      return this as T;
    } else {
      return wrap(
          await _rawDelegate(real(path)).delete(recursive: recursive) as D);
    }
  }

  @override
  void deleteSync({bool recursive: false}) {
    String path = fileSystem._resolve(this.path,
        followLinks: false, notFound: _NotFoundBehavior.throwError);

    String real(String path) => fileSystem._real(path, resolve: false);
    FileSystemEntityType type(String path) =>
        fileSystem.delegate.typeSync(real(path), followLinks: false);

    if (type(path) == FileSystemEntityType.LINK) {
      if (expectedType == FileSystemEntityType.LINK) {
        fileSystem.delegate.link(real(path)).deleteSync();
      } else {
        String resolvedPath = fileSystem._resolve(p.basename(path),
            from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
        if (!recursive && type(resolvedPath) != expectedType) {
          throw expectedType == FileSystemEntityType.FILE
              ? common.isADirectory(path)
              : common.notADirectory(path);
        }
        fileSystem.delegate.link(real(path)).deleteSync();
      }
    } else {
      _rawDelegate(real(path)).deleteSync(recursive: recursive);
    }
  }

  @override
  Stream<FileSystemEvent> watch({
    int events: FileSystemEvent.ALL,
    bool recursive: false,
  }) =>
      throw new UnsupportedError('watch is not supported on ChrootFileSystem');

  @override
  bool get isAbsolute => fileSystem.path.isAbsolute(path);
}
