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

import 'package:meta/meta.dart';

import '../config/config.dart';
import '../config/experiments.dart';
import '../elements/elements.dart';
import '../logging/logging.dart';
import '../util/string_util.dart';
import 'c_generator.dart';
import 'resolver.dart';
import 'visitor.dart';

// Import prefixes.
const _jni = 'jni';
const _ffi = 'ffi';

// package:jni types.
const _jType = '$_jni.JObjType';
const _jPointer = '$_jni.JObjectPtr';
const _jReference = '$_jni.JReference';
const _jGlobalReference = '$_jni.JGlobalReference';
const _jArray = '$_jni.JArray';
const _jObject = '$_jni.JObject';
const _jResult = '$_jni.JniResult';
const _jThrowable = '$_jni.JThrowablePtr';

// package:ffi types.
const _voidPointer = '$_ffi.Pointer<$_ffi.Void>';

// Prefixes and suffixes.
const _typeParamPrefix = '\$';

// Misc.
const _protectedExtension = 'ProtectedJniExtensions';
const _classRef = '_class';
const _lookup = 'jniLookup';

/// Used for C bindings.
const _selfPointer = 'reference.pointer';

/// Used for Dart-only bindings.
const _self = 'this';

// Docs.
const _releaseInstruction =
    '  /// The returned object must be released after use, '
    'by calling the [release] method.';

extension on Iterable<String> {
  /// Similar to [join] but adds the [separator] to the end as well.
  String delimited([String separator = '']) {
    return map((e) => '$e$separator').join();
  }
}

/// Encloses [inside] in the middle of [open] and [close]
/// if [inside] is not empty.
String _encloseIfNotEmpty(String open, String inside, String close) {
  if (inside == '') return '';
  return '$open$inside$close';
}

String _newLine({int depth = 0}) {
  return '\n${'  ' * depth}';
}

/// Merges two maps. For the same keys, their value lists will be concatenated.
///
/// ** After calling this, the original maps might get modified! **
Map<K, List<V>> _mergeMapValues<K, V>(Map<K, List<V>> a, Map<K, List<V>> b) {
  final merged = <K, List<V>>{};
  for (final key in {...a.keys, ...b.keys}) {
    if (!a.containsKey(key)) {
      merged[key] = b[key]!;
      continue;
    }
    if (!b.containsKey(key)) {
      merged[key] = a[key]!;
      continue;
    }

    // Merging the smaller one to the bigger one
    if (a[key]!.length > b[key]!.length) {
      merged[key] = a[key]!;
      merged[key]!.addAll(b[key]!);
    } else {
      merged[key] = b[key]!;
      merged[key]!.addAll(a[key]!);
    }
  }
  return merged;
}

/// **Naming Convention**
///
/// Let's take the following code as an example:
///
/// ```dart
/// Method definition
/// void f<T extends num, U>(JType<T> $T, JType<U> $U, T t, U u) {
///   // ...
/// }
/// f<int, String>($T, $U, t, u); // Calling the Method
/// ```
///
/// Here `f` will be replaced according to the place of usage.
///
/// * `fArgsDef` refers to `T t, U u` – the arguments in the method
///   definition.
/// * `fArgsCall` refer to `t, u` – the arguments passed to call the method.
/// * `fTypeParamsDef` refers to `<T extends num, U>` – the type parameters
///   of the method at the point of definition.
/// * `fTypeParamsCall` refers to `<int, String>` – the type parameters when
///   calling, or whenever we don't want to have the `extends` keyword.
/// * `fTypeClassesDef` refers to `JType<T> $T, JType<U> $U`.
/// * `fTypeClassesCall` refers to `$T, $U` when calling the method.
class DartGenerator extends Visitor<Classes, Future<void>> {
  final Config config;

  DartGenerator(this.config);

  static const cInitImport = 'import "dart:ffi" as ffi;\n'
      'import "package:jni/internal_helpers_for_jnigen.dart";\n';

  /// Initialization code for C based bindings.
  ///
  /// Should be called once in a package. In package-structured bindings
  /// this is placed in _init.dart in package root.
  String get cInitCode => '''
// Auto-generated initialization code.

final $_ffi.Pointer<T> Function<T extends $_ffi.NativeType>(String sym) $_lookup =
    $_protectedExtension.initGeneratedLibrary("${config.outputConfig.cConfig!.libraryName}");


''';

  static const autoGeneratedNotice = '// Autogenerated by jnigen. '
      'DO NOT EDIT!\n\n';
  static const defaultImports = '''
import "dart:isolate" show ReceivePort;
import "dart:ffi" as ffi;
import "package:jni/internal_helpers_for_jnigen.dart";
import "package:jni/jni.dart" as jni;

''';

  // Sort alphabetically.
  static const defaultLintSuppressions = '''
// ignore_for_file: annotate_overrides
// ignore_for_file: camel_case_extensions
// ignore_for_file: camel_case_types
// ignore_for_file: constant_identifier_names
// ignore_for_file: doc_directive_unknown
// ignore_for_file: file_names
// ignore_for_file: lines_longer_than_80_chars
// ignore_for_file: no_leading_underscores_for_local_identifiers
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: overridden_fields
// ignore_for_file: unnecessary_cast
// ignore_for_file: unused_element
// ignore_for_file: unused_field
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: unused_shown_name
// ignore_for_file: use_super_parameters

''';
  static const preImportBoilerplate =
      autoGeneratedNotice + defaultLintSuppressions + defaultImports;

  /// Run dart format command on [path].
  Future<void> _runDartFormat(String path) async {
    log.info('Running dart format...');
    final formatRes = await Process.run('dart', ['format', path]);
    // if negative exit code, likely due to an interrupt.
    if (formatRes.exitCode > 0) {
      log.fatal('Dart format completed with exit code ${formatRes.exitCode} '
          'This usually means there\'s a syntax error in bindings.\n'
          'Please look at the generated files and report a bug: \n'
          'https://github.com/dart-lang/native/issues/new?labels=package%3Ajnigen\n');
    }
  }

  @override
  Future<void> visit(Classes node) async {
    final cBased = config.outputConfig.bindingsType == BindingsType.cBased;
    final root = config.outputConfig.dartConfig.path;
    final preamble = config.preamble ?? '';
    if (config.outputConfig.dartConfig.structure ==
        OutputStructure.singleFile) {
      final file = File.fromUri(root);
      await file.create(recursive: true);
      log.info("Generating ${cBased ? "C + Dart" : "Pure Dart"} Bindings");
      final s = file.openWrite();
      s.writeln(preamble);
      s.writeln(autoGeneratedNotice);
      s.writeln(defaultLintSuppressions);
      s.writeln(defaultImports);
      if (cBased) {
        s.writeln(cInitCode);
      }
      final resolver = Resolver(
        importedClasses: config.importedClasses,
        currentClass: null, // Single file mode.
        inputClassNames: node.decls.keys.toSet(),
      );
      final classGenerator = _ClassGenerator(config, s, resolver);
      for (final classDecl in node.decls.values) {
        classDecl.accept(classGenerator);
      }
      await s.close();
      await _runDartFormat(file.path);
      return;
    }
    final files = <String, List<ClassDecl>>{};
    final packages = <String, Set<String>>{};
    for (final classDecl in node.decls.values) {
      final fileClass = Resolver.getFileClassName(classDecl.binaryName);

      files.putIfAbsent(fileClass, () => <ClassDecl>[]);
      files[fileClass]!.add(classDecl);

      packages.putIfAbsent(classDecl.packageName, () => {});
      packages[classDecl.packageName]!.add(fileClass.split('.').last);
    }

    log.info("Using dart root = $root");
    const initFileName = '_init.dart';
    if (cBased) {
      final initFileUri = root.resolve(initFileName);
      final initFile = File.fromUri(initFileUri);
      await initFile.create(recursive: true);
      final initStream = initFile.openWrite();
      initStream.writeln(preamble);
      initStream.writeln(cInitImport);
      initStream.writeln(cInitCode);
      await initStream.close();
    }
    for (var fileClassName in files.keys) {
      final relativeFileName = '${fileClassName.replaceAll('.', '/')}.dart';
      final dartFileUri = root.resolve(relativeFileName);
      final dartFile = await File.fromUri(dartFileUri).create(recursive: true);
      log.fine('$fileClassName -> ${dartFile.path}');

      final classesInFile = files[fileClassName]!;
      final dartFileStream = dartFile.openWrite();
      dartFileStream.writeln(preamble);
      dartFileStream.writeln(autoGeneratedNotice);
      dartFileStream.writeln(defaultLintSuppressions);
      dartFileStream.writeln(defaultImports);
      final s = StringBuffer();
      if (cBased) {
        final initFilePath = ('../' *
                relativeFileName.codeUnits
                    .where((cu) => cu == '/'.codeUnitAt(0))
                    .length) +
            initFileName;
        s.write('import "$initFilePath";');
      }
      final resolver = Resolver(
        importedClasses: config.importedClasses,
        currentClass: fileClassName,
        inputClassNames: node.decls.keys.toSet(),
      );
      final classGenerator = _ClassGenerator(config, s, resolver);
      for (final classDecl in classesInFile) {
        classDecl.accept(classGenerator);
      }
      dartFileStream.writeAll(resolver.getImportStrings(), '\n');
      dartFileStream.writeln(s.toString());
      await dartFileStream.close();
    }

    // write _package.dart export files
    for (var package in packages.keys) {
      final dirUri = root.resolve('${package.replaceAll('.', '/')}/');
      final exportFileUri = dirUri.resolve("_package.dart");
      final exportFile = File.fromUri(exportFileUri);
      exportFile.createSync(recursive: true);
      final exports =
          packages[package]!.map((cls) => 'export "$cls.dart";').join('\n');
      exportFile.writeAsStringSync(exports);
    }
    await _runDartFormat(root.toFilePath());
    log.info('Completed.');
  }
}

/// Generates the Dart class definition, type class, and the array extension.
class _ClassGenerator extends Visitor<ClassDecl, void> {
  final Config config;
  final StringSink s;
  final Resolver resolver;

  _ClassGenerator(
    this.config,
    this.s,
    this.resolver,
  );

  static const staticTypeGetter = 'type';
  static const instanceTypeGetter = '\$$staticTypeGetter';

  @override
  void visit(ClassDecl node) {
    final isDartOnly =
        config.outputConfig.bindingsType == BindingsType.dartOnly;

    // Docs.
    s.write('/// from: ${node.binaryName}\n');
    node.javadoc?.accept(_DocGenerator(s, depth: 0));

    // Class definition.
    final name = node.finalName;
    final superName = node.superclass!.accept(_TypeGenerator(resolver));
    final implClassName = '\$${name}Impl';
    final typeParamsDef = _encloseIfNotEmpty(
      '<',
      node.allTypeParams
          .accept(const _TypeParamGenerator(withExtends: true))
          .join(', '),
      '>',
    );
    final typeParams = node.allTypeParams
        .accept(const _TypeParamGenerator(withExtends: false));
    final typeParamsCall = _encloseIfNotEmpty(
      '<',
      typeParams.map((typeParam) => '$_typeParamPrefix$typeParam').join(', '),
      '>',
    );
    final staticTypeGetterCallArgs = _encloseIfNotEmpty(
      '(',
      typeParams.join(', '),
      ')',
    );
    final typeClassesDef = typeParams
        .map((typeParam) =>
            'final $_jType<$_typeParamPrefix$typeParam> $typeParam;')
        .join(_newLine(depth: 1));
    final ctorTypeClassesDef = typeParams
        .map((typeParam) => 'this.$typeParam,')
        .join(_newLine(depth: 2));
    final superClass = (node.classDecl.superclass!.type as DeclaredType);
    final superTypeClassesCall = superClass.classDecl.isObject
        ? ''
        : superClass.params
            .accept(_TypeClassGenerator(resolver))
            .map((typeClass) => '${typeClass.name},')
            .join(_newLine(depth: 2));
    s.write('''
class $name$typeParamsDef extends $superName {
  @override
  late final $_jType<$name$typeParamsCall> $instanceTypeGetter = $staticTypeGetter$staticTypeGetterCallArgs;

  $typeClassesDef

  $name.fromReference(
    $ctorTypeClassesDef
    $_jReference reference,
  ): super.fromReference(
    $superTypeClassesCall
    reference
  );

''');

    if (isDartOnly) {
      final internalName = node.internalName;
      s.write('''
  static final $_classRef = $_jni.JClass.forName(r"$internalName");

''');
    }

    // Static TypeClass getter.
    s.writeln(
        '  /// The type which includes information such as the signature of this class.');
    final typeClassName = node.typeClassName;
    if (typeParams.isEmpty) {
      s.writeln('static const $staticTypeGetter = $typeClassName();');
    } else {
      final staticTypeGetterTypeClassesDef = typeParams
          .map(
              (typeParam) => '$_jType<$_typeParamPrefix$typeParam> $typeParam,')
          .join(_newLine(depth: 2));
      final typeClassesCall =
          typeParams.map((typeParam) => '$typeParam,').join(_newLine(depth: 3));
      s.write('''
  static $typeClassName$typeParamsCall $staticTypeGetter$typeParamsDef(
    $staticTypeGetterTypeClassesDef
  ) {
    return $typeClassName(
      $typeClassesCall
    );
  }

''');
    }

    // Fields and Methods
    final fieldGenerator = _FieldGenerator(config, resolver, s);
    for (final field in node.fields) {
      field.accept(fieldGenerator);
    }
    final methodGenerator = _MethodGenerator(config, resolver, s);
    for (final method in node.methods) {
      method.accept(methodGenerator);
    }

    // Experimental: Interface implementation.
    if (node.declKind == DeclKind.interfaceKind &&
        (config.experiments?.contains(Experiment.interfaceImplementation) ??
            false)) {
      s.write('''
  /// Maps a specific port to the implemented interface.
  static final Map<int, $implClassName> _\$impls = {};
''');
      s.write(r'''
  ReceivePort? _$p;

  static jni.JObjectPtr _$invoke(
    int port,
    jni.JObjectPtr descriptor,
    jni.JObjectPtr args,
  ) {
    return _$invokeMethod(
      port,
      $MethodInvocation.fromAddresses(
        0,
        descriptor.address,
        args.address,
      ),
    );
  }

  static final ffi.Pointer<
          ffi.NativeFunction<
              jni.JObjectPtr Function(
                  ffi.Uint64, jni.JObjectPtr, jni.JObjectPtr)>>
      _$invokePointer = ffi.Pointer.fromFunction(_$invoke);

  static ffi.Pointer<ffi.Void> _$invokeMethod(
    int $p,
    $MethodInvocation $i,
  ) {
    try {
      final $d = $i.methodDescriptor.toDartString(releaseOriginal: true);
      final $a = $i.args;
    ''');
      final proxyMethodIf = _InterfaceMethodIf(resolver, s);
      for (final method in node.methods) {
        method.accept(proxyMethodIf);
      }
      s.write('''
    } catch (e) {
      return $_protectedExtension.newDartException(e.toString());
    }
    return jni.nullptr;
  }

  factory $name.implement(
    $implClassName$typeParamsCall \$impl,
  ) {
''');
      final typeClassesCall = typeParams
          .map((typeParam) => '\$impl.$typeParam,')
          .join(_newLine(depth: 3));
      s.write('''
    final \$p = ReceivePort();
    final \$x = $name.fromReference(
      $typeClassesCall
      $_protectedExtension.newPortProxy(
        r"${node.binaryName}",
        \$p,
        _\$invokePointer,
      ),
    ).._\$p = \$p;
    final \$a = \$p.sendPort.nativePort; 
    _\$impls[\$a] = \$impl;
    \$p.listen((\$m) {
      if (\$m == null) {
        _\$impls.remove(\$p.sendPort.nativePort);
        \$p.close();
        return;
      }
      final \$i = \$MethodInvocation.fromMessage(\$m as List<dynamic>);
      final \$r = _\$invokeMethod(\$p.sendPort.nativePort, \$i);
      $_protectedExtension.returnResult(\$i.result, \$r);
    });
    return \$x;
  }
  ''');
    }

    // Writing any custom code provided for this class.
    if (config.customClassBody?.containsKey(node.binaryName) ?? false) {
      s.writeln(config.customClassBody![node.binaryName]);
    }

    // End of Class definition.
    s.writeln('}');

    // Experimental: Interface implementation
    // Abstract and concrete Impl class definition.
    // Used for interface implementation.
    if (node.declKind == DeclKind.interfaceKind &&
        (config.experiments?.contains(Experiment.interfaceImplementation) ??
            false)) {
      // Abstract Impl class.
      final typeClassGetters = typeParams
          .map((typeParam) =>
              '$_jType<$_typeParamPrefix$typeParam> get $typeParam;')
          .join(_newLine(depth: 1));
      final abstractFactoryArgs = _encloseIfNotEmpty(
        '{',
        [
          ...typeParams
              .map((typeParam) => 'required $_jType<\$$typeParam> $typeParam,'),
          ...node.methods.accept(_ConcreteImplClosureCtorArg(resolver)),
        ].join(_newLine(depth: 2)),
        '}',
      );
      s.write('''
abstract interface class $implClassName$typeParamsDef {
  factory $implClassName(
    $abstractFactoryArgs
  ) = _$implClassName;

  $typeClassGetters

''');
      final abstractImplMethod = _AbstractImplMethod(resolver, s);
      for (final method in node.methods) {
        method.accept(abstractImplMethod);
      }
      s.writeln('}');

      // Concrete Impl class.
      // This is for passing closures instead of implementing the class.
      final concreteCtorArgs = _encloseIfNotEmpty(
        '{',
        [
          ...typeParams.map((typeParam) => 'required this.$typeParam,'),
          ...node.methods.accept(_ConcreteImplClosureCtorArg(resolver)),
        ].join(_newLine(depth: 2)),
        '}',
      );
      final setClosures = _encloseIfNotEmpty(
        ' :  ',
        node.methods
            .map((method) => '_${method.finalName} = ${method.finalName}')
            .join(', '),
        '',
      );
      final typeClassesDef = typeParams.map((typeParam) => '''
@override
final $_jType<\$$typeParam> $typeParam;
''').join(_newLine(depth: 1));
      s.write('''

class _$implClassName$typeParamsDef implements $implClassName$typeParamsCall {
  _$implClassName(
    $concreteCtorArgs
  )$setClosures;

  $typeClassesDef

''');
      final concreteClosureDef = _ConcreteImplClosureDef(resolver, s);
      for (final method in node.methods) {
        method.accept(concreteClosureDef);
      }
      s.writeln();
      final concreteMethodDef = _ConcreteImplMethod(resolver, s);
      for (final method in node.methods) {
        method.accept(concreteMethodDef);
      }
      s.writeln('}');
    }
    // TypeClass definition.
    final typeClassesCall =
        typeParams.map((typeParam) => '$typeParam,').join(_newLine(depth: 2));
    final signature = node.signature;
    final superTypeClass = superClass.accept(_TypeClassGenerator(resolver));
    final hashCodeTypeClasses = typeParams.join(', ');
    final equalityTypeClasses = typeParams
        .map((typeParam) => ' &&\n        $typeParam == other.$typeParam')
        .join();
    final hashCode = typeParams.isEmpty
        ? '($typeClassName).hashCode'
        : 'Object.hash($typeClassName, $hashCodeTypeClasses)';
    s.write('''
final class $typeClassName$typeParamsDef extends $_jType<$name$typeParamsCall> {
  $typeClassesDef

  const $typeClassName(
    $ctorTypeClassesDef
  );

  @override
  String get signature => r"$signature";

  @override
  $name$typeParamsCall fromReference($_jReference reference) => $name.fromReference(
    $typeClassesCall
    reference
  );

  @override
  $_jType get superType => ${superTypeClass.name};

  @override
  final superCount = ${node.superCount};

  @override
  int get hashCode => $hashCode;

  @override
  bool operator ==(Object other) {
    return other.runtimeType == ($typeClassName$typeParamsCall) &&
        other is $typeClassName$typeParamsCall$equalityTypeClasses;
  }
}

''');
    log.finest('Generated bindings for class ${node.binaryName}');
  }
}

/// Generates the JavaDoc comments.
class _DocGenerator extends Visitor<JavaDocComment, void> {
  final StringSink s;
  final int depth;

  const _DocGenerator(this.s, {required this.depth});

  @override
  void visit(JavaDocComment node) {
    final link = RegExp('{@link ([^{}]+)}');
    final indent = '  ' * depth;
    final comments = node.comment
        .replaceAllMapped(link, (match) => match.group(1) ?? '')
        .replaceAll('#', '\\#')
        .replaceAll('<p>', '')
        .replaceAll('</p>', '\n')
        .replaceAll('<b>', '__')
        .replaceAll('</b>', '__')
        .replaceAll('<em>', '_')
        .replaceAll('</em>', '_')
        .split('\n')
        .join('\n$indent///');
    s.write('''
$indent///
$indent/// $comments
''');
  }
}

/// Generates the user-facing Dart type.
class _TypeGenerator extends TypeVisitor<String> {
  final Resolver? resolver;

  const _TypeGenerator(this.resolver);

  @override
  String visitArrayType(ArrayType node) {
    final innerType = node.type;
    if (innerType.kind == Kind.primitive) {
      return '$_jArray<$_jni.j${(innerType.type as PrimitiveType).name}>';
    }
    return '$_jArray<${innerType.accept(this)}>';
  }

  @override
  String visitDeclaredType(DeclaredType node) {
    if (node.classDecl.binaryName == 'java.lang.Object' ||
        node.classDecl.binaryName == 'java.lang.String') {
      return '$_jni.${node.classDecl.finalName}';
    }

    // All type parameters of this type
    final allTypeParams = node.classDecl.allTypeParams
        .accept(const _TypeParamGenerator(withExtends: false))
        .toList();
    // The ones that are declared.
    final definedTypeParams = node.params.accept(this).toList();

    // Replacing the declared ones. They come at the end.
    // The rest will be JObject.
    if (allTypeParams.length >= node.params.length) {
      allTypeParams.replaceRange(
        0,
        allTypeParams.length - node.params.length,
        List.filled(
          allTypeParams.length - node.params.length,
          _jObject,
        ),
      );
      allTypeParams.replaceRange(
        allTypeParams.length - node.params.length,
        allTypeParams.length,
        definedTypeParams,
      );
    }

    final typeParams = _encloseIfNotEmpty('<', allTypeParams.join(', '), '>');
    final prefix = resolver?.resolvePrefix(node.classDecl) ?? '';
    return '$prefix${node.classDecl.finalName}$typeParams';
  }

  @override
  String visitPrimitiveType(PrimitiveType node) {
    return node.dartType;
  }

  @override
  String visitTypeVar(TypeVar node) {
    return '$_typeParamPrefix${node.name}';
  }

  @override
  String visitWildcard(Wildcard node) {
    // TODO(#141): Support wildcards
    return super.visitWildcard(node);
  }

  @override
  String visitNonPrimitiveType(ReferredType node) {
    return _jObject;
  }
}

class _TypeClass {
  final String name;
  final bool canBeConst;

  const _TypeClass(this.name, this.canBeConst);
}

/// Generates the type class.
class _TypeClassGenerator extends TypeVisitor<_TypeClass> {
  final bool isConst;

  /// Whether or not to return the equivalent boxed type class for primitives.
  /// Only for interface implemetation.
  final bool boxPrimitives;

  /// Whether or not to find the correct type variable from the static map.
  /// Only for interface implemetation.
  final bool typeVarFromMap;

  final Resolver resolver;

  _TypeClassGenerator(
    this.resolver, {
    this.isConst = true,
    this.boxPrimitives = false,
    this.typeVarFromMap = false,
  });

  @override
  _TypeClass visitArrayType(ArrayType node) {
    final innerTypeClass = node.type.accept(_TypeClassGenerator(
      resolver,
      isConst: false,
      boxPrimitives: false,
      typeVarFromMap: typeVarFromMap,
    ));
    final ifConst = innerTypeClass.canBeConst && isConst ? 'const ' : '';
    return _TypeClass(
      '$ifConst${_jArray}Type(${innerTypeClass.name})',
      innerTypeClass.canBeConst,
    );
  }

  @override
  _TypeClass visitDeclaredType(DeclaredType node) {
    final allTypeParams = node.classDecl.allTypeParams
        .accept(const _TypeParamGenerator(withExtends: false))
        .toList();

    // The ones that are declared.
    final definedTypeClasses = node.params.accept(_TypeClassGenerator(
      resolver,
      isConst: false,
      boxPrimitives: false,
      typeVarFromMap: typeVarFromMap,
    ));

    // Can be const if all the type parameters are defined and each of them are
    // also const.
    final canBeConst =
        allTypeParams.isEmpty || definedTypeClasses.every((e) => e.canBeConst);

    // Replacing the declared ones. They come at the end.
    // The rest will be `JObjectType`.
    if (allTypeParams.length >= node.params.length) {
      allTypeParams.replaceRange(
        0,
        allTypeParams.length - node.params.length,
        List.filled(
          allTypeParams.length - node.params.length,
          // Adding const to subexpressions if the entire expression is not const.
          '${canBeConst ? '' : 'const '}${_jObject}Type()',
        ),
      );
      allTypeParams.replaceRange(
        allTypeParams.length - node.params.length,
        allTypeParams.length,
        // Adding const to subexpressions if the entire expression is not const.
        definedTypeClasses.map((param) =>
            '${param.canBeConst && !canBeConst ? 'const ' : ''}${param.name}'),
      );
    }

    final args = allTypeParams.join(', ');
    final ifConst = isConst && canBeConst ? 'const ' : '';
    final prefix = resolver.resolvePrefix(node.classDecl);
    return _TypeClass(
      '$ifConst$prefix${node.classDecl.typeClassName}($args)',
      canBeConst,
    );
  }

  @override
  _TypeClass visitPrimitiveType(PrimitiveType node) {
    final ifConst = isConst ? 'const ' : '';
    final name = boxPrimitives ? 'J${node.boxedName}' : 'j${node.name}';
    return _TypeClass('$ifConst$_jni.${name}Type()', true);
  }

  @override
  _TypeClass visitTypeVar(TypeVar node) {
    if (typeVarFromMap) {
      return _TypeClass('_\$impls[\$p]!.${node.name}', false);
    }
    return _TypeClass(node.name, false);
  }

  @override
  _TypeClass visitWildcard(Wildcard node) {
    // TODO(#141): Support wildcards
    return super.visitWildcard(node);
  }

  @override
  _TypeClass visitNonPrimitiveType(ReferredType node) {
    final ifConst = isConst ? 'const ' : '';
    return _TypeClass('$ifConst${_jObject}Type()', true);
  }
}

class _TypeParamGenerator extends Visitor<TypeParam, String> {
  final bool withExtends;

  const _TypeParamGenerator({required this.withExtends});

  @override
  String visit(TypeParam node) {
    if (!withExtends) {
      return node.name;
    }
    // TODO(#144): resolve the actual type being extended, if any.
    return '$_typeParamPrefix${node.name} extends $_jObject';
  }
}

class _JniResultGetter extends TypeVisitor<String> {
  final Resolver resolver;

  _JniResultGetter(this.resolver);

  @override
  String visitPrimitiveType(PrimitiveType node) {
    if (node.name == 'void') return 'check()';
    if (node.name == 'double') return 'doubleFloat';
    if (node.name == 'int') return 'integer';
    return node.name;
  }

  @override
  String visitNonPrimitiveType(ReferredType node) {
    final type = node.accept(_TypeClassGenerator(resolver)).name;
    return 'object($type)';
  }
}

/// Type signature for C-based bindings.
///
/// When `isFFi` is `true`, it generates the ffi type signature and when it's
/// false, it generates the dart type signature.
///
/// For example `ffi.Int32` is an ffi type signature while `int` is a Dart one:
/// ```dart
/// jniLookup<ffi.NativeFunction<jni.JniResult Function(ffi.Int32, ffi.Int32)>>(
///       "sum")
///   .asFunction<jni.JniResult Function(int, int)>();
/// ```
class _TypeSig extends TypeVisitor<String> {
  final bool isFfi;
  final bool isCBased;

  const _TypeSig({required this.isFfi, required this.isCBased});

  @override
  String visitPrimitiveType(PrimitiveType node) {
    if (!isCBased && isFfi) {
      // TODO(https://github.com/dart-lang/sdk/issues/55471): Once this lands in
      // the stable, use the actual types instead.
      if (node.name == 'float' || node.name == 'double') {
        return '$_ffi.Double';
      } else {
        return '$_ffi.Int64';
      }
    }
    if (isFfi) return '$_ffi.${node.ffiType}';
    if (node.name == 'boolean') return 'int';
    return node.dartType;
  }

  @override
  String visitNonPrimitiveType(ReferredType node) {
    return _voidPointer;
  }
}

class _ToNativeSuffix extends TypeVisitor<String> {
  const _ToNativeSuffix();

  @override
  String visitPrimitiveType(PrimitiveType node) {
    if (node.name == 'boolean') {
      return ' ? 1 : 0';
    }
    return '';
  }

  @override
  String visitNonPrimitiveType(ReferredType node) {
    return '.$_selfPointer';
  }
}

class _FieldGenerator extends Visitor<Field, void> {
  final Config config;
  final Resolver resolver;
  final StringSink s;

  const _FieldGenerator(this.config, this.resolver, this.s);

  void writeCAccessor(Field node) {
    final name = node.finalName;
    final cName = node.accept(const CFieldName());
    final ifRef = node.isStatic ? '' : '$_jPointer, ';

    s.write('''
  static final _get_$name =
      $_lookup<$_ffi.NativeFunction<$_jResult Function($ifRef)>>(
              "get_$cName")
          .asFunction<$_jResult Function($ifRef)>();

''');

    if (!node.isFinal) {
      final ffiSig =
          node.type.accept(const _TypeSig(isFfi: true, isCBased: true));
      final dartSig =
          node.type.accept(const _TypeSig(isFfi: false, isCBased: true));
      s.write('''
  static final _set_$name =
      $_lookup<$_ffi.NativeFunction<$_jResult Function($ifRef$ffiSig)>>(
              "set_$cName")
          .asFunction<$_jResult Function($ifRef$dartSig)>();

''');
    }
  }

  String cGetter(Field node) {
    final name = node.finalName;
    final getter = node.type.accept(_JniResultGetter(resolver));
    final self = node.isStatic ? '' : _selfPointer;
    return '_get_$name($self).$getter';
  }

  String cSetter(Field node) {
    final name = node.finalName;
    final self = node.isStatic ? '' : '$_selfPointer, ';
    final toNativeSuffix = node.type.accept(const _ToNativeSuffix());
    return '_set_$name(${self}value$toNativeSuffix).check()';
  }

  void writeDartOnlyAccessor(Field node) {
    final name = node.finalName;
    final staticOrInstance = node.isStatic ? 'static' : 'instance';
    final descriptor = node.type.descriptor;
    s.write('''
  static final _id_$name =
      $_classRef.${staticOrInstance}FieldId(
        r"${node.name}",
        r"$descriptor",
      );
''');
  }

  String dartOnlyGetter(Field node) {
    final name = node.finalName;
    final self = node.isStatic ? _classRef : _self;
    final type = node.type.accept(_TypeClassGenerator(resolver)).name;
    return '_id_$name.get($self, $type)';
  }

  String dartOnlySetter(Field node) {
    final name = node.finalName;
    final self = node.isStatic ? _classRef : _self;
    final type = node.type.accept(_TypeClassGenerator(resolver)).name;
    return '_id_$name.set($self, $type, value)';
  }

  void writeDocs(Field node, {required bool writeReleaseInstructions}) {
    final originalDecl = '${node.type.shorthand} ${node.name}';
    s.writeln('  /// from: ${node.modifiers.join(' ')} $originalDecl');
    if (node.type.kind != Kind.primitive && writeReleaseInstructions) {
      s.writeln(_releaseInstruction);
    }
    node.javadoc?.accept(_DocGenerator(s, depth: 1));
  }

  @override
  void visit(Field node) {
    final isCBased = config.outputConfig.bindingsType == BindingsType.cBased;

    // Check if it should be a `static const` getter.
    if (node.isFinal && node.isStatic && node.defaultValue != null) {
      final name = node.finalName;
      final value = node.defaultValue!;
      if (value is num || value is bool) {
        writeDocs(node, writeReleaseInstructions: false);
        s.writeln('  static const $name = $value;');
        return;
      }
    }

    // Accessors.
    (isCBased ? writeCAccessor : writeDartOnlyAccessor)(node);

    // Getter docs.
    writeDocs(node, writeReleaseInstructions: true);

    final name = node.finalName;
    final ifStatic = node.isStatic ? 'static ' : '';
    final type = node.type.accept(_TypeGenerator(resolver));
    s.write('$ifStatic$type get $name => ');
    s.write((isCBased ? cGetter : dartOnlyGetter)(node));
    s.writeln(';\n');
    if (!node.isFinal) {
      // Setter docs.
      writeDocs(node, writeReleaseInstructions: true);

      s.write('${ifStatic}set $name($type value) => ');
      s.write((isCBased ? cSetter : dartOnlySetter)(node));
      s.writeln(';\n');
    }
  }
}

class _MethodTypeSig extends Visitor<Method, String> {
  final bool isFfi;
  final bool isCBased;

  const _MethodTypeSig({required this.isFfi, required this.isCBased});

  @override
  String visit(Method node) {
    final callParams = node.params
        .map((param) => param.type)
        .accept(_TypeSig(isFfi: isFfi, isCBased: isCBased))
        .join(', ');
    final args = [
      if ((!node.isCtor && !node.isStatic) || !isCBased) _voidPointer,
      if (!isCBased) '$_jni.JMethodIDPtr',
      !isCBased && isFfi && callParams.isNotEmpty
          ? '$_ffi.VarArgs<($callParams${node.params.length == 1 ? ',' : ''})>'
          : callParams
    ].join(', ');
    final isCtor = node.isCtor;
    final isVoid = node.returnType.name == 'void';
    final returnType = !isCBased && !isCtor && isVoid ? _jThrowable : _jResult;
    return '$returnType Function($args)';
  }
}

/// Generates Dart bindings for Java methods.
class _MethodGenerator extends Visitor<Method, void> {
  final Config config;
  final Resolver resolver;
  final StringSink s;

  const _MethodGenerator(this.config, this.resolver, this.s);

  void writeCAccessor(Method node) {
    final name = node.finalName;
    final cName = node.accept(const CMethodName());
    final ffiSig =
        node.accept(const _MethodTypeSig(isFfi: true, isCBased: true));
    final dartSig =
        node.accept(const _MethodTypeSig(isFfi: false, isCBased: true));
    s.write('''
  static final _$name =
          $_lookup<$_ffi.NativeFunction<$ffiSig>>("$cName")
      .asFunction<$dartSig>();

''');
  }

  void writeDartOnlyAccessor(Method node) {
    final name = node.finalName;
    final kind = node.isCtor
        ? 'constructor'
        : node.isStatic
            ? 'staticMethod'
            : 'instanceMethod';
    final descriptor = node.descriptor;
    s.write('''
  static final _id_$name = $_classRef.${kind}Id(
''');
    if (!node.isCtor) s.writeln('    r"${node.name}",');
    s.write('''
    r"$descriptor",
  );
''');
    final ffiSig =
        node.accept(const _MethodTypeSig(isFfi: true, isCBased: false));
    final dartSig =
        node.accept(const _MethodTypeSig(isFfi: false, isCBased: false));
    final methodName = node.accept(const _CallMethodName());
    s.write('''

  static final _$name = $_protectedExtension
    .lookup<$_ffi.NativeFunction<$ffiSig>>("$methodName")
    .asFunction<$dartSig>();
''');
  }

  bool isSuspendFun(Method node) {
    return node.asyncReturnType != null;
  }

  String cCtor(Method node) {
    final name = node.finalName;
    final params = node.params.accept(const _ParamCall()).join(', ');
    return '_$name($params).reference';
  }

  String dartOnlyCtor(Method node) {
    final name = node.finalName;
    final params = [
      '$_classRef.reference.pointer',
      '_id_$name as $_jni.JMethodIDPtr',
      ...node.params.accept(const _ParamCall()),
    ].join(', ');
    return '_$name($params).reference';
  }

  String cMethodCall(Method node) {
    final name = node.finalName;
    final params = [
      if (!node.isStatic) _selfPointer,
      ...node.params.accept(const _ParamCall()),
    ].join(', ');
    final resultGetter = node.returnType.accept(_JniResultGetter(resolver));
    return '_$name($params).$resultGetter';
  }

  String dartOnlyMethodCall(Method node) {
    final name = node.finalName;
    final params = [
      node.isStatic ? '$_classRef.reference.pointer' : _selfPointer,
      '_id_$name as $_jni.JMethodIDPtr',
      ...node.params.accept(const _ParamCall()),
    ].join(', ');
    final resultGetter = node.returnType.accept(_JniResultGetter(resolver));
    return '_$name($params).$resultGetter';
  }

  @override
  void visit(Method node) {
    final isCBased = config.outputConfig.bindingsType == BindingsType.cBased;

    // Accessors
    (isCBased ? writeCAccessor : writeDartOnlyAccessor)(node);

    // Docs
    s.write('  /// from: ');
    s.writeAll(node.modifiers.map((m) => '$m '));
    s.write('${node.returnType.shorthand} ${node.name}(');
    s.writeAll(node.params.map((p) => '${p.type.shorthand} ${p.name}'), ', ');
    s.writeln(')');
    if (node.returnType.kind != Kind.primitive || node.isCtor) {
      s.writeln(_releaseInstruction);
    }
    node.javadoc?.accept(_DocGenerator(s, depth: 1));

    // Used for inferring the type parameter from the given parameters.
    final typeLocators = node.params
        .accept(_ParamTypeLocator(resolver: resolver))
        .fold(<String, List<String>>{}, _mergeMapValues).map(
            (key, value) => MapEntry(
                  key,
                  _encloseIfNotEmpty(
                    '[',
                    value.delimited(', '),
                    ']',
                  ),
                ));

    bool isRequired(TypeParam typeParam) {
      return (typeLocators[typeParam.name] ?? '').isEmpty;
    }

    final typeInference =
        (node.isCtor ? node.classDecl.allTypeParams : node.typeParams)
            .where((tp) => !isRequired(tp))
            .map((tp) => tp.name)
            .map((tp) => '$tp ??= $_jni.lowestCommonSuperType'
                '(${typeLocators[tp]}) as $_jType<$_typeParamPrefix$tp>;')
            .join(_newLine(depth: 2));

    if (node.isCtor) {
      final className = node.classDecl.finalName;
      final name = node.finalName;
      final ctorName = name == 'new0' ? className : '$className.$name';
      final paramsDef = node.params.accept(_ParamDef(resolver)).delimited(', ');
      final typeClassDef = _encloseIfNotEmpty(
        '{',
        node.classDecl.allTypeParams
            .map((typeParam) => typeParam
                .accept(_CtorTypeClassDef(isRequired: isRequired(typeParam))))
            .delimited(', '),
        '}',
      );
      final typeClassCall = node.classDecl.allTypeParams
          .map((typeParam) =>
              typeParam.accept(const _TypeParamGenerator(withExtends: false)))
          .delimited(', ');

      final ctorExpr = (isCBased ? cCtor : dartOnlyCtor)(node);
      s.write('''
  factory $ctorName($paramsDef$typeClassDef) {
    $typeInference
    return ${node.classDecl.finalName}.fromReference(
      $typeClassCall
      $ctorExpr
    );
  }

''');
      return;
    }

    final name = node.finalName;
    final returnType = isSuspendFun(node)
        ? 'Future<${node.asyncReturnType!.accept(_TypeGenerator(resolver))}>'
        : node.returnType.accept(_TypeGenerator(resolver));
    final returnTypeClass = (node.asyncReturnType ?? node.returnType)
        .accept(_TypeClassGenerator(resolver))
        .name;
    final ifStatic = node.isStatic ? 'static ' : '';
    final defArgs = node.params.accept(_ParamDef(resolver)).toList();
    final typeClassDef = _encloseIfNotEmpty(
      '{',
      node.typeParams
          .map((typeParam) => typeParam.accept(_MethodTypeClassDef(
                isRequired: isRequired(typeParam),
              )))
          .delimited(', '),
      '}',
    );
    final typeParamsDef = _encloseIfNotEmpty(
      '<',
      node.typeParams
          .accept(const _TypeParamGenerator(withExtends: true))
          .join(', '),
      '>',
    );
    if (isSuspendFun(node)) {
      defArgs.removeLast();
    }
    final params = defArgs.delimited(', ');
    s.write('  $ifStatic$returnType $name$typeParamsDef($params$typeClassDef)');
    final callExpr = (isCBased ? cMethodCall : dartOnlyMethodCall)(node);
    if (isSuspendFun(node)) {
      final returningType =
          node.asyncReturnType!.accept(_TypeClassGenerator(resolver)).name;
      s.write('''async {
    $typeInference
    final \$p = ReceivePort();
    final \$c = $_jObject.fromReference($_protectedExtension.newPortContinuation(\$p));
    $callExpr;
    final \$o = $_jGlobalReference($_jPointer.fromAddress(await \$p.first));
    final \$k = $returnTypeClass.jClass.reference.pointer;
    if (!$_jni.Jni.env.IsInstanceOf(\$o.pointer, \$k)) {
      throw "Failed";
    }
    return $returningType.fromReference(\$o);
  }

''');
    } else {
      final returning = returnType == 'void' ? callExpr : 'return $callExpr';
      s.writeln('''{
    $typeInference
    $returning;
  }
''');
    }
  }
}

/// Generates the method type param definition.
///
/// For example `required JObjType<T> $T` in:
/// ```dart
/// void bar(..., {required JObjType<T> $T}) => ...
/// ```
class _MethodTypeClassDef extends Visitor<TypeParam, String> {
  final bool isRequired;

  const _MethodTypeClassDef({required this.isRequired});

  @override
  String visit(TypeParam node) {
    return '${isRequired ? 'required ' : ''}$_jType'
        '<$_typeParamPrefix${node.name}>${isRequired ? '' : '?'} ${node.name}';
  }
}

/// Generates the class type param definition. Used only in constructors.
///
/// For example `required this.$T` in:
/// ```dart
/// class Foo {
///   final JObjType<T> $T;
///   Foo(..., {required this.$T}) => ...
/// }
/// ```
class _CtorTypeClassDef extends Visitor<TypeParam, String> {
  final bool isRequired;

  const _CtorTypeClassDef({required this.isRequired});

  @override
  String visit(TypeParam node) {
    return '${isRequired ? 'required ' : ''} $_jType'
        '<$_typeParamPrefix${node.name}>${isRequired ? '' : '?'} ${node.name}';
  }
}

/// Method parameter's definition.
///
/// For example `Foo foo` in:
/// ```dart
/// void bar(Foo foo) => ...
/// ```
class _ParamDef extends Visitor<Param, String> {
  final Resolver resolver;

  const _ParamDef(this.resolver);

  @override
  String visit(Param node) {
    final type = node.type.accept(_TypeGenerator(resolver));
    return '$type ${node.finalName}';
  }
}

/// Method parameter used in calling the native method.
///
/// For example `foo.reference.pointer` in:
/// ```dart
/// void bar(Foo foo) => _bar(foo.reference.pointer);
/// ```
class _ParamCall extends Visitor<Param, String> {
  const _ParamCall();

  @override
  String visit(Param node) {
    final nativeSuffix = node.type.accept(const _ToNativeSuffix());
    final paramCall = '${node.finalName}$nativeSuffix';
    return paramCall;
  }
}

/// A pair of [StringBuffer]s that can create an expression from the outer layer
/// inwards.
///
/// For example:
/// ```dart
/// final buffer = OutsideInBuffer(); // asterisk (*) is used to show the middle
/// buffer.appendLeft('f('); // f(*
/// buffer.prependRight('x)'); // f(*x)
/// buffer.appendLeft('g('); // f(g(*x)
/// buffer.prependRight('y) + '); // f(g(*y) + x)
/// buffer.toString(); // f(g(y) + x)
/// ```
@visibleForTesting
class OutsideInBuffer {
  final StringBuffer _leftBuffer;
  final StringBuffer _rightBuffer;

  OutsideInBuffer()
      : _leftBuffer = StringBuffer(),
        _rightBuffer = StringBuffer();

  void prependRight(Object? object) {
    final s = object.toString();
    for (var i = 0; i < s.length; ++i) {
      _rightBuffer.write(s[s.length - i - 1]);
    }
  }

  void appendLeft(Object? object) {
    _leftBuffer.write(object);
  }

  @override
  String toString() {
    return _leftBuffer.toString() + _rightBuffer.toString().reversed;
  }
}

/// The ways to locate each type parameter.
///
/// For example in `JArray<JMap<$T, $T>> a`, `T` can be retreived using
/// ```dart
/// ((((a.$type as jni.JArrayType).elementType) as $JMapType).K) as jni.JObjType<$T>
/// ```
/// and
/// ```dart
/// ((((a.$type as jni.JArrayType).elementType) as $JMapType).V) as jni.JObjType<$T>
/// ```
class _ParamTypeLocator extends Visitor<Param, Map<String, List<String>>> {
  final Resolver resolver;

  _ParamTypeLocator({required this.resolver});

  @override
  Map<String, List<String>> visit(Param node) {
    return node.type.accept(_TypeVarLocator(resolver: resolver)).map(
          (key, value) => MapEntry(
            key,
            value
                .map((e) =>
                    (e..appendLeft('${node.finalName}.\$type')).toString())
                .toList(),
          ),
        );
  }
}

class _TypeVarLocator extends TypeVisitor<Map<String, List<OutsideInBuffer>>> {
  final Resolver resolver;

  _TypeVarLocator({required this.resolver});

  @override
  Map<String, List<OutsideInBuffer>> visitNonPrimitiveType(ReferredType node) {
    return {};
  }

  @override
  Map<String, List<OutsideInBuffer>> visitWildcard(Wildcard node) {
    // TODO(#141): Support wildcards
    return super.visitWildcard(node);
  }

  @override
  Map<String, List<OutsideInBuffer>> visitTypeVar(TypeVar node) {
    return {
      node.name: [
        OutsideInBuffer(),
      ],
    };
  }

  @override
  Map<String, List<OutsideInBuffer>> visitDeclaredType(DeclaredType node) {
    if (node.classDecl.isObject) {
      return {};
    }
    final offset = node.classDecl.allTypeParams.length - node.params.length;
    final result = <String, List<OutsideInBuffer>>{};
    final prefix = resolver.resolvePrefix(node.classDecl);
    final typeClass = '$prefix${node.classDecl.typeClassName}';
    for (var i = 0; i < node.params.length; ++i) {
      final typeParam = node.classDecl.allTypeParams[i + offset].name;
      final exprs = node.params[i].accept(this);
      for (final expr in exprs.entries) {
        for (final buffer in expr.value) {
          buffer.appendLeft('(');
          buffer.prependRight(' as $typeClass).$typeParam');
          result[expr.key] = (result[expr.key] ?? [])..add(buffer);
        }
      }
    }
    return result;
  }

  @override
  Map<String, List<OutsideInBuffer>> visitArrayType(ArrayType node) {
    final exprs = node.type.accept(this);
    for (final e in exprs.values.expand((i) => i)) {
      e.appendLeft('((');
      e.prependRight(' as ${_jArray}Type).elementType as $_jType)');
    }
    return exprs;
  }

  @override
  Map<String, List<OutsideInBuffer>> visitPrimitiveType(PrimitiveType node) {
    return {};
  }
}

/// Method defintion for Impl abstract class used for interface implementation.
class _AbstractImplMethod extends Visitor<Method, void> {
  final Resolver resolver;
  final StringSink s;

  _AbstractImplMethod(this.resolver, this.s);

  @override
  void visit(Method node) {
    final returnType = node.returnType.accept(_TypeGenerator(resolver));
    final name = node.finalName;
    final args = node.params.accept(_ParamDef(resolver)).join(', ');
    s.writeln('  $returnType $name($args);');
  }
}

/// Closure defintion for concrete Impl class used for interface implementation.
class _ConcreteImplClosureDef extends Visitor<Method, void> {
  final Resolver resolver;
  final StringSink s;

  _ConcreteImplClosureDef(this.resolver, this.s);

  @override
  void visit(Method node) {
    final returnType = node.returnType.accept(_TypeGenerator(resolver));
    final name = node.finalName;
    final args = node.params.accept(_ParamDef(resolver)).join(', ');
    s.writeln('  final $returnType Function($args) _$name;');
  }
}

/// Closure argument for concrete Impl class constructor.
/// Used for interface implementation.
class _ConcreteImplClosureCtorArg extends Visitor<Method, String> {
  final Resolver resolver;

  _ConcreteImplClosureCtorArg(this.resolver);

  @override
  String visit(Method node) {
    final returnType = node.returnType.accept(_TypeGenerator(resolver));
    final name = node.finalName;
    final args = node.params.accept(_ParamDef(resolver)).join(', ');
    return 'required $returnType Function($args) $name,';
  }
}

/// Method defintion for concrete Impl class used for interface implementation.
class _ConcreteImplMethod extends Visitor<Method, void> {
  final Resolver resolver;
  final StringSink s;

  _ConcreteImplMethod(this.resolver, this.s);

  @override
  void visit(Method node) {
    final returnType = node.returnType.accept(_TypeGenerator(resolver));
    final name = node.finalName;
    final argsDef = node.params.accept(_ParamDef(resolver)).join(', ');
    final argsCall = node.params.map((param) => param.finalName).join(', ');
    s.write('''
  $returnType $name($argsDef) {
    return _$name($argsCall);
  }''');
  }
}

/// The if statement to check which method has been called from the proxy class.
class _InterfaceMethodIf extends Visitor<Method, void> {
  final Resolver resolver;
  final StringSink s;

  _InterfaceMethodIf(this.resolver, this.s);

  @override
  void visit(Method node) {
    final isVoid = node.returnType.name == 'void';
    final signature = node.javaSig;
    final saveResult = isVoid ? '' : 'final \$r = ';
    final name = node.finalName;
    s.write('''
        if (\$d == r"$signature") {
          ${saveResult}_\$impls[\$p]!.$name(
''');
    for (var i = 0; i < node.params.length; ++i) {
      node.params[i].accept(_InterfaceParamCast(resolver, s, paramIndex: i));
    }
    const returnBox = _InterfaceReturnBox();
    s.write('''
          );
          return ${node.returnType.accept(returnBox)};
        }
''');
  }
}

/// Generates casting to the correct parameter type from the list of JObject
/// arguments received from the call to the proxy class.
class _InterfaceParamCast extends Visitor<Param, void> {
  final Resolver resolver;
  final StringSink s;
  final int paramIndex;

  _InterfaceParamCast(
    this.resolver,
    this.s, {
    required this.paramIndex,
  });

  @override
  void visit(Param node) {
    final typeClass = node.type
        .accept(_TypeClassGenerator(
          resolver,
          boxPrimitives: true,
          typeVarFromMap: true,
        ))
        .name;
    s.write('\$a[$paramIndex].castTo($typeClass, releaseOriginal: true)');
    if (node.type.kind == Kind.primitive) {
      // Convert to Dart type.
      final name = (node.type.type as PrimitiveType).name;
      s.write('.${name}Value(releaseOriginal: true)');
    }
    s.writeln(',');
  }
}

/// Boxes the returned primitive value into the correct Boxed type.
/// Only returns the reference for non primitive types.
/// Returns null for void.
///
/// Since Dart doesn't know that this global reference is still used, it might
/// garbage collect it via [NativeFinalizer] thus making it invalid.
/// This passes the ownership to Java using [setAsReleased].
///
/// `toPointer` detaches the object from the [NativeFinalizer] and Java
/// will clean up the global reference afterwards.
///
/// For example `$r.toJInteger().reference.toPointer()` when the return
/// type is `integer`.
class _InterfaceReturnBox extends TypeVisitor<String> {
  const _InterfaceReturnBox();

  @override
  String visitNonPrimitiveType(ReferredType node) {
    // Casting is done to create a new global reference. The user might
    // use the original reference elsewhere and so the original object
    // should not be [setAsReleased].
    return '(\$r as $_jObject).castTo(const ${_jObject}Type()).reference.toPointer()';
  }

  @override
  String visitPrimitiveType(PrimitiveType node) {
    if (node.name == 'void') {
      return '$_jni.nullptr';
    }
    return '$_jni.J${node.boxedName}(\$r).reference.toPointer()';
  }
}

class _CallMethodName extends Visitor<Method, String> {
  const _CallMethodName();

  @override
  String visit(Method node) {
    if (node.isCtor) {
      return 'globalEnv_NewObject';
    }
    final String type;
    if (node.returnType.kind == Kind.primitive) {
      type = (node.returnType.type as PrimitiveType).name.capitalize();
    } else {
      type = 'Object';
    }
    return 'globalEnv_Call${node.isStatic ? 'Static' : ''}${type}Method';
  }
}
