// Copyright (c) 2025, 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';
import 'dart:ffi';

final repoRoot = File.fromUri(Platform.script).parent.parent.parent.path;
final runtimeRoot = '$repoRoot/runtime';
final buildtoolsRoot = '$repoRoot/buildtools';
final clangBinDir =
    '$buildtoolsRoot/$currentPlatformBuildtoolsSubdir/clang/bin';
final clangFormatBin = '$clangBinDir/clang-format';

final currentPlatformBuildtoolsSubdir = switch (Abi.current()) {
  Abi.macosX64 => 'mac-x64',
  Abi.macosArm64 => 'mac-arm64',
  Abi.linuxX64 => 'linux-x64',
  Abi.linuxArm64 => 'linux-arm64',
  Abi.windowsX64 => 'win-x64',
  Abi.windowsArm64 => 'win-arm64',
  _ => throw UnimplementedError(),
};

void main(List<String> args) {
  final checkUpToDate = args.contains('--check-up-to-date');

  final dartApiHFile = File('$runtimeRoot/include/dart_api.h');
  final dartNativeApiHFile = File('$runtimeRoot/include/dart_native_api.h');
  final dartApiWinCFile = File('$runtimeRoot/bin/dart_api_win.c');
  final dartApiWinCTmpFile = File('$runtimeRoot/bin/dart_api_win_tmp.c');
  final dartApiHContents = dartApiHFile.readAsStringSync();
  final dartNativeApiHContents = dartNativeApiHFile.readAsStringSync();

  final procedureRegexp = RegExp(
    r'(DART_\w+\s+)+(?<returnType>[\w\s\*]+)\s+(?<name>\w+)\((?<arguments>[^)]*)\);',
    multiLine: true,
  );

  final matches = [
    ...procedureRegexp.allMatches(dartApiHContents),
    ...procedureRegexp.allMatches(dartNativeApiHContents),
  ];

  final procedures = <Procedure>[];

  for (final match in matches) {
    final returnType = match.namedGroup('returnType')!;
    final name = match.namedGroup('name')!;
    final argumentsString = match.namedGroup('arguments') ?? '';
    final argumentList = argumentsString
        .split(',')
        .where((arg) => arg != 'void')
        .map((arg) {
          final parts = arg.trim().split(' ');
          return (
            type: parts.sublist(0, parts.length - 1).join(' '),
            name: parts[parts.length - 1],
          );
        })
        .toList();
    procedures.add((
      name: name,
      returnType: returnType,
      arguments: argumentList,
    ));
  }

  final buffer = StringBuffer();

  buffer.writeln('''
// Copyright (c) 2025, 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.

// DO NOT EDIT. This file is generated by runtime/tools/generate_dart_api_win_c.dart.

#include <windows.h>

#include <include/dart_api.h>
#include <include/dart_native_api.h>

''');

  // Generate typedefs for all procedures.
  for (final procedure in procedures) {
    buffer.write('typedef ');
    buffer.write(procedure.returnType);
    buffer.write(' (*');
    buffer.write(procedure.typedefName);
    buffer.write(')(');
    for (final (i, argument) in procedure.arguments.indexed) {
      buffer.write(argument.type);
      if (i < procedure.arguments.length - 1) {
        buffer.write(', ');
      }
    }
    buffer.writeln(');');
  }

  buffer.writeln();

  // Generate function pointers for all procedures.
  for (final procedure in procedures) {
    buffer.write('static ');
    buffer.write(procedure.typedefName);
    buffer.write(' ');
    buffer.write(procedure.functionPointerName);
    buffer.writeln(' = NULL;');
  }

  buffer.writeln();

  // Generate the DllMain function that initializes all function pointers.
  buffer.writeln('''
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
  if (fdwReason == DLL_PROCESS_ATTACH) {
    HMODULE process = GetModuleHandle(NULL);
''');

  for (final procedure in procedures) {
    buffer.write('    ');
    buffer.write(procedure.functionPointerName);
    buffer.write(' = (');
    buffer.write(procedure.typedefName);
    buffer.write(') GetProcAddress(process, "');
    buffer.write(procedure.name);
    buffer.writeln('");');
  }

  buffer.writeln('''
  }

  return TRUE;
}''');

  buffer.writeln();

  // Generate redirecting implementations for all procedures.
  for (final procedure in procedures) {
    final (:name, :returnType, :arguments) = procedure;
    buffer.write(returnType);
    buffer.write(' ');
    buffer.write(name);
    buffer.write('(');
    for (final (i, (:name, :type)) in arguments.indexed) {
      buffer.write(type);
      buffer.write(' ');
      buffer.write(name);
      if (i < arguments.length - 1) {
        buffer.write(', ');
      }
    }
    buffer.writeln(') {');
    buffer.write('  ');
    if (procedure.returnType != 'void') {
      buffer.write('return ');
    }
    buffer.write(procedure.functionPointerName);
    buffer.write('(');
    for (final (i, argument) in arguments.indexed) {
      buffer.write(argument.name);
      if (i < arguments.length - 1) {
        buffer.write(', ');
      }
    }
    buffer.writeln(');');
    buffer.writeln('}');
    buffer.writeln();
  }

  buffer.writeln();

  dartApiWinCTmpFile.writeAsStringSync(buffer.toString());

  try {
    // Run clang-format on the generated file.
    final clangFormatResult = Process.runSync(
      clangFormatBin,
      ['-i', dartApiWinCTmpFile.path],
      // Allows us to specify the path to the clang-format binary without the
      // .exe extension on Windows.
      runInShell: Platform.isWindows,
    );
    if (clangFormatResult.exitCode != 0) {
      print(clangFormatResult.stdout);
      print(clangFormatResult.stderr);
      exitCode = 1;
    } else {
      final changed =
          !dartApiWinCFile.existsSync() ||
          dartApiWinCTmpFile.readAsStringSync() !=
              dartApiWinCFile.readAsStringSync();
      if (changed) {
        if (checkUpToDate) {
          exitCode = 1;
        } else {
          dartApiWinCTmpFile.copySync(dartApiWinCFile.path);
        }
      }
    }
  } finally {
    dartApiWinCTmpFile.deleteSync();
  }
}

typedef Procedure = ({
  String name,
  String returnType,
  List<({String name, String type})> arguments,
});

extension on Procedure {
  String get typedefName => '${name}Type';
  String get functionPointerName => '${name}Fn';
}
