// Copyright (c) 2023, 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 'dart:async';
import 'dart:io';

import 'package:dartdev/src/sdk.dart';
import 'package:dartdev/src/utils.dart';
import 'package:logging/logging.dart';
import 'package:native_assets_builder/native_assets_builder.dart';
import 'package:native_assets_cli/native_assets_cli_internal.dart';

import 'core.dart';

/// Compiles all native assets for host OS in JIT mode.
///
/// If provided, only native assets of all transitive dependencies of
/// [runPackageName] are built.
Future<(bool success, List<EncodedAsset> assets)> compileNativeAssetsJit({
  required bool verbose,
  String? runPackageName,
}) async {
  final workingDirectory = Directory.current.uri;
  // TODO(https://github.com/dart-lang/package_config/issues/126): Use
  // package config resolution from package:package_config.
  if (!await File.fromUri(
          workingDirectory.resolve('.dart_tool/package_config.json'))
      .exists()) {
    if (await File.fromUri(workingDirectory.resolve('pubspec.yaml')).exists()) {
      // Silently run `pub get`, this is what would happen in
      // `getExecutableForCommand` later.
      final result = await Process.run(sdk.dart, ['pub', 'get']);
      if (result.exitCode != 0) {
        return (true, <EncodedAsset>[]);
      }
    } else {
      return (true, <EncodedAsset>[]);
    }
  }
  final nativeAssetsBuildRunner = NativeAssetsBuildRunner(
    // This always runs in JIT mode.
    dartExecutable: Uri.file(sdk.dart),
    logger: logger(verbose),
  );
  final target = Target.current;
  final targetMacOSVersion =
      target.os == OS.macOS ? minimumSupportedMacOSVersion : null;
  final buildResult = await nativeAssetsBuildRunner.build(
    workingDirectory: workingDirectory,
    // When running in JIT mode, only the host OS needs to be build.
    target: target,
    // When running in JIT mode, only dynamic libraries are supported.
    linkModePreference: LinkModePreference.dynamic,
    // Dart has no concept of release vs debug, default to release.
    buildMode: BuildMode.release,
    includeParentEnvironment: true,
    runPackageName: runPackageName,
    targetMacOSVersion: targetMacOSVersion,
    linkingEnabled: false,
    supportedAssetTypes: [
      CodeAsset.type,
    ],
    buildValidator: (config, output) async => [
      ...await validateDataAssetBuildOutput(config, output),
      ...await validateCodeAssetBuildOutput(config, output),
    ],
    applicationAssetValidator: (assets) async => [
      ...await validateCodeAssetsInApplication(assets),
    ],
  );

  return (
    buildResult.success,
    buildResult.encodedAssets,
  );
}

/// Compiles all native assets for host OS in JIT mode, and creates the
/// native assets yaml file.
///
/// If provided, only native assets of all transitive dependencies of
/// [runPackageName] are built.
///
/// Used in `dart run` and `dart test`.
Future<(bool success, Uri? nativeAssetsYaml)> compileNativeAssetsJitYamlFile({
  required bool verbose,
  String? runPackageName,
}) async {
  final (success, assets) = await compileNativeAssetsJit(
    verbose: verbose,
    runPackageName: runPackageName,
  );
  if (!success) {
    return (false, null);
  }
  final codeAssets = assets
      .where((e) => e.type == CodeAsset.type)
      .map(CodeAsset.fromEncoded)
      .toList();
  final dataAssets = assets
      .where((e) => e.type == DataAsset.type)
      .map(DataAsset.fromEncoded)
      .toList();
  final kernelAssets = KernelAssets([
    ...[
      for (final asset in codeAssets) _targetLocation(asset),
    ],
    ...[
      for (final asset in dataAssets) _dataTargetLocation(asset),
    ]
  ]);

  final workingDirectory = Directory.current.uri;
  final assetsUri = workingDirectory.resolve('.dart_tool/native_assets.yaml');
  final nativeAssetsYaml = '''# Native assets mapping for host OS in JIT mode.
# Generated by dartdev and package:native_assets_builder.
${kernelAssets.toNativeAssetsFile()}''';
  final assetFile = File(assetsUri.toFilePath());
  await assetFile.writeAsString(nativeAssetsYaml);
  return (true, assetsUri);
}

KernelAsset _targetLocation(CodeAsset asset) {
  final linkMode = asset.linkMode;
  final KernelAssetPath kernelAssetPath;
  switch (linkMode) {
    case DynamicLoadingSystem _:
      kernelAssetPath = KernelAssetSystemPath(linkMode.uri);
    case LookupInExecutable _:
      kernelAssetPath = KernelAssetInExecutable();
    case LookupInProcess _:
      kernelAssetPath = KernelAssetInProcess();
    case DynamicLoadingBundled _:
      kernelAssetPath = KernelAssetAbsolutePath(asset.file!);
    default:
      throw Exception(
        'Unsupported CodeAsset linkMode ${linkMode.runtimeType} in asset $asset',
      );
  }
  return KernelAsset(
    id: asset.id,
    target: Target.fromArchitectureAndOS(asset.architecture!, asset.os),
    path: kernelAssetPath,
  );
}

KernelAsset _dataTargetLocation(DataAsset asset) {
  return KernelAsset(
    id: asset.id,
    target: Target.current,
    path: KernelAssetAbsolutePath(asset.file),
  );
}

Future<bool> warnOnNativeAssets() async {
  final workingDirectory = Directory.current.uri;
  if (!await File.fromUri(
          workingDirectory.resolve('.dart_tool/package_config.json'))
      .exists()) {
    // If `pub get` hasn't run, we can't know, so don't error.
    return false;
  }
  try {
    final packageLayout =
        await PackageLayout.fromRootPackageRoot(workingDirectory);
    final packagesWithNativeAssets = [
      ...await packageLayout.packagesWithAssets(Hook.build),
      ...await packageLayout.packagesWithAssets(Hook.link)
    ];
    if (packagesWithNativeAssets.isEmpty) {
      return false;
    }
    final packageNames = packagesWithNativeAssets.map((p) => p.name).join(' ');
    log.stderr(
      'Package(s) $packageNames require the native assets feature to be enabled. '
      'Enable native assets with `--enable-experiment=native-assets`.',
    );
  } on FormatException catch (e) {
    // This can be thrown if the package_config.json is malformed or has
    // duplicate entries.
    log.stderr(
      'Error encountered while parsing package_config.json: ${e.message}',
    );
  }
  return true;
}

Logger logger(bool verbose) => Logger('')
  ..onRecord.listen((LogRecord record) {
    final levelValue = record.level.value;
    if (levelValue >= Level.SEVERE.value) {
      log.stderr(record.message);
    } else if (levelValue >= Level.WARNING.value ||
        verbose && levelValue >= Level.INFO.value) {
      log.stdout(record.message);
    } else {
      // Note, this is ignored by default.
      log.trace(record.message);
    }
  });
