// 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_product.dill',
  );
  final File platformDillFile = new File.fromUri(platformDill);
  if (!platformDillFile.existsSync()) {
    throw "Didn't find vm_platform_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;
}
