// 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:convert';
import "dart:io";

import 'package:front_end/src/api_unstable/vm.dart'
    show computePlatformBinariesLocation;

main() {
  final Directory tmpDir = Directory.systemTemp.createTempSync(
    "obfuscationtest",
  );
  try {
    final Uri tmpDirUri = tmpDir.uri;
    final Uri secretfilename = tmpDirUri.resolve("secretfilename.dart");
    final File secretfilenameFile = new File.fromUri(secretfilename);
    secretfilenameFile.writeAsStringSync("""
import "secretfilename2.dart";

main() {
  print("Hello, World!");
  verySecretFoo();
}
""");
    final Uri secretfilename2 = tmpDirUri.resolve("secretfilename2.dart");
    final File secretfilename2File = new File.fromUri(secretfilename2);
    secretfilename2File.writeAsStringSync("""
@pragma('vm:entry-point')
void verySecretFoo() {
  print("foo!");
  alsoVerySecretFoo();
}

void alsoVerySecretFoo() {
  print("foo too!");
}
""");

    List<MappingPair> mapping = getSnapshotMap(tmpDir, secretfilenameFile);
    bool good = verify(
      mapping,
      {
        // This contains @pragma('vm:entry-point') and the uri should not change.
        secretfilename2.toString(),
        // This contains @pragma('vm:entry-point') and the name should not change.
        "verySecretFoo",
      },
      {
        // This is not special and should have been obfuscated.
        secretfilename.toString(),
        // This is not special and should have been obfuscated.
        "alsoVerySecretFoo",
      },
    );
    if (!good) throw "Obfuscation didn't work as expected";
    print("Good");
  } finally {
    tmpDir.deleteSync(recursive: true);
  }
}

List<MappingPair> getSnapshotMap(Directory tmpDir, File compileDartFile) {
  final Uri genKernel = Platform.script.resolve('../bin/gen_kernel.dart');
  final File genKernelFile = new File.fromUri(genKernel);
  if (!genKernelFile.existsSync()) {
    throw "Didn't find gen_kernel at $genKernel";
  }

  File resolvedExecutableFile = new File(Platform.resolvedExecutable);
  Uri resolvedExecutable = resolvedExecutableFile.uri;
  String genSnapshotFilename = "gen_snapshot";
  if (Platform.isWindows) genSnapshotFilename += ".exe";

  Uri genSnapshot = resolvedExecutable.resolve(genSnapshotFilename);
  File genSnapshotFile = new File.fromUri(genSnapshot);
  if (!genSnapshotFile.existsSync()) {
    print(
      "Didn't find gen_kernel at $genSnapshot... Trying utils/$genSnapshotFilename",
    );
    genSnapshot = resolvedExecutable.resolve("utils/$genSnapshotFilename");
    genSnapshotFile = new File.fromUri(genSnapshot);
    if (!genSnapshotFile.existsSync()) {
      throw "Didn't find gen_kernel at $genSnapshot";
    }
  }

  final Uri platformDill = computePlatformBinariesLocation().resolve(
    'vm_platform_strong_product.dill',
  );
  final File platformDillFile = new File.fromUri(platformDill);
  if (!platformDillFile.existsSync()) {
    throw "Didn't find vm_platform_strong_product at $platformDill";
  }

  final Uri tmpDirUri = tmpDir.uri;

  final Uri kernelDill = tmpDirUri.resolve("kernel.dill");
  final File kernelDillFile = new File.fromUri(kernelDill);

  print("Running gen_kernel");
  // Extracted from pkg/dart2native/lib/dart2native.dart.
  final ProcessResult kernelRun = Process.runSync(Platform.resolvedExecutable, [
    genKernelFile.path,
    "--platform",
    platformDillFile.path,
    "--aot",
    "-Ddart.vm.product=true",
    "-o",
    kernelDillFile.path,
    "--invocation-modes=compile",
    "--verbosity=all",
    compileDartFile.path,
  ]);

  if (kernelRun.exitCode != 0) {
    throw "Got exit code ${kernelRun.exitCode}\n"
        "stdout: ${kernelRun.stdout}\n"
        "stderr: ${kernelRun.stderr}";
  }

  final Uri aotElf = tmpDirUri.resolve("aot.elf");
  final File aotElfFile = new File.fromUri(aotElf);
  final Uri obfuscationMap = tmpDirUri.resolve("obfuscation.map");
  final File obfuscationMapFile = new File.fromUri(obfuscationMap);

  print("Running $genSnapshot");
  // Extracted from pkg/dart2native/lib/dart2native.dart.
  final ProcessResult snapshotRun = Process.runSync(genSnapshotFile.path, [
    "--snapshot-kind=app-aot-elf",
    "--elf=${aotElfFile.path}",
    "--dwarf-stack-traces",
    "--obfuscate",
    "--strip",
    "--save-obfuscation-map=${obfuscationMapFile.path}",
    kernelDillFile.path,
  ]);

  if (snapshotRun.exitCode != 0) {
    throw "Got exit code ${snapshotRun.exitCode}\n"
        "stdout: ${snapshotRun.stdout}\n"
        "stderr: ${snapshotRun.stderr}";
  }

  print("Reading $obfuscationMap");

  return readJsonMapping(obfuscationMapFile);
}

List<MappingPair> readJsonMapping(File file) {
  List<MappingPair> result = [];
  List<dynamic> json = jsonDecode(file.readAsStringSync());
  for (int i = 0; i < json.length; i += 2) {
    result.add(new MappingPair(json[i] as String, json[i + 1] as String));
  }
  return result;
}

class MappingPair {
  final String from;
  final String to;

  MappingPair(this.from, this.to);

  String toString() => "MappingPair[$from->$to]";
}

bool verify(
  List<MappingPair> mapping,
  Set<String> expectedIdentity,
  Set<String> expectedDifferent,
) {
  bool good = true;
  Set<String> missingKeys = new Set<String>.of(expectedIdentity)
    ..addAll(expectedDifferent);
  for (MappingPair entry in mapping) {
    missingKeys.remove(entry.from);
    if (expectedIdentity.contains(entry.from) && entry.from != entry.to) {
      print(
        "Expected ${entry.from} to map to itself, "
        "but mapped to ${entry.to}",
      );
      good = false;
    }
    if (expectedDifferent.contains(entry.from) && entry.from == entry.to) {
      print(
        "Expected ${entry.from} to map to something different, "
        "but it didn't.",
      );
      good = false;
    }
  }
  if (missingKeys.isNotEmpty) {
    print("Expected to have seen the following entries which wasn't found:");
    for (String missingKey in missingKeys) {
      print("- $missingKey");
    }
    good = false;
  }
  return good;
}
