// Copyright (c) 2022, 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:io';

import 'package:args/args.dart';
import 'package:frontend_server/resident_frontend_server_utils.dart'
    show
        computeCachedDillAndCompilerOptionsPaths,
        ResidentCompilerInfo,
        sendAndReceiveResponse;
import 'package:kernel/binary/tag.dart' show isValidSdkHash;
import 'package:path/path.dart' as p;
import 'package:pub/pub.dart';

import 'core.dart';
import 'resident_frontend_constants.dart';
import 'resident_frontend_utils.dart';
import 'sdk.dart';
import 'unified_analytics.dart';

typedef CompileRequestGeneratorCallback =
    String Function({
      required String executable,
      required String outputDill,
      required ArgResults args,
      String? packages,
      String? nativeAssetsYaml,
    });

/// Uses the resident frontend compiler to compute a kernel file for
/// [executable]. Throws a [FrontendCompilerException] if the compilation
/// fails or if the source code contains compilation errors.
///
/// [executable] is expected to contain a path to the dart source file and
/// a package_config file.
///
/// [serverInfoFile] is the location that should be checked to find an existing
/// Resident Frontend Compiler. If one does not exist, a server is created and
/// its address and port information is written to this file location.
///
/// [args] is the [ArgResults] object that is created by the DartDev commands.
/// This is where the optional path override for the serverInfoFile is passed
/// in.
///
/// [compileRequestGenerator] is applied to produce a request for the Resident
/// Frontend Server.
Future<DartExecutableWithPackageConfig> generateKernel(
  DartExecutableWithPackageConfig executable,
  File serverInfoFile,
  ArgResults args,
  CompileRequestGeneratorCallback compileRequestGenerator, {
  required bool quiet,
  bool aot = false,
  String? nativeAssetsYaml,
  bool progressUpdatesOnStderr = false,
}) async {
  // Locates the package_config.json and cached kernel file, makes sure the
  // resident frontend server is up and running, and computes a kernel.
  await ensureCompilationServerIsRunning(
    serverInfoFile,
    quiet: quiet,
    progressUpdatesOnStderr: progressUpdatesOnStderr,
  );

  final packageRoot = _packageRootFor(executable);
  final packageConfig = packageRoot != null
      ? p.join(packageRoot, packageConfigName)
      : null;

  final canonicalizedExecutablePath = p.canonicalize(executable.executable);
  final cachedDillPath = computeCachedDillAndCompilerOptionsPaths(
    canonicalizedExecutablePath,
  ).cachedDillPath;

  Map<String, dynamic> result;
  try {
    result = await sendAndReceiveResponse(
      compileRequestGenerator(
        executable: canonicalizedExecutablePath,
        outputDill: cachedDillPath,
        packages: packageConfig,
        args: args,
        nativeAssetsYaml: nativeAssetsYaml,
      ),
      serverInfoFile,
    );
  } on FileSystemException catch (e) {
    throw FrontendCompilerException._(e.message, CompilationIssue.serverError);
  }
  if (!result[responseSuccessString]) {
    if (result.containsKey(responseErrorString)) {
      throw FrontendCompilerException._(
        result[responseErrorString],
        CompilationIssue.serverError,
      );
    } else {
      throw FrontendCompilerException._(
        (result[responseOutputString] as List<dynamic>).join('\n'),
        CompilationIssue.compilationError,
      );
    }
  }
  return DartExecutableWithPackageConfig(
    executable: cachedDillPath,
    packageConfig: packageConfig,
  );
}

/// Ensures that a Resident Frontend Compiler associated with [serverInfoFile]
/// will be running at the point when the future returned by this function
/// completes. Throws a [FrontendCompilerException] if starting the server
/// fails.
Future<void> ensureCompilationServerIsRunning(
  File serverInfoFile, {
  required bool quiet,
  bool progressUpdatesOnStderr = false,
}) async {
  if (serverInfoFile.existsSync()) {
    final residentCompilerInfo = ResidentCompilerInfo.fromFile(serverInfoFile);
    if (residentCompilerInfo.sdkHash != null &&
        isValidSdkHash(residentCompilerInfo.sdkHash!)) {
      // There is already a Resident Frontend Compiler associated with
      // [serverInfoFile] that is running and compatible with the Dart SDK that
      // the user is currently using.
      return;
    } else {
      if (!quiet) {
        log.stderr(
          'The Dart SDK has been upgraded or downgraded since the Resident '
          'Frontend Compiler was started, so the Resident Frontend Compiler will '
          'now be restarted for compatibility reasons.',
        );
      }
      await shutDownOrForgetResidentFrontendCompiler(serverInfoFile);
    }
  }
  try {
    Directory(p.dirname(serverInfoFile.path)).createSync(recursive: true);
    final Process frontendServerProcess;
    if (File(sdk.frontendServerAotSnapshot).existsSync()) {
      frontendServerProcess = await Process.start(
        sdk.dartAotRuntime,
        [
          sdk.frontendServerAotSnapshot,
          '--resident-info-file-name=${serverInfoFile.absolute.path}',
        ],
        workingDirectory: homeDir?.path,
        mode: ProcessStartMode.detachedWithStdio,
      );
    } else {
      throw StateError('Unable to find snapshot for frontend server');
    }

    final serverOutput = String.fromCharCodes(
      await frontendServerProcess.stdout.first,
    ).trim();
    if (serverOutput.startsWith('Error')) {
      throw StateError(serverOutput);
    }
    if (!quiet) {
      final sink = progressUpdatesOnStderr ? log.stderr : log.stdout;
      // Prints the server's address and port information
      sink(serverOutput);
      sink('');
      sink('Run dart compilation-server shutdown to terminate the process.');
    }
  } catch (e) {
    throw FrontendCompilerException._(
      e.toString(),
      CompilationIssue.serverCreationError,
    );
  }
}

/// Returns the path to the root of the [executable]'s package, or null
/// if it is a standalone dart file.
String? _packageRootFor(DartExecutableWithPackageConfig executable) {
  Directory currentDirectory = Directory(
    p.dirname(p.canonicalize(executable.executable)),
  );

  while (currentDirectory.parent.path != currentDirectory.path) {
    if (File(p.join(currentDirectory.path, packageConfigName)).existsSync()) {
      return currentDirectory.path;
    }
    currentDirectory = currentDirectory.parent;
  }
  return null;
}

/// Indicates the type of issue encountered with the
/// Resident Frontend Compiler
enum CompilationIssue {
  /// Communication with the Resident Frontend Compiler failed.
  serverError,

  /// The Resident Frontend Compiler failed to launch
  serverCreationError,

  /// There were compilation errors in the Dart source code.
  compilationError,

  /// Resident mode is only supported for sources within Dart packages
  standaloneProgramError,
}

/// Indicates an error with the Resident Frontend Compiler.
class FrontendCompilerException implements Exception {
  final String message;
  final CompilationIssue issue;

  FrontendCompilerException._(this.message, this.issue);

  @override
  String toString() {
    return 'FrontendCompilerException: $message';
  }
}
