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

import 'package:package_config/package_config.dart';

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/user_messages.dart';
import '../cache.dart';
import '../dart/package_map.dart';

/// A strategy for locating the `out/` directory of a local engine build.
///
/// The flutter tool can be run with the output files of one or more engine builds
/// replacing the cached artifacts. Typically this is done by setting the
/// `--local-engine` command line flag to the name of the desired engine variant
/// (e.g. "host_debug_unopt"). Provided that the `flutter/` and `engine/` directories
/// are located adjacent to one another, the output folder will be located
/// automatically.
///
/// For scenarios where the engine is not adjacent to flutter, the
/// `--local-engine-src-path` can be provided to give an exact path.
///
/// For more information on local engines, see README.md.
class LocalEngineLocator {
  LocalEngineLocator({
    required Platform platform,
    required Logger logger,
    required FileSystem fileSystem,
    required String flutterRoot,
    required UserMessages userMessages,
  }) : _platform = platform,
       _logger = logger,
       _fileSystem = fileSystem,
       _flutterRoot = flutterRoot,
        _userMessages = userMessages;

  final Platform _platform;
  final Logger _logger;
  final FileSystem _fileSystem;
  final String _flutterRoot;
  final UserMessages _userMessages;

  /// Returns the engine build path of a local engine if one is located, otherwise `null`.
  Future<EngineBuildPaths?> findEnginePath({
    String? engineSourcePath,
    String? localEngine,
    String? localHostEngine,
    String? localWebSdk,
    String? packagePath,
  }) async {
    engineSourcePath ??= _platform.environment[kFlutterEngineEnvironmentVariableName];
    if (engineSourcePath == null && localEngine == null && localWebSdk == null && packagePath == null) {
      return null;
    }

    if (engineSourcePath == null) {
      try {
        if (localEngine != null) {
          engineSourcePath = _findEngineSourceByBuildPath(localEngine);
        }
        if (localWebSdk != null) {
          engineSourcePath ??= _findEngineSourceByBuildPath(localWebSdk);
        }
        engineSourcePath ??= await _findEngineSourceByPackageConfig(packagePath);
      } on FileSystemException catch (e) {
        _logger.printTrace('Local engine auto-detection file exception: $e');
        engineSourcePath = null;
      }

      // If engineSourcePath is still not set, try to determine it by flutter root.
      engineSourcePath ??= _tryEnginePath(
        _fileSystem.path.join(_fileSystem.directory(_flutterRoot).parent.path, 'engine', 'src'),
      );
    }

    if (engineSourcePath != null && _tryEnginePath(engineSourcePath) == null) {
      throwToolExit(
        _userMessages.runnerNoEngineBuildDirInPath(engineSourcePath),
        exitCode: 2,
      );
    }

    if (engineSourcePath != null) {
      _logger.printTrace('Local engine source at $engineSourcePath');
      return _findEngineBuildPath(
        engineSourcePath: engineSourcePath,
        localEngine: localEngine,
        localWebSdk: localWebSdk,
        localHostEngine: localHostEngine,
      );
    }
    if (localEngine != null || localWebSdk != null) {
      throwToolExit(
        _userMessages.runnerNoEngineSrcDir(
          kFlutterEnginePackageName,
          kFlutterEngineEnvironmentVariableName,
        ),
        exitCode: 2,
      );
    }
    return null;
  }

  String? _findEngineSourceByBuildPath(String buildPath) {
    // When the local engine is an absolute path to a variant inside the
    // out directory, parse the engine source.
    // --local-engine /path/to/cache/builder/src/out/host_debug_unopt
    if (_fileSystem.path.isAbsolute(buildPath)) {
      final Directory buildDirectory = _fileSystem.directory(buildPath);
      final Directory outDirectory = buildDirectory.parent;
      final Directory srcDirectory = outDirectory.parent;
      if (buildDirectory.existsSync() && outDirectory.basename == 'out' && srcDirectory.basename == 'src') {
        _logger.printTrace('Parsed engine source from local engine as ${srcDirectory.path}.');
        return srcDirectory.path;
      }
    }
    return null;
  }

  Future<String?> _findEngineSourceByPackageConfig(String? packagePath) async {
    final PackageConfig packageConfig = await loadPackageConfigWithLogging(
      _fileSystem.file(
        // TODO(zanderso): update to package_config
        packagePath ?? _fileSystem.path.join('.packages'),
      ),
      logger: _logger,
      throwOnError: false,
    );
    // Skip if sky_engine is the version in bin/cache.
    Uri? engineUri = packageConfig[kFlutterEnginePackageName]?.packageUriRoot;
    final String cachedPath = _fileSystem.path.join(_flutterRoot, 'bin', 'cache', 'pkg', kFlutterEnginePackageName, 'lib');
    if (engineUri != null && _fileSystem.identicalSync(cachedPath, engineUri.path)) {
      _logger.printTrace('Local engine auto-detection sky_engine in $packagePath is the same version in bin/cache.');
      engineUri = null;
    }
    // If sky_engine is specified and the engineSourcePath not set, try to
    // determine the engineSourcePath by sky_engine setting. A typical engine Uri
    // looks like:
    // file://flutter-engine-local-path/src/out/host_debug_unopt/gen/dart-pkg/sky_engine/lib/
    String? engineSourcePath;
    final String? engineUriPath = engineUri?.path;
    if (engineUriPath != null) {
      engineSourcePath = _fileSystem.directory(engineUriPath)
        .parent
        .parent
        .parent
        .parent
        .parent
        .parent
        .path;
      if (engineSourcePath == _fileSystem.path.dirname(engineSourcePath) || engineSourcePath.isEmpty) {
        engineSourcePath = null;
        throwToolExit(
          _userMessages.runnerNoEngineSrcDir(
            kFlutterEnginePackageName,
            kFlutterEngineEnvironmentVariableName,
          ),
          exitCode: 2,
        );
      }
    }
    return engineSourcePath;
  }

  EngineBuildPaths _findEngineBuildPath({
    required String engineSourcePath,
    String? localEngine,
    String? localWebSdk,
    String? localHostEngine,
  }) {
    if (localEngine == null && localWebSdk == null) {
      throwToolExit(_userMessages.runnerLocalEngineOrWebSdkRequired, exitCode: 2);
    }

    String? engineBuildPath;
    String? engineHostBuildPath;
    if (localEngine != null) {
      engineBuildPath = _fileSystem.path.normalize(_fileSystem.path.join(engineSourcePath, 'out', localEngine));
      if (!_fileSystem.isDirectorySync(engineBuildPath)) {
        throwToolExit(_userMessages.runnerNoEngineBuild(engineBuildPath), exitCode: 2);
      }

      if (localHostEngine == null) {
        throwToolExit(_userMessages.runnerLocalEngineRequiresHostEngine);
      }
      engineHostBuildPath = _fileSystem.path.normalize(
        _fileSystem.path.join(_fileSystem.path.dirname(engineBuildPath), localHostEngine),
      );
      if (!_fileSystem.isDirectorySync(engineHostBuildPath)) {
        throwToolExit(_userMessages.runnerNoEngineBuild(engineHostBuildPath), exitCode: 2);
      }
    }

    String? webSdkPath;
    if (localWebSdk != null) {
      webSdkPath = _fileSystem.path.normalize(_fileSystem.path.join(engineSourcePath, 'out', localWebSdk));
      if (!_fileSystem.isDirectorySync(webSdkPath)) {
        throwToolExit(_userMessages.runnerNoWebSdk(webSdkPath), exitCode: 2);
      }
    }

    return EngineBuildPaths(targetEngine: engineBuildPath, webSdk: webSdkPath, hostEngine: engineHostBuildPath);
  }

  String? _tryEnginePath(String enginePath) {
    if (_fileSystem.isDirectorySync(_fileSystem.path.join(enginePath, 'out'))) {
      return enginePath;
    }
    return null;
  }
}
