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

// @dart = 2.7

import 'dart:io';

import 'package:compiler/compiler_api.dart' as api;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common/codegen.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:compiler/src/inferrer/types.dart';
import 'package:compiler/src/serialization/serialization.dart';
import 'package:compiler/src/serialization/strategies.dart';
import 'package:compiler/src/serialization/task.dart';
import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;
import '../helpers/memory_compiler.dart';
import '../helpers/text_helpers.dart';

/// Entries in dump info that naturally differ between compilations.
const List<String> dumpInfoExceptions = [
  '"compilationMoment":',
  '"compilationDuration":',
  '"toJsonDuration":'
];

void generateJavaScriptCode(
    Compiler compiler, GlobalTypeInferenceResults globalTypeInferenceResults) {
  final codegenInputs = compiler.initializeCodegen(globalTypeInferenceResults);
  final codegenResults = OnDemandCodegenResults(globalTypeInferenceResults,
      codegenInputs, compiler.backendStrategy.functionCompiler);
  final programSize = compiler.runCodegenEnqueuer(codegenResults);
  if (compiler.options.dumpInfo) {
    compiler.runDumpInfo(codegenResults, programSize);
  }
}

void finishCompileAndCompare(
    Map<api.OutputType, Map<String, String>> expectedOutput,
    OutputCollector actualOutputCollector,
    Compiler compiler,
    SerializationStrategy strategy,
    {bool stoppedAfterClosedWorld = false,
    bool stoppedAfterTypeInference = false}) {
  if (stoppedAfterClosedWorld) {
    JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
    var newClosedWorldAndIndices =
        cloneClosedWorld(compiler, closedWorld, strategy);
    compiler.performGlobalTypeInference(newClosedWorldAndIndices.data);
  }

  if (stoppedAfterClosedWorld || stoppedAfterTypeInference) {
    GlobalTypeInferenceResults globalInferenceResults =
        compiler.globalInference.resultsForTesting;
    var indices = compiler.closedWorldIndicesForTesting;
    GlobalTypeInferenceResults newGlobalInferenceResults =
        cloneInferenceResults(
            indices, compiler, globalInferenceResults, strategy);
    generateJavaScriptCode(compiler, newGlobalInferenceResults);
  }
  var actualOutput = actualOutputCollector.clear();
  Expect.setEquals(
      expectedOutput.keys, actualOutput.keys, "Output type mismatch.");

  void check(api.OutputType outputType, Map<String, String> fileMap) {
    Map<String, String> newFileMap = actualOutput[outputType];
    Expect.setEquals(fileMap.keys, newFileMap.keys,
        "File mismatch for output type $outputType.");
    fileMap.forEach((String fileName, String code) {
      String newCode = newFileMap[fileName];
      bool Function(int, List<String>, List<String>) filter;
      if (outputType == api.OutputType.dumpInfo) {
        filter = (int index, List<String> lines1, List<String> lines2) {
          if (index <= lines1.length && index <= lines2.length) {
            String line1 = lines1[index];
            String line2 = lines2[index];
            for (String exception in dumpInfoExceptions) {
              if (line1.trim().startsWith(exception) &&
                  line2.trim().startsWith(exception)) {
                return true;
              }
            }
          }
          return false;
        };
      }
      int failureLine =
          checkEqualContentAndShowDiff(code, newCode, filter: filter);
      Expect.isNull(
          failureLine,
          "Output mismatch at line $failureLine in "
          "file '${fileName}' of type ${outputType}.");
    });
  }

  expectedOutput.forEach(check);
}

runTest(
    {Uri entryPoint,
    Map<String, String> memorySourceFiles: const <String, String>{},
    Uri packageConfig,
    Uri librariesSpecificationUri,
    List<String> options,
    SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
    bool useDataKinds: false}) async {
  var commonOptions = options + ['--out=out.js'];
  OutputCollector collector = new OutputCollector();
  CompilationResult result = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: memorySourceFiles,
      packageConfig: packageConfig,
      librariesSpecificationUri: librariesSpecificationUri,
      options: commonOptions,
      outputProvider: collector,
      beforeRun: (Compiler compiler) {
        compiler.forceSerializationForTesting = true;
      });
  Expect.isTrue(result.isSuccess);
  Map<api.OutputType, Map<String, String>> expectedOutput = collector.clear();

  OutputCollector collector2 = new OutputCollector();
  CompilationResult result2 = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: memorySourceFiles,
      packageConfig: packageConfig,
      librariesSpecificationUri: librariesSpecificationUri,
      options: commonOptions,
      outputProvider: collector2,
      beforeRun: (Compiler compiler) {
        compiler.forceSerializationForTesting = true;
        compiler.stopAfterClosedWorldForTesting = true;
      });
  Expect.isTrue(result2.isSuccess);

  var dillUri = Uri.parse('out.dill');
  var closedWorldUri = Uri.parse('world.data');
  OutputCollector collector3a = new OutputCollector();
  CompilationResult result3a = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: memorySourceFiles,
      packageConfig: packageConfig,
      librariesSpecificationUri: librariesSpecificationUri,
      options: options +
          ['--out=$dillUri', '${Flags.writeClosedWorld}=$closedWorldUri'],
      outputProvider: collector3a,
      beforeRun: (Compiler compiler) {
        compiler.forceSerializationForTesting = true;
      });
  Expect.isTrue(result3a.isSuccess);
  Expect.isTrue(collector3a.binaryOutputMap.containsKey(dillUri));
  Expect.isTrue(collector3a.binaryOutputMap.containsKey(closedWorldUri));

  Directory dir =
      await Directory.systemTemp.createTemp('serialization_test_helper');
  var dillFileUri = dir.uri.resolve('out.dill');
  var closedWorldFileUri = dir.uri.resolve('world.data');
  var dillBytes = collector3a.binaryOutputMap[dillUri].list;
  var closedWorldBytes = collector3a.binaryOutputMap[closedWorldUri].list;
  File(dillFileUri.path).writeAsBytesSync(dillBytes);
  File(closedWorldFileUri.path).writeAsBytesSync(closedWorldBytes);
  OutputCollector collector3b = new OutputCollector();
  CompilationResult result3b = await runCompiler(
      entryPoint: entryPoint,
      memorySourceFiles: memorySourceFiles,
      packageConfig: packageConfig,
      librariesSpecificationUri: librariesSpecificationUri,
      options: commonOptions +
          [
            '${Flags.inputDill}=$dillFileUri',
            '${Flags.readClosedWorld}=$closedWorldFileUri',
            '${Flags.writeData}=global.data'
          ],
      outputProvider: collector3b,
      beforeRun: (Compiler compiler) {
        compiler.forceSerializationForTesting = true;
        compiler.stopAfterGlobalTypeInferenceForTesting = true;
      });
  Expect.isTrue(result3b.isSuccess);

  finishCompileAndCompare(
      expectedOutput, collector2, result2.compiler, strategy,
      stoppedAfterClosedWorld: true);
  finishCompileAndCompare(
      expectedOutput, collector3b, result3b.compiler, strategy,
      stoppedAfterTypeInference: true);
  await dir.delete(recursive: true);
}

void checkData(List<int> data, List<int> newData) {
  Expect.equals(
      data.length, newData.length, "Reserialization data length mismatch.");
  for (int i = 0; i < data.length; i++) {
    if (data[i] != newData[i]) {
      print('Reserialization data mismatch at offset $i:');
      for (int j = i - 50; j < i + 50; j++) {
        if (0 <= j && j <= data.length) {
          String text;
          if (data[j] == newData[j]) {
            text = '${data[j]}';
          } else {
            text = '${data[j]} <> ${newData[j]}';
          }
          print('${j == i ? '> ' : '  '}$j: $text');
        }
      }
      break;
    }
  }
  Expect.listEquals(data, newData);
}

DataAndIndices<JsClosedWorld> cloneClosedWorld(Compiler compiler,
    JsClosedWorld closedWorld, SerializationStrategy strategy) {
  ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
  List<int> irData = strategy.serializeComponent(component);
  List<int> closedWorldData =
      strategy.serializeClosedWorld(closedWorld, compiler.options);
  print('data size: ${closedWorldData.length}');

  ir.Component newComponent = strategy.deserializeComponent(irData);
  var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
      compiler.options,
      compiler.reporter,
      compiler.environment,
      compiler.abstractValueStrategy,
      newComponent,
      closedWorldData);
  List<int> newClosedWorldData = strategy.serializeClosedWorld(
      newClosedWorldAndIndices.data, compiler.options);
  checkData(closedWorldData, newClosedWorldData);
  return newClosedWorldAndIndices;
}

/// Tests that cloned inference results serialize to the same data.
///
/// Does 3 round trips to serialize/deserialize the provided data. The first
/// round normalizes the data as some information might be dropped in the
/// serialization/deserialization process. The second and third rounds are
/// compared for consistency.
GlobalTypeInferenceResults cloneInferenceResults(
    DataSourceIndices indices,
    Compiler compiler,
    GlobalTypeInferenceResults results,
    SerializationStrategy strategy) {
  List<int> irData = strategy.unpackAndSerializeComponent(results);
  List<int> closedWorldData =
      strategy.serializeClosedWorld(results.closedWorld, compiler.options);
  List<int> worldData = strategy.serializeGlobalTypeInferenceResults(
      indices, results, compiler.options);
  print('data size: ${worldData.length}');

  ir.Component newComponent = strategy.deserializeComponent(irData);
  var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
      compiler.options,
      compiler.reporter,
      compiler.environment,
      compiler.abstractValueStrategy,
      newComponent,
      closedWorldData);
  var newIndices = indices == null ? null : newClosedWorldAndIndices.indices;
  GlobalTypeInferenceResults initialResults = strategy
      .deserializeGlobalTypeInferenceResults(
          compiler.options,
          compiler.reporter,
          compiler.environment,
          compiler.abstractValueStrategy,
          newComponent,
          newClosedWorldAndIndices.data,
          newIndices,
          worldData)
      .data;
  List<int> initialWorldData = strategy.serializeGlobalTypeInferenceResults(
      newIndices, initialResults, compiler.options);
  GlobalTypeInferenceResults finalResults = strategy
      .deserializeGlobalTypeInferenceResults(
          compiler.options,
          compiler.reporter,
          compiler.environment,
          compiler.abstractValueStrategy,
          newComponent,
          newClosedWorldAndIndices.data,
          newIndices,
          worldData)
      .data;
  List<int> finalWorldData = strategy.serializeGlobalTypeInferenceResults(
      newIndices, finalResults, compiler.options);
  checkData(initialWorldData, finalWorldData);
  return finalResults;
}
