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

import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;

import '../io.dart' as io;
import 'directory.dart';
import 'file.dart';
import 'file_system_entity.dart';
import 'link.dart';

/// A generic representation of a file system.
///
/// Note that this class uses `dart:io` only inasmuch as it deals in the types
/// exposed by the `dart:io` library. Subclasses should document their level of
/// dependence on the library (and the associated implications of using that
/// implementation in the browser).
abstract class FileSystem {
  /// Creates a new `FileSystem`.
  const FileSystem();

  /// Returns a reference to a [Directory] at [path].
  ///
  /// [path] can be either a [String], a [Uri], or a [FileSystemEntity].
  Directory directory(dynamic path);

  /// Returns a reference to a [File] at [path].
  ///
  /// [path] can be either a [String], a [Uri], or a [FileSystemEntity].
  File file(dynamic path);

  /// Returns a reference to a [Link] at [path].
  ///
  /// [path] can be either a [String], a [Uri], or a [FileSystemEntity].
  Link link(dynamic path);

  /// An object for manipulating paths in this file system.
  p.Context get path;

  /// Gets the system temp directory.
  ///
  /// It is left to file system implementations to decide how to define the
  /// "system temp directory".
  Directory get systemTempDirectory;

  /// Creates a directory object pointing to the current working directory.
  Directory get currentDirectory;

  /// Sets the current working directory to the specified [path].
  ///
  /// The new value set can be either a [Directory] or a [String].
  ///
  /// Relative paths will be resolved by the underlying file system
  /// implementation (meaning it is up to the underlying implementation to
  /// decide whether to support relative paths).
  set currentDirectory(dynamic path);

  /// Asynchronously calls the operating system's stat() function on [path].
  /// Returns a Future which completes with a [io.FileStat] object containing
  /// the data returned by stat().
  /// If the call fails, completes the future with a [io.FileStat] object with
  /// .type set to FileSystemEntityType.NOT_FOUND and the other fields invalid.
  Future<io.FileStat> stat(String path);

  /// Calls the operating system's stat() function on [path].
  /// Returns a [io.FileStat] object containing the data returned by stat().
  /// If the call fails, returns a [io.FileStat] object with .type set to
  /// FileSystemEntityType.NOT_FOUND and the other fields invalid.
  io.FileStat statSync(String path);

  /// Checks whether two paths refer to the same object in the
  /// file system. Returns a [Future<bool>] that completes with the result.
  ///
  /// Comparing a link to its target returns false, as does comparing two links
  /// that point to the same target.  To check the target of a link, use
  /// Link.target explicitly to fetch it.  Directory links appearing
  /// inside a path are followed, though, to find the file system object.
  ///
  /// Completes the returned Future with an error if one of the paths points
  /// to an object that does not exist.
  Future<bool> identical(String path1, String path2);

  /// Synchronously checks whether two paths refer to the same object in the
  /// file system.
  ///
  /// Comparing a link to its target returns false, as does comparing two links
  /// that point to the same target.  To check the target of a link, use
  /// Link.target explicitly to fetch it.  Directory links appearing
  /// inside a path are followed, though, to find the file system object.
  ///
  /// Throws an error if one of the paths points to an object that does not
  /// exist.
  bool identicalSync(String path1, String path2);

  /// Tests if [FileSystemEntity.watch] is supported on the current system.
  bool get isWatchSupported;

  /// Finds the type of file system object that a [path] points to. Returns
  /// a `Future<FileSystemEntityType>` that completes with the result.
  ///
  /// [io.FileSystemEntityType.link] will only be returned if [followLinks] is
  /// `false`, and [path] points to a link
  ///
  /// If the [path] does not point to a file system object or an error occurs
  /// then [io.FileSystemEntityType.notFound] is returned.
  Future<io.FileSystemEntityType> type(String path, {bool followLinks = true});

  /// Syncronously finds the type of file system object that a [path] points
  /// to. Returns a [io.FileSystemEntityType].
  ///
  /// [io.FileSystemEntityType.link] will only be returned if [followLinks] is
  /// `false`, and [path] points to a link
  ///
  /// If the [path] does not point to a file system object or an error occurs
  /// then [io.FileSystemEntityType.notFound] is returned.
  io.FileSystemEntityType typeSync(String path, {bool followLinks = true});

  /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.file].
  Future<bool> isFile(String path) async =>
      await type(path) == io.FileSystemEntityType.file;

  /// Synchronously checks if [`type(path)`](type) returns
  /// [io.FileSystemEntityType.file].
  bool isFileSync(String path) =>
      typeSync(path) == io.FileSystemEntityType.file;

  /// Checks if [`type(path)`](type) returns
  /// [io.FileSystemEntityType.directory].
  Future<bool> isDirectory(String path) async =>
      await type(path) == io.FileSystemEntityType.directory;

  /// Synchronously checks if [`type(path)`](type) returns
  /// [io.FileSystemEntityType.directory].
  bool isDirectorySync(String path) =>
      typeSync(path) == io.FileSystemEntityType.directory;

  /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.link].
  Future<bool> isLink(String path) async =>
      await type(path, followLinks: false) == io.FileSystemEntityType.link;

  /// Synchronously checks if [`type(path)`](type) returns
  /// [io.FileSystemEntityType.link].
  bool isLinkSync(String path) =>
      typeSync(path, followLinks: false) == io.FileSystemEntityType.link;

  /// Gets the string path represented by the specified generic [path].
  ///
  /// [path] may be a [io.FileSystemEntity], a [String], or a [Uri].
  @protected
  String getPath(dynamic path) {
    if (path is io.FileSystemEntity) {
      return path.path;
    } else if (path is String) {
      return path;
    } else if (path is Uri) {
      return this.path.fromUri(path);
    } else {
      throw ArgumentError('Invalid type for "path": ${path?.runtimeType}');
    }
  }
}
