// Copyright (c) 2019, 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:io' show File, Platform;

import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:front_end/src/api_prototype/compiler_options.dart'
    show DiagnosticMessage;

import 'package:kernel/kernel.dart'
    show Class, Component, ConstantExpression, Field, IntConstant, Library;

import 'package:kernel/target/targets.dart' show NoneTarget, TargetFlags;

import 'binary_md_dill_reader.dart' show BinaryMdDillReader;

import 'incremental_suite.dart' show getOptions, normalCompileToComponent;

import 'utils/io_utils.dart' show computeRepoDir;

const String maxSupported =
    "static const uint32_t kMaxSupportedKernelFormatVersion = ";

// Match stuff like "V(Nothing, 0)"
final RegExp tagParser = new RegExp(r"V\((\w*),\s*(\d+)\)");

// Match stuff like "kNullConstant = 0,"
final RegExp constantTagParser = new RegExp(r"k(\w*)\s*=\s*(\d+)");

void main() async {
  File binaryMd = new File("$repoDir/pkg/kernel/binary.md");
  String binaryMdContent = binaryMd.readAsStringSync();

  BinaryMdDillReader binaryMdReader =
      new BinaryMdDillReader(binaryMdContent, []);
  binaryMdReader.setup();

  File vmTagFile = new File("$repoDir/runtime/vm/kernel_binary.h");
  String vmTagContent = vmTagFile.readAsStringSync();
  List<String> vmTagLines = vmTagContent.split("\n");
  int? vmVersion;
  Map<int, String> vmTagToName = {};
  Map<int, String> vmConstantTagToName = {};
  for (int i = 0; i < vmTagLines.length; i++) {
    String line = vmTagLines[i];
    if (line.startsWith(maxSupported)) {
      vmVersion = int.parse(line
          .substring(line.indexOf(maxSupported) + maxSupported.length)
          .substring(0, 2) // Assume version < 100 for now.
          .trim());
    } else if (line.startsWith("#define KERNEL_TAG_LIST(V)")) {
      while (true) {
        RegExpMatch? match = tagParser.firstMatch(line);
        if (match != null) {
          int value = int.parse(match.group(2)!);
          int end = value + 1;
          if (uses8Tags(match.group(1)!)) {
            end = value + 8;
          }
          for (int j = value; j < end; j++) {
            vmTagToName[j] = match.group(1)!;
          }
        }
        if (!vmTagLines[i].trim().endsWith(r"\")) {
          break;
        }
        i++;
        line = vmTagLines[i];
      }
    } else if (line.startsWith("enum ConstantTag {")) {
      while (true) {
        RegExpMatch? match = constantTagParser.firstMatch(line);
        if (match != null) {
          vmConstantTagToName[int.parse(match.group(2)!)] = match.group(1)!;
        }
        if (vmTagLines[i].trim().startsWith("}")) {
          break;
        }
        i++;
        line = vmTagLines[i];
      }
    }
  }

  final Uri kernelTagUri = Uri.base.resolve("pkg/kernel/lib/binary/tag.dart");
  Component c = await normalCompileToComponent(kernelTagUri,
      options: getOptions()
        ..target = new NoneTarget(new TargetFlags())
        ..onDiagnostic = (DiagnosticMessage message) {
          if (message.severity == Severity.error) {
            print(message.plainTextFormatted.join('\n'));
          }
        });

  Library tagLibrary =
      c.libraries.firstWhere((l) => l.fileUri.pathSegments.last == "tag.dart");
  Class tagClass = tagLibrary.classes.firstWhere((c) => c.name == "Tag");
  Class constantTagClass =
      tagLibrary.classes.firstWhere((c) => c.name == "ConstantTag");

  int? tagVersion;
  for (TagCompare compareMe in [
    new TagCompare(binaryMdReader.tagToName, binaryMdReader.version,
        vmTagToName, vmVersion, tagClass),
    new TagCompare(binaryMdReader.constantTagToName, binaryMdReader.version,
        vmConstantTagToName, vmVersion, constantTagClass)
  ]) {
    Map<int, String> tagToName = {};
    for (Field f in compareMe.tagClass.fields) {
      // Class doesn't only contain tag stuff.
      if (f.name.text.endsWith("Mask")) continue;
      if (f.name.text.endsWith("HighBit")) continue;
      if (f.name.text.endsWith("Bias")) continue;
      if (f.name.text == "ComponentFile") continue;
      ConstantExpression value = f.initializer as ConstantExpression;
      IntConstant intConstant = value.constant as IntConstant;
      int intValue = intConstant.value;
      if (f.name.text == "BinaryFormatVersion") {
        tagVersion = intValue;
        continue;
      }

      int end = intValue + 1;
      // There are a few special cases that takes up a total of 8 tags.
      if (uses8Tags(f.name.text)) {
        end = intValue + 8;
      }
      for (; intValue < end; intValue++) {
        if (tagToName[intValue] != null) {
          throw "Double entry for ${intValue}: "
              "${f.name.text} and ${tagToName[intValue]}";
        }
        tagToName[intValue] = f.name.text;
      }
    }

    Map<int, String> tagToNameMd = {};
    for (MapEntry<int, String> entry in compareMe.mdTagToName.entries) {
      if (entry.value.contains("<")) {
        tagToNameMd[entry.key] =
            entry.value.substring(0, entry.value.indexOf("<")).trim();
      } else {
        tagToNameMd[entry.key] = entry.value;
      }
    }

    // Kernels tag.dart vs binary.mds tags.
    for (int key in tagToNameMd.keys) {
      String nameMd = tagToNameMd[key]!;
      String name = tagToName[key]!;
      if (nameMd == name) continue;
      throw "$key: $nameMd vs $name";
    }
    for (int key in tagToName.keys) {
      String nameMd = tagToNameMd[key]!;
      String name = tagToName[key]!;
      if (nameMd == name) continue;
      throw "$key: $nameMd vs $name";
    }
    if (tagVersion != compareMe.mdVersion) {
      throw "Version in tag.dart: $tagVersion; "
          "version in binary.md: ${compareMe.mdVersion}";
    }

    // Kernels tag.dart vs the VMs tags.
    // Here we only compare one way because the VM can have more (old) tags.
    for (int key in tagToName.keys) {
      String nameVm = compareMe.vmTagToName[key]!;
      String name = tagToName[key]!;
      if (nameVm == name) continue;
      throw "$key: $nameVm vs $name";
    }
    if (tagVersion != compareMe.vmVersion) {
      throw "Version in tag.dart: $tagVersion; "
          "version in VM: ${compareMe.vmVersion}";
    }
  }

  print("OK");
}

bool uses8Tags(String name) {
  return name == "SpecializedVariableGet" ||
      name == "SpecializedVariableSet" ||
      name == "SpecializedIntLiteral";
}

final String repoDir = computeRepoDir();

String get dartVm => Platform.executable;

class TagCompare {
  final Map<int, String> mdTagToName;
  final int? mdVersion;
  final Map<int, String> vmTagToName;
  final int? vmVersion;
  final Class tagClass;

  TagCompare(this.mdTagToName, this.mdVersion, this.vmTagToName, this.vmVersion,
      this.tagClass);
}
