// Copyright (c) 2018, 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:dart2wasm/target.dart' show WasmTarget;
import 'package:front_end/src/api_unstable/vm.dart'
    show
        CompilerOptions,
        DiagnosticMessage,
        computePlatformBinariesLocation,
        kernelForModule,
        kernelForProgram,
        parseExperimentalArguments,
        parseExperimentalFlags;
import 'package:kernel/ast.dart';
import 'package:kernel/text/ast_to_text.dart' show Printer;
import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
import 'package:kernel/target/targets.dart';
import 'package:test/test.dart';

/// Environment define to update expectation files on failures.
const kUpdateExpectations = 'updateExpectations';

/// Environment define to dump actual results alongside expectations.
const kDumpActualResult = 'dump.actual.result';

Future<Component> compileTestCaseToKernelProgram(
  Uri sourceUri, {
  required Target target,
  List<String>? experimentalFlags,
  Map<String, String>? environmentDefines,
  Uri? packagesFileUri,
  List<Uri>? linkedDependencies,
}) async {
  Directory? tempDirectory;
  try {
    final platformFileName =
        (target is WasmTarget)
            ? target.platformFile
            : 'vm_platform_strong.dill';
    final platformKernel = computePlatformBinariesLocation().resolve(
      platformFileName,
    );
    environmentDefines ??= <String, String>{};
    final options =
        new CompilerOptions()
          ..target = target
          ..additionalDills = <Uri>[platformKernel]
          ..environmentDefines = environmentDefines
          ..packagesFileUri = packagesFileUri
          ..explicitExperimentalFlags = parseExperimentalFlags(
            parseExperimentalArguments(experimentalFlags),
            onError: (String message) {
              throw message;
            },
          )
          ..onDiagnostic = (DiagnosticMessage message) {
            fail("Compilation error: ${message.plainTextFormatted.join('\n')}");
          };
    if (linkedDependencies != null) {
      final Component component =
          (await kernelForModule(linkedDependencies, options)).component!;
      tempDirectory = await Directory.systemTemp.createTemp();
      Uri uri = tempDirectory.uri.resolve("generated.dill");
      File generated = new File.fromUri(uri);
      IOSink sink = generated.openWrite();
      try {
        new BinaryPrinter(sink).writeComponentFile(component);
      } finally {
        await sink.close();
      }
      options..additionalDills = <Uri>[platformKernel, uri];
    }

    final Component component =
        (await kernelForProgram(sourceUri, options))!.component!;

    // Make sure the library name is the same and does not depend on the order
    // of test cases.
    component.mainMethod!.enclosingLibrary.name = '#lib';
    return component;
  } finally {
    await tempDirectory?.delete(recursive: true);
  }
}

/// Returns a human-readable string representation of [library].
///
/// If [removeSelectorIds] is provided, selector ids above 99 are removed.
/// Extra libraries apart from the main library are passed to the front-end as
/// additional dills, which places them last in the library list, causing them
/// to have very high (and often changing) selector IDs.
String kernelLibraryToString(
  Library library, {
  bool removeSelectorIds = false,
}) {
  final StringBuffer buffer = new StringBuffer();
  final printer = new Printer(buffer, showMetadata: true);
  printer.writeLibraryFile(library);
  printer.writeConstantTable(library.enclosingComponent!);
  String result = buffer.toString();
  final libraryName = library.name;
  if (libraryName != null) {
    result = result.replaceAll(library.importUri.toString(), library.name!);
  }
  if (removeSelectorIds) {
    result = result
        .replaceAll(RegExp(r',methodOrSetterSelectorId:\d{3,}'), '')
        .replaceAll(RegExp(r',getterSelectorId:\d{3,}'), '');
  }
  return result;
}

String kernelComponentToString(Component component) {
  final StringBuffer buffer = new StringBuffer();
  new Printer(buffer, showMetadata: true).writeComponentFile(component);
  final mainLibrary = component.mainMethod!.enclosingLibrary;
  return buffer.toString().replaceAll(
    mainLibrary.importUri.toString(),
    mainLibrary.name!,
  );
}

class DevNullSink<T> implements Sink<T> {
  @override
  void add(T data) {}

  @override
  void close() {}
}

void ensureKernelCanBeSerializedToBinary(Component component) {
  new BinaryPrinter(new DevNullSink<List<int>>()).writeComponentFile(component);
}

class Difference {
  final int line;
  final String actual;
  final String expected;

  Difference(this.line, this.actual, this.expected);
}

Difference findFirstDifference(String actual, String expected) {
  final actualLines = actual.split('\n');
  final expectedLines = expected.split('\n');
  int i = 0;
  for (; i < actualLines.length && i < expectedLines.length; ++i) {
    if (actualLines[i] != expectedLines[i]) {
      return new Difference(i + 1, actualLines[i], expectedLines[i]);
    }
  }
  return new Difference(
    i + 1,
    i < actualLines.length ? actualLines[i] : '<END>',
    i < expectedLines.length ? expectedLines[i] : '<END>',
  );
}

void compareResultWithExpectationsFile(
  Uri source,
  String actual, {
  String expectFilePostfix = '',
}) {
  final baseFilename = '${source.toFilePath()}$expectFilePostfix';
  final expectFile = new File('$baseFilename.expect');
  final expected = expectFile.existsSync() ? expectFile.readAsStringSync() : '';

  if (actual != expected) {
    if (bool.fromEnvironment(kUpdateExpectations)) {
      expectFile.writeAsStringSync(actual);
      print("  Updated $expectFile");
    } else {
      if (bool.fromEnvironment(kDumpActualResult)) {
        new File('$baseFilename.actual').writeAsStringSync(actual);
      }
      Difference diff = findFirstDifference(actual, expected);
      fail("""

Result is different for the test case $source

The first difference is at line ${diff.line}.
Actual:   ${diff.actual}
Expected: ${diff.expected}

This failure can be caused by changes in the front-end if it starts generating
different kernel AST for the same Dart programs.

In order to re-generate expectations run tests with -D$kUpdateExpectations=true VM option:

  tools/test.py -m release --vm-options -D$kUpdateExpectations=true --timeout 600 pkg/vm/

In order to dump actual results into .actual files run tests with -D$kDumpActualResult=true VM option:

  tools/test.py -m release --vm-options -D$kDumpActualResult=true --timeout 600 pkg/vm/

""");
    }
  }
}
