// 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 'package:dev_compiler/dev_compiler.dart';
import 'package:dev_compiler/src/command/command.dart';
import 'package:dev_compiler/src/js_ast/js_ast.dart';
import 'package:front_end/src/api_unstable/ddc.dart' as fe;
import 'package:kernel/target/targets.dart';

/// Result compiling using [compileFromMemory].
///
/// This is meant for testing and therefore include not only the resulting
/// [Program] various artifacts of the compilation.
class MemoryCompilerResult {
  final fe.DdcResult ddcResult;
  final ProgramCompiler compiler;
  final Program program;
  final List<fe.CfeDiagnosticMessage> errors;

  MemoryCompilerResult(
    this.ddcResult,
    this.compiler,
    this.program,
    this.errors,
  );
}

/// Result of compiling using [componentFromMemory].
///
/// This is meant for use in tests and performs the front end compilation to
/// components without calling DDC.
class MemoryComponentResult {
  final fe.DdcResult ddcResult;
  final List<fe.CfeDiagnosticMessage> errors;
  fe.InitializedCompilerState? initialCompilerState;

  MemoryComponentResult(this.ddcResult, this.errors, this.initialCompilerState);
}

/// Uri used as the base uri for files provided in memory through the
/// [MemoryFileSystem].
Uri memoryDirectory = Uri.parse('memory://');

/// Compiles [entryPoint] to a kernel `Component` using the [memoryFiles] as
/// sources.
///
/// [memoryFiles] maps relative paths to their source text. [entryPoint] must
/// be absolute, using [baseUri] (defaulted to [memoryDirectory]) to refer to a
/// file from [memoryFiles].
Future<MemoryComponentResult> componentFromMemory(
  Map<String, String> memoryFiles,
  Uri entryPoint, {
  Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags = const {},
  Uri? baseUri,
}) async {
  baseUri ??= memoryDirectory;
  var errors = <fe.CfeDiagnosticMessage>[];
  void diagnosticMessageHandler(fe.CfeDiagnosticMessage message) {
    if (message.severity == fe.CfeSeverity.error) {
      errors.add(message);
    }
    fe.printDiagnosticMessage(message, print);
  }

  var memoryFileSystem = fe.MemoryFileSystem(baseUri);
  for (var entry in memoryFiles.entries) {
    memoryFileSystem
        .entityForUri(baseUri.resolve(entry.key))
        .writeAsStringSync(entry.value);
  }
  var compilerState = fe.initializeCompiler(
    null,
    false,
    sourcePathToUri(getSdkPath()),
    sourcePathToUri(defaultSdkSummaryPath),
    null,
    sourcePathToUri(defaultLibrarySpecPath),
    [],
    DevCompilerTarget(TargetFlags(trackWidgetCreation: false)),
    fileSystem: fe.HybridFileSystem(memoryFileSystem),
    environmentDefines: {},
    explicitExperimentalFlags: explicitExperimentalFlags,
  );
  var result = await fe.compile(compilerState, [
    entryPoint,
  ], diagnosticMessageHandler);
  if (result == null) {
    throw 'Memory compilation failed';
  }
  return MemoryComponentResult(result, errors, compilerState);
}

/// Compiles [entryPoint] to a kernel `Component` using the [memoryFiles] as
/// sources. Uses the incremental compiler.
///
/// [memoryFiles] maps relative paths to their source text. [entryPoint] must
/// be absolute, using [baseUri] (defaulted to [memoryDirectory]) to refer to a
/// file from [memoryFiles].
Future<MemoryComponentResult> incrementalComponentFromMemory(
  Map<String, String> memoryFiles,
  Uri entryPoint, {
  Map<fe.ExperimentalFlag, bool> explicitExperimentalFlags = const {},
  Uri? baseUri,
  fe.InitializedCompilerState? initialCompilerState,
  Uri? packageConfigUri,
}) async {
  baseUri ??= memoryDirectory;
  var errors = <fe.CfeDiagnosticMessage>[];
  void diagnosticMessageHandler(fe.CfeDiagnosticMessage message) {
    if (message.severity == fe.CfeSeverity.error) {
      errors.add(message);
    }
    fe.printDiagnosticMessage(message, print);
  }

  var memoryFileSystem = fe.MemoryFileSystem(baseUri);
  for (var entry in memoryFiles.entries) {
    memoryFileSystem
        .entityForUri(baseUri.resolve(entry.key))
        .writeAsStringSync(entry.value);
  }
  var inputDigests = {
    sourcePathToUri(defaultSdkSummaryPath): const [0],
  };
  var compilerState = await fe.initializeIncrementalCompiler(
    initialCompilerState,
    {},
    [],
    false,
    sourcePathToUri(getSdkPath()),
    sourcePathToUri(defaultSdkSummaryPath),
    packageConfigUri,
    sourcePathToUri(defaultLibrarySpecPath),
    [],
    inputDigests,
    DevCompilerTarget(TargetFlags(trackWidgetCreation: false)),
    fileSystem: fe.HybridFileSystem(memoryFileSystem),
    environmentDefines: {},
    explicitExperimentalFlags: explicitExperimentalFlags,
  );
  var incrementalCompiler = compilerState.incrementalCompiler!;
  compilerState.options.onDiagnostic = diagnosticMessageHandler;
  var incrementalCompilerResult = await incrementalCompiler.computeDelta(
    entryPoints: [entryPoint],
    fullComponent: false,
  );
  var cachedSdkInput =
      compilerState.workerInputCache![sourcePathToUri(defaultSdkSummaryPath)];
  var result = fe.DdcResult(
    incrementalCompilerResult.component,
    cachedSdkInput?.component,
    [],
    incrementalCompilerResult.classHierarchy,
    incrementalCompilerResult.neededDillLibraries,
  );
  return MemoryComponentResult(result, errors, compilerState);
}

/// Compiles [entryPoint] to JavaScript using the [memoryFiles] as sources.
///
/// [memoryFiles] maps relative paths to their source text. [entryPoint] must
/// be absolute, using [memoryDirectory] as a base uri to refer to a file from
/// [memoryFiles].
Future<MemoryCompilerResult> compileFromMemory(
  Map<String, String> memoryFiles,
  Uri entryPoint, {
  Map<fe.ExperimentalFlag, bool>? explicitExperimentalFlags,
  Uri? baseUri,
}) async {
  baseUri ??= memoryDirectory;
  var MemoryComponentResult(ddcResult: result, :errors) =
      await componentFromMemory(memoryFiles, entryPoint, baseUri: baseUri);
  var options = Options(moduleName: 'test');
  var compiler =
      // TODO(nshahan): Do we need to support [importToSummary] and
      // [summaryToModule].
      ProgramCompiler(result.component, result.classHierarchy, options, {}, {});

  var jsModule = compiler.emitModule(result.compiledLibraries);

  return MemoryCompilerResult(result, compiler, jsModule, errors);
}
