// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// A minimal library for discovering and probing a local engine repository.
///
/// This library is intended to be used by tools that need to interact with a
/// local engine repository, such as `clang_tidy` or `githooks`. For example,
/// finding the `compile_commands.json` file for the most recently built output:
///
/// ```dart
/// final Engine engine = Engine.findWithin();
/// final Output? output = engine.latestOutput();
/// if (output == null) {
///   print('No output targets found.');
/// } else {
///   final io.File? compileCommandsJson = output.compileCommandsJson;
///   if (compileCommandsJson == null) {
///     print('No compile_commands.json file found.');
///   } else {
///     print('Found compile_commands.json file at ${compileCommandsJson.path}');
///   }
/// }
/// ```
library;

import 'dart:io' as io;

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

/// Represents the `$ENGINE` directory (i.e. a checked-out Flutter engine).
///
/// If you have a path to the `$ENGINE/src` directory, use [Engine.fromSrcPath].
///
/// If you have a path to a directory within the `$ENGINE/src` directory, or
/// want to use the current working directory, use [Engine.findWithin].
final class Engine {
  const Engine._({
    required this.srcDir,
    required this.flutterDir,
    required this.outDir,
  });

  /// Creates an [Engine] from a path such as `/Users/.../flutter/engine/src`.
  ///
  /// ```dart
  /// final Engine engine = Engine.findWithin('/Users/.../engine/src');
  /// print(engine.srcDir.path); // /Users/.../engine/src
  /// ```
  ///
  /// Throws a [InvalidEngineException] if the path is not a valid engine root.
  factory Engine.fromSrcPath(String srcPath) {
    // If the path does not end in `/src`, fail.
    if (p.basename(srcPath) != 'src') {
      throw InvalidEngineException.doesNotEndWithSrc(srcPath);
    }

    // If the directory does not exist, or is not a directory, fail.
    final io.Directory srcDir = io.Directory(srcPath);
    if (!srcDir.existsSync()) {
      throw InvalidEngineException.notADirectory(srcPath);
    }

    // Check for the existence of a `flutter` directory within `src`.
    final io.Directory flutterDir = io.Directory(p.join(srcPath, 'flutter'));
    if (!flutterDir.existsSync()) {
      throw InvalidEngineException.missingFlutterDirectory(srcPath);
    }

    // We do **NOT** check for the existence of a `out` directory within `src`,
    // it's not required to exist (i.e. a new checkout of the engine), and we
    // don't want to fail if it doesn't exist.
    final io.Directory outDir = io.Directory(p.join(srcPath, 'out'));

    return Engine._(
      srcDir: srcDir,
      flutterDir: flutterDir,
      outDir: outDir,
    );
  }

  /// Creates an [Engine] by looking for a `src/` directory in the given path.
  ///
  /// Similar to [tryFindWithin], but throws a [StateError] if the path is not
  /// within a valid engine. This is useful for tools that require an engine
  /// and do not have a reasonable fallback or recovery path.
  factory Engine.findWithin([String? path]) {
    final Engine? engine = tryFindWithin(path);
    if (engine == null) {
      throw StateError('The path "$path" is not within a valid engine.');
    }
    return engine;
  }

  /// Creates an [Engine] by looking for a `src/` directory in the given [path].
  ///
  /// ```dart
  /// // Use the current working directory.
  /// final Engine engine = Engine.findWithin();
  /// print(engine.srcDir.path); // /Users/.../engine/src
  ///
  /// // Use a specific directory.
  /// final Engine engine = Engine.findWithin('/Users/.../engine/src/foo/bar');
  /// print(engine.srcDir.path); // /Users/.../engine/src
  /// ```
  ///
  /// If a [path] is not provided, the current working directory is used.
  ///
  /// If path does not exist, or is not a directory, an error is thrown.
  ///
  /// Returns `null` if the path is not within a valid engine.
  static Engine? tryFindWithin([String? path]) {
    path ??= p.current;

    // Search parent directories for a `src` directory.
    io.Directory maybeSrcDir = io.Directory(path);

    if (!maybeSrcDir.existsSync()) {
      throw StateError(
        'The path "$path" does not exist or is not a directory.'
      );
    }

    do {
      try {
        return Engine.fromSrcPath(maybeSrcDir.path);
      } on InvalidEngineException {
        // Ignore, we'll keep searching.
      }
      maybeSrcDir = maybeSrcDir.parent;
    } while (maybeSrcDir.parent.path != maybeSrcDir.path /* at root */);

    return null;
  }

  /// The path to the `$ENGINE/src` directory.
  final io.Directory srcDir;

  /// The path to the `$ENGINE/src/flutter` directory.
  final io.Directory flutterDir;

  /// The path to the `$ENGINE/src/out` directory.
  ///
  /// **NOTE**: This directory may not exist.
  final io.Directory outDir;

  /// Returns a list of all output targets in [outDir].
  List<Output> outputs() {
    return outDir
      .listSync()
      .whereType<io.Directory>()
      .map<Output>(Output._)
      .toList();
  }

  /// Returns the most recently modified output target in [outDir].
  ///
  /// If there are no output targets, returns `null`.
  Output? latestOutput() {
    final List<Output> outputs = this.outputs();
    if (outputs.isEmpty) {
      return null;
    }
    outputs.sort((Output a, Output b) {
      return b.path.statSync().modified.compareTo(a.path.statSync().modified);
    });
    return outputs.first;
  }
}

/// An implementation of [Engine] that has pre-defined outputs for testing.
final class TestEngine extends Engine {
  /// Creates a [TestEngine] with pre-defined paths.
  ///
  /// The [srcDir] and [flutterDir] must exist, but the [outDir] is optional.
  ///
  /// Optionally, provide a list of [outputs] to use, otherwise it is empty.
  TestEngine.withPaths({
    required super.srcDir,
    required super.flutterDir,
    required super.outDir,
    List<TestOutput> outputs = const <TestOutput>[],
  }) : _outputs = outputs, super._() {
    if (!srcDir.existsSync()) {
      throw ArgumentError.value(srcDir, 'srcDir', 'does not exist');
    }
    if (!flutterDir.existsSync()) {
      throw ArgumentError.value(flutterDir, 'flutterDir', 'does not exist');
    }
  }

  /// Creates a [TestEngine] within a temporary directory.
  ///
  /// The [rootDir] is the temporary directory that will contain the engine.
  ///
  /// Optionally, provide a list of [outputs] to use, otherwise it is empty.
  factory TestEngine.createTemp({
    required io.Directory rootDir,
    List<TestOutput> outputs = const <TestOutput>[],
  }) {
    final io.Directory srcDir = io.Directory(p.join(rootDir.path, 'src'));
    final io.Directory flutterDir = io.Directory(p.join(srcDir.path, 'flutter'));
    final io.Directory outDir = io.Directory(p.join(srcDir.path, 'out'));
    srcDir.createSync(recursive: true);
    flutterDir.createSync(recursive: true);
    outDir.createSync(recursive: true);
    return TestEngine.withPaths(
      srcDir: srcDir,
      flutterDir: flutterDir,
      outDir: outDir,
      outputs: outputs,
    );
  }

  final List<TestOutput> _outputs;

  @override
  List<Output> outputs() => List<Output>.unmodifiable(_outputs);

  @override
  Output? latestOutput() {
    if (_outputs.isEmpty) {
      return null;
    }
    _outputs.sort((TestOutput a, TestOutput b) {
      return b.lastModified.compareTo(a.lastModified);
    });
    return _outputs.first;
  }
}

/// An implementation of [Output] that has a pre-defined path for testing.
final class TestOutput extends Output {
  /// Creates a [TestOutput] with a pre-defined path.
  ///
  /// Optionally, provide a [lastModified] date.
  TestOutput(super.path, {DateTime? lastModified})
    : lastModified = lastModified ?? _defaultLastModified,
      super._();

  static final DateTime _defaultLastModified = DateTime.now();

  /// The last modified date of the output target.
  final DateTime lastModified;
}

/// Thrown when an [Engine] could not be created from a path.
sealed class InvalidEngineException implements Exception {
  /// Thrown when an [Engine] was created from a path not ending in `src`.
  factory InvalidEngineException.doesNotEndWithSrc(String path) {
    return InvalidEngineSrcPathException._(path);
  }

  /// Thrown when an [Engine] was created from a directory that does not exist.
  factory InvalidEngineException.notADirectory(String path) {
    return InvalidEngineNotADirectoryException._(path);
  }

  /// Thrown when an [Engine] was created from a path not containing `flutter/`.
  factory InvalidEngineException.missingFlutterDirectory(String path) {
    return InvalidEngineMissingFlutterDirectoryException._(path);
  }
}

/// Thrown when an [Engine] was created from a path not ending in `src`.
final class InvalidEngineSrcPathException implements InvalidEngineException {
  InvalidEngineSrcPathException._(this.path);

  /// The path that was used to create the [Engine].
  final String path;

  @override
  String toString() {
    return 'The path $path does not end in `${p.separator}src`.';
  }
}

/// Thrown when an [Engine] was created from a path that is not a directory.
final class InvalidEngineNotADirectoryException implements InvalidEngineException {
  InvalidEngineNotADirectoryException._(this.path);

  /// The path that was used to create the [Engine].
  final String path;

  @override
  String toString() {
    return 'The path "$path" does not exist or is not a directory.';
  }
}

/// Thrown when an [Engine] was created from a path not containing `flutter/`.
final class InvalidEngineMissingFlutterDirectoryException implements InvalidEngineException {
  InvalidEngineMissingFlutterDirectoryException._(this.path);

  /// The path that was used to create the [Engine].
  final String path;

  @override
  String toString() {
    return 'The path "$path" does not contain a "flutter" directory.';
  }
}

/// Represents a single output target in the `$ENGINE/src/out` directory.
final class Output {
  const Output._(this.path);

  /// The directory containing the output target.
  final io.Directory path;

  /// The `compile_commands.json` file that should exist for this output target.
  ///
  /// The file may not exist.
  io.File get compileCommandsJson {
    return io.File(p.join(path.path, 'compile_commands.json'));
  }
}
