// 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) {
          String msg = expectedType == FileSystemEntityType.FILE
              ? 'Is a directory'
              : 'Not a directory';
          throw new FileSystemException(msg, 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) {
          String msg = expectedType == FileSystemEntityType.FILE
              ? 'Is a directory'
              : 'Not a directory';
          throw new FileSystemException(msg, 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);
}
