// Copyright (c) 2023, 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';

//
// Configuration.
//

const nativeToDartType = {
  'Int8': 'int',
  'Int16': 'int',
  'Int32': 'int',
  'Int64': 'int',
  'Uint8': 'int',
  'Uint16': 'int',
  'Uint32': 'int',
  'Uint64': 'int',
  'Float': 'double',
  'Double': 'double',
  'Pointer<Uint8>': 'Pointer<Uint8>',
  'Handle': 'Object',
};

const generateFor = {
  'Int8': [1],
  'Int16': [1],
  'Int32': [1, 2, 4, 10, 20],
  'Int64': [1, 2, 4, 10, 20],
  'Uint8': [1],
  'Uint16': [1],
  'Uint32': [1],
  'Uint64': [1],
  'Float': [1, 2, 4, 10, 20],
  'Double': [1, 2, 4, 10, 20],
  'Pointer<Uint8>': [1, 2, 4, 10, 20],
  'Handle': [1, 2, 4, 10, 20],
};

const allNumbers = [1, 2, 4, 10, 20];

//
// Generator.
//

void main() {
  final List<String> nativeTypes = nativeToDartType.keys.toList();
  final List<String> dartTypes = nativeToDartType.values.toSet().toList();
  final List<String> nativeIntTypes = nativeTypes.where(isInt).toList();
  final List<String> nativeDoubleTypes = nativeTypes.where(isDouble).toList();
  final List<String> nativePointerTypes = nativeTypes.where(isPointer).toList();
  final List<String> nativeHandleTypes = nativeTypes.where(isHandle).toList();

  final StringBuffer buffer = StringBuffer();
  buffer.write(header);
  generateTypedefs(buffer, 'Function', dartTypes, allNumbers);
  generateTypedefs(buffer, 'NativeFunction', nativeTypes, allNumbers);
  generateBenchmarkInt(buffer, nativeIntTypes);
  generateBenchmarkDouble(buffer, nativeDoubleTypes);
  generateBenchmarkPointer(buffer, nativePointerTypes);
  generateBenchmarkHandle(buffer, nativeHandleTypes);

  final path = Platform.script.resolve('dart/benchmark_generated.dart').path;
  File(path).writeAsStringSync(buffer.toString());
  print(Process.runSync('dart', ['format', path]).stderr);
}

const header = '''
// Copyright (c) 2023, 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.
//
// This file has been automatically generated. Please do not edit it manually.
// To regenerate the file, run the following script:
//
// > dart benchmarks/FfiCall/generate_benchmarks.dart

// Using part of, so that the library uri is identical to the main file.
// That way the FfiNativeResolver works for the main uri.
part of 'FfiCall.dart';

''';

void generateTypedefs(
  StringBuffer buffer,
  String namePrefix,
  List<String> types,
  List<int> numbers,
) {
  for (String type in types) {
    for (int number in numbers) {
      final String name = '$namePrefix$number${toIdentifier(type)}';
      final String arguments = repeat(type, number, ', ');
      buffer.write('typedef $name = $type Function($arguments);');
    }
  }
}

void generateBenchmarkInt(StringBuffer buffer, List<String> types) {
  for (String type in types) {
    final String typeName = toIdentifier(type);
    final String dartType = toIdentifier(nativeToDartType[type]!);
    for (int number in generateFor[type]!) {
      final String name = '${typeName}x${'$number'.padLeft(2, '0')}';
      final String expected = IntVariation(type, number).expectedValue(number);
      final String functionType = 'Function$number$dartType';
      final String functionNativeType = 'NativeFunction$number$typeName';
      final String functionNameC = 'Function$number$typeName';
      final String argument = IntVariation(type, number).argument;
      final String arguments = repeat(argument, number, ', ');
      final String functionNameDart = 'function$number$typeName';
      final String dartArguments = List.generate(
        number,
        (i) => '$dartType a$i',
      ).join(', ');

      buffer.write('''
class $name extends FfiBenchmarkBase {
  final $functionType f;

  $name({bool isLeaf = false})
        : f = isLeaf
            ? ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: true)
            : ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: false),
        super('FfiCall.$name', isLeaf: isLeaf);

  @override
  void run() {
    int x = 0;
    for (int i = 0; i < N; i++) {
      x += f($arguments);
    }
    expectEquals(x, $expected);
  }
}
''');

      for (bool isLeaf in [false, true]) {
        final leaf = isLeaf ? 'Leaf' : '';
        buffer.write('''
@Native<$functionNativeType>(symbol: '$functionNameC', isLeaf: $isLeaf)
external $dartType $functionNameDart$leaf($dartArguments);

class ${name}Native$leaf extends FfiBenchmarkBase {
  ${name}Native$leaf() : super('FfiCall.${name}Native', isLeaf: $isLeaf);

  @override
  void run() {
    int x = 0;
    for (int i = 0; i < N; i++) {
      x += $functionNameDart$leaf($arguments);
    }
    expectEquals(x, $expected);
  }
}
''');
      }
    }
  }
}

void generateBenchmarkDouble(StringBuffer buffer, List<String> types) {
  for (String type in types) {
    final String typeName = toIdentifier(type);
    final String dartType = toIdentifier(nativeToDartType[type]!);
    for (int number in generateFor[type]!) {
      final String name = '${typeName}x${'$number'.padLeft(2, '0')}';
      final String expected =
          number == 1
              ? 'N + N * 42.0' // Do work with single arg.
              : 'N * $number * ($number + 1) / 2 '; // The rest sums arguments.
      final String functionType = 'Function$number$dartType';
      final String functionNativeType = 'NativeFunction$number$typeName';
      final String functionNameC = 'Function$number$typeName';
      final List<double> argVals = List.generate(number, (i) => 1.0 * (i + 1));
      final String arguments = argVals.join(', ');
      final String functionNameDart = 'function$number$typeName';
      final String dartArguments = List.generate(
        number,
        (i) => '$dartType a$i',
      ).join(', ');
      buffer.write('''
class $name extends FfiBenchmarkBase {
  final $functionType f;

  $name({bool isLeaf = false})
        : f = isLeaf
            ? ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: true)
            : ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: false),
        super('FfiCall.$name', isLeaf: isLeaf);

  @override
  void run() {
    double x = 0;
    for (int i = 0; i < N; i++) {
      x += f($arguments);
    }
    final double expected = $expected;
    expectApprox(x, expected);
  }
}
''');

      for (bool isLeaf in [false, true]) {
        final leaf = isLeaf ? 'Leaf' : '';
        buffer.write('''
@Native<$functionNativeType>(symbol: '$functionNameC', isLeaf: $isLeaf)
external $dartType $functionNameDart$leaf($dartArguments);

class ${name}Native$leaf extends FfiBenchmarkBase {
  ${name}Native$leaf() : super('FfiCall.${name}Native', isLeaf: $isLeaf);

  @override
  void run() {
    double x = 0;
    for (int i = 0; i < N; i++) {
      x += $functionNameDart$leaf($arguments);
    }
    final double expected = $expected;
    expectApprox(x, expected);
  }
}
''');
      }
    }
  }
}

void generateBenchmarkPointer(StringBuffer buffer, List<String> types) {
  for (String type in types) {
    if (type != 'Pointer<Uint8>') throw Exception('Not implemented for $type.');
    final String typeName = toIdentifier(type);
    final String dartType = nativeToDartType[type]!;
    final String dartTypeName = toIdentifier(dartType);
    for (int number in generateFor[type]!) {
      final String name = '${typeName}x${'$number'.padLeft(2, '0')}';
      final List<String> pointerNames = List.generate(
        number,
        (i) => 'p${i + 1}',
      );
      final String pointers = pointerNames
          .map((n) => '$type $n = nullptr;')
          .join('\n');
      final String setup =
          List.generate(
            number - 1,
            (i) => 'p${i + 2} = p1.elementAt(${i + 1});',
          ).join();
      final String functionType = 'Function$number$dartTypeName';
      final String functionNativeType = 'NativeFunction$number$typeName';
      final String functionNameC = 'Function$number$typeName';
      final String arguments = pointerNames.skip(1).join(', ');
      final String functionNameDart = 'function$number$typeName';
      final String dartArguments = List.generate(
        number,
        (i) => '$dartType a$i',
      ).join(', ');
      buffer.write('''
class $name extends FfiBenchmarkBase {
  final $functionType f;

  $name({bool isLeaf = false})
        : f = isLeaf
            ? ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: true)
            : ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: false),
        super('FfiCall.$name', isLeaf: isLeaf);

  $pointers

  @override
  void setup() {
    p1 = calloc(N + 1);
    $setup
  }

  @override
  void teardown() {
    calloc.free(p1);
  }

  @override
  void run() {
  $type x = p1;
    for (int i = 0; i < N; i++) {
      x = f(x, $arguments);
    }
    expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
  }
}
''');

      for (bool isLeaf in [false, true]) {
        final leaf = isLeaf ? 'Leaf' : '';
        buffer.write('''
@Native<$functionNativeType>(symbol: '$functionNameC', isLeaf: $isLeaf)
external $dartType $functionNameDart$leaf($dartArguments);

class ${name}Native$leaf extends FfiBenchmarkBase {
  ${name}Native$leaf() : super('FfiCall.${name}Native', isLeaf: $isLeaf);

  $pointers

  @override
  void setup() {
    p1 = calloc(N + 1);
    $setup
  }

  @override
  void teardown() {
    calloc.free(p1);
  }

  @override
  void run() {
  $type x = p1;
    for (int i = 0; i < N; i++) {
      x = $functionNameDart$leaf(x, $arguments);
    }
    expectEquals(x.address, p1.address + N * sizeOf<Uint8>());
  }
}
''');
      }
    }
  }
}

void generateBenchmarkHandle(StringBuffer buffer, List<String> types) {
  for (String type in types) {
    if (type != 'Handle') throw Exception('Not implemented for $type.');
    final String typeName = toIdentifier(type);
    final String dartType = toIdentifier(nativeToDartType[type]!);
    for (int number in generateFor[type]!) {
      final String name = '${typeName}x${'$number'.padLeft(2, '0')}';
      final String setup = List.generate(
        number + 1,
        (i) => 'final m$i = MyClass($i);',
      ).skip(2).join('\n');
      final String functionType = 'Function$number$dartType';
      final String functionNativeType = 'NativeFunction$number$typeName';
      final String functionNameC = 'Function$number$typeName';
      final String arguments = List.generate(
        number - 1,
        (i) => 'm${i + 2}',
      ).join(', ');
      final String functionNameDart = 'function$number$typeName';
      final String dartArguments = List.generate(
        number,
        (i) => '$dartType a$i',
      ).join(', ');
      buffer.write('''
class $name extends FfiBenchmarkBase {
  final $functionType f;

  $name()
        : f = ffiTestFunctions.lookupFunction<$functionNativeType,$functionType>('$functionNameC', isLeaf: false),
        super('FfiCall.$name', isLeaf: false);

  @override
  void run() {
    final m1 = MyClass(123);
    $setup
    Object x = m1;
    for (int i = 0; i < N; i++) {
      x = f(x, $arguments);
    }
    expectIdentical(x, m1);
  }
}

@Native<$functionNativeType>(symbol: '$functionNameC', isLeaf: false)
external $dartType $functionNameDart($dartArguments);

class ${name}Native extends FfiBenchmarkBase {
  ${name}Native() : super('FfiCall.${name}Native', isLeaf: false);

  @override
  void run() {
    final m1 = MyClass(123);
    $setup
    Object x = m1;
    for (int i = 0; i < N; i++) {
      x = $functionNameDart(x, $arguments);
    }
    expectIdentical(x, m1);
  }
}
''');
    }
  }
}

//
// Benchmark variations.
//

class IntVariation {
  /// The argument passed to the C function, the same value is passed if the C
  /// function has multiple parameters.
  final String argument;

  /// The expected value of summation of all return values.
  final String Function(int number) expectedValue;

  /// These benchmarks sum all arguments over all iterations.
  IntVariation.LargeIntManyArguments()
    : argument = 'i',
      expectedValue = ((int number) => 'N * (N - 1) * $number / 2');

  /// Benchmarks with only one argument return 42 added to the argument.
  IntVariation.LargeIntOneArgument()
    : argument = 'i',
      expectedValue = ((int number) => 'N * (N - 1) / 2 + N * 42');

  /// The benchmarks with small ints (`int8_t`, `uint8_t`, etc.) we pass an
  /// arbitrary fixed argument between 0 and 127 to prevent truncation.
  ///
  /// The C function returns 42 added to the argument.
  IntVariation.SmallInt()
    : argument = '17',
      expectedValue = ((int number) => 'N * 17 + N * 42');

  factory IntVariation(String type, int number) {
    if (isSmallInt(type)) {
      return IntVariation.SmallInt();
    }
    if (number == 1) {
      return IntVariation.LargeIntOneArgument();
    }
    return IntVariation.LargeIntManyArguments();
  }
}

//
// Helper functions.
//

String toIdentifier(String type) =>
    type.replaceAll('<', '').replaceAll('>', '');

String repeat(String input, int n, String separator) {
  if (n == 0) {
    return '';
  }

  return (input + separator) * (n - 1) + input;
}

bool isInt(String type) => type.startsWith('Int') || type.startsWith('Uint');

/// True for `int8_t`, `uint8_t`, `int16_t`, and `uint16_t`.
bool isSmallInt(String type) =>
    isInt(type) && (type.contains('8') || type.contains('16'));

bool isDouble(String type) =>
    type.startsWith('Float') || type.startsWith('Double');

bool isPointer(String type) => type.startsWith('Pointer');

bool isHandle(String type) => type == 'Handle';
