// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'ast.dart';
import 'functional.dart';
import 'generator.dart';
import 'generator_tools.dart';
import 'pigeon_lib.dart' show Error;

/// General comment opening token.
const String _commentPrefix = '//';

/// Documentation comment spec.
const DocumentCommentSpecification _docCommentSpec =
    DocumentCommentSpecification(_commentPrefix);

/// The default serializer for Flutter.
const String _defaultCodecSerializer = 'flutter::StandardCodecSerializer';

/// Options that control how C++ code will be generated.
class CppOptions {
  /// Creates a [CppOptions] object
  const CppOptions({
    this.headerIncludePath,
    this.namespace,
    this.copyrightHeader,
    this.headerOutPath,
  });

  /// The path to the header that will get placed in the source filed (example:
  /// "foo.h").
  final String? headerIncludePath;

  /// The namespace where the generated class will live.
  final String? namespace;

  /// A copyright header that will get prepended to generated code.
  final Iterable<String>? copyrightHeader;

  /// The path to the output header file location.
  final String? headerOutPath;

  /// Creates a [CppOptions] from a Map representation where:
  /// `x = CppOptions.fromMap(x.toMap())`.
  static CppOptions fromMap(Map<String, Object> map) {
    return CppOptions(
      headerIncludePath: map['header'] as String?,
      namespace: map['namespace'] as String?,
      copyrightHeader: map['copyrightHeader'] as Iterable<String>?,
      headerOutPath: map['cppHeaderOut'] as String?,
    );
  }

  /// Converts a [CppOptions] to a Map representation where:
  /// `x = CppOptions.fromMap(x.toMap())`.
  Map<String, Object> toMap() {
    final Map<String, Object> result = <String, Object>{
      if (headerIncludePath != null) 'header': headerIncludePath!,
      if (namespace != null) 'namespace': namespace!,
      if (copyrightHeader != null) 'copyrightHeader': copyrightHeader!,
    };
    return result;
  }

  /// Overrides any non-null parameters from [options] into this to make a new
  /// [CppOptions].
  CppOptions merge(CppOptions options) {
    return CppOptions.fromMap(mergeMaps(toMap(), options.toMap()));
  }
}

/// Class that manages all Cpp code generation.
class CppGenerator extends Generator<OutputFileOptions<CppOptions>> {
  /// Constructor.
  const CppGenerator();

  /// Generates C++ file of type specified in [generatorOptions]
  @override
  void generate(OutputFileOptions<CppOptions> generatorOptions, Root root,
      StringSink sink) {
    assert(generatorOptions.fileType == FileType.header ||
        generatorOptions.fileType == FileType.source);
    if (generatorOptions.fileType == FileType.header) {
      const CppHeaderGenerator()
          .generate(generatorOptions.languageOptions, root, sink);
    } else if (generatorOptions.fileType == FileType.source) {
      const CppSourceGenerator()
          .generate(generatorOptions.languageOptions, root, sink);
    }
  }
}

/// Writes C++ header (.h) file to sink.
class CppHeaderGenerator extends StructuredGenerator<CppOptions> {
  /// Constructor.
  const CppHeaderGenerator();

  @override
  void writeFilePrologue(
      CppOptions generatorOptions, Root root, Indent indent) {
    if (generatorOptions.copyrightHeader != null) {
      addLines(indent, generatorOptions.copyrightHeader!, linePrefix: '// ');
    }
    indent.writeln('$_commentPrefix $generatedCodeWarning');
    indent.writeln('$_commentPrefix $seeAlsoWarning');
    indent.newln();
  }

  @override
  void writeFileImports(CppOptions generatorOptions, Root root, Indent indent) {
    final String guardName = _getGuardName(generatorOptions.headerIncludePath);
    indent.writeln('#ifndef $guardName');
    indent.writeln('#define $guardName');

    _writeSystemHeaderIncludeBlock(indent, <String>[
      'flutter/basic_message_channel.h',
      'flutter/binary_messenger.h',
      'flutter/encodable_value.h',
      'flutter/standard_message_codec.h',
    ]);
    indent.newln();
    _writeSystemHeaderIncludeBlock(indent, <String>[
      'map',
      'string',
      'optional',
    ]);
    indent.newln();
    if (generatorOptions.namespace != null) {
      indent.writeln('namespace ${generatorOptions.namespace} {');
    }
    indent.newln();
    if (generatorOptions.namespace?.endsWith('_pigeontest') ?? false) {
      final String testFixtureClass =
          '${_pascalCaseFromSnakeCase(generatorOptions.namespace!.replaceAll('_pigeontest', ''))}Test';
      indent.writeln('class $testFixtureClass;');
    }
    indent.newln();
    indent.writeln('$_commentPrefix Generated class from Pigeon.');
  }

  @override
  void writeEnum(
      CppOptions generatorOptions, Root root, Indent indent, Enum anEnum) {
    indent.newln();
    addDocumentationComments(
        indent, anEnum.documentationComments, _docCommentSpec);
    indent.write('enum class ${anEnum.name} ');
    indent.addScoped('{', '};', () {
      enumerate(anEnum.members, (int index, final EnumMember member) {
        addDocumentationComments(
            indent, member.documentationComments, _docCommentSpec);
        indent.writeln(
            '${member.name} = $index${index == anEnum.members.length - 1 ? '' : ','}');
      });
    });
  }

  @override
  void writeGeneralUtilities(
      CppOptions generatorOptions, Root root, Indent indent) {
    _writeErrorOr(indent, friends: root.apis.map((Api api) => api.name));
  }

  @override
  void writeDataClass(
      CppOptions generatorOptions, Root root, Indent indent, Class klass) {
    // When generating for a Pigeon unit test, add a test fixture friend class to
    // allow unit testing private methods, since testing serialization via public
    // methods is essentially an end-to-end test.
    String? testFixtureClass;
    if (generatorOptions.namespace?.endsWith('_pigeontest') ?? false) {
      testFixtureClass =
          '${_pascalCaseFromSnakeCase(generatorOptions.namespace!.replaceAll('_pigeontest', ''))}Test';
    }
    indent.newln();

    const List<String> generatedMessages = <String>[
      ' Generated class from Pigeon that represents data sent in messages.'
    ];

    addDocumentationComments(
        indent, klass.documentationComments, _docCommentSpec,
        generatorComments: generatedMessages);

    indent.write('class ${klass.name} ');
    indent.addScoped('{', '};', () {
      indent.addScoped(' public:', '', () {
        indent.writeln('${klass.name}();');
        for (final NamedType field in getFieldsInSerializationOrder(klass)) {
          addDocumentationComments(
              indent, field.documentationComments, _docCommentSpec);
          final HostDatatype baseDatatype = getFieldHostDatatype(
              field, root.classes, root.enums, _baseCppTypeForBuiltinDartType);
          indent.writeln(
              '${_getterReturnType(baseDatatype)} ${_makeGetterName(field)}() const;');
          indent.writeln(
              'void ${_makeSetterName(field)}(${_unownedArgumentType(baseDatatype)} value_arg);');
          if (field.type.isNullable) {
            // Add a second setter that takes the non-nullable version of the
            // argument for convenience, since setting literal values with the
            // pointer version is non-trivial.
            final HostDatatype nonNullType = _nonNullableType(baseDatatype);
            indent.writeln(
                'void ${_makeSetterName(field)}(${_unownedArgumentType(nonNullType)} value_arg);');
          }
          indent.newln();
        }
      });

      indent.addScoped(' private:', '', () {
        indent.writeln('${klass.name}(const flutter::EncodableList& list);');
        indent.writeln('flutter::EncodableList ToEncodableList() const;');
        for (final Class friend in root.classes) {
          if (friend != klass &&
              friend.fields.any(
                  (NamedType element) => element.type.baseName == klass.name)) {
            indent.writeln('friend class ${friend.name};');
          }
        }
        for (final Api api in root.apis) {
          // TODO(gaaclarke): Find a way to be more precise with our
          // friendships.
          indent.writeln('friend class ${api.name};');
          indent.writeln('friend class ${_getCodecSerializerName(api)};');
        }
        if (testFixtureClass != null) {
          indent.writeln('friend class $testFixtureClass;');
        }

        for (final NamedType field in getFieldsInSerializationOrder(klass)) {
          final HostDatatype hostDatatype = getFieldHostDatatype(
              field, root.classes, root.enums, _baseCppTypeForBuiltinDartType);
          indent.writeln(
              '${_valueType(hostDatatype)} ${_makeInstanceVariableName(field)};');
        }
      });
    }, nestCount: 0);
    indent.newln();
  }

  @override
  void writeFlutterApi(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Api api,
  ) {
    assert(api.location == ApiLocation.flutter);
    if (getCodecClasses(api, root).isNotEmpty) {
      _writeCodec(generatorOptions, root, indent, api);
    }
    const List<String> generatedMessages = <String>[
      ' Generated class from Pigeon that represents Flutter messages that can be called from C++.'
    ];
    addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
        generatorComments: generatedMessages);
    indent.write('class ${api.name} ');
    indent.addScoped('{', '};', () {
      indent.addScoped(' private:', '', () {
        indent.writeln('flutter::BinaryMessenger* binary_messenger_;');
      });
      indent.addScoped(' public:', '', () {
        indent
            .write('${api.name}(flutter::BinaryMessenger* binary_messenger);');
        indent.newln();
        indent
            .writeln('static const flutter::StandardMessageCodec& GetCodec();');
        for (final Method func in api.methods) {
          final HostDatatype returnType = getHostDatatype(func.returnType,
              root.classes, root.enums, _baseCppTypeForBuiltinDartType);
          addDocumentationComments(
              indent, func.documentationComments, _docCommentSpec);

          final Iterable<String> argTypes = func.arguments.map((NamedType arg) {
            final HostDatatype hostType = getFieldHostDatatype(
                arg, root.classes, root.enums, _baseCppTypeForBuiltinDartType);
            return _flutterApiArgumentType(hostType);
          });
          final Iterable<String> argNames =
              indexMap(func.arguments, _getArgumentName);
          final List<String> parameters = <String>[
            ...map2(argTypes, argNames, (String x, String y) => '$x $y'),
            ..._flutterApiCallbackParameters(returnType),
          ];
          indent.writeln(
              'void ${_makeMethodName(func)}(${parameters.join(', ')});');
        }
      });
    }, nestCount: 0);
    indent.newln();
  }

  @override
  void writeHostApi(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Api api,
  ) {
    assert(api.location == ApiLocation.host);
    if (getCodecClasses(api, root).isNotEmpty) {
      _writeCodec(generatorOptions, root, indent, api);
    }
    const List<String> generatedMessages = <String>[
      ' Generated interface from Pigeon that represents a handler of messages from Flutter.'
    ];
    addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
        generatorComments: generatedMessages);
    indent.write('class ${api.name} ');
    indent.addScoped('{', '};', () {
      indent.addScoped(' public:', '', () {
        indent.writeln('${api.name}(const ${api.name}&) = delete;');
        indent.writeln('${api.name}& operator=(const ${api.name}&) = delete;');
        indent.writeln('virtual ~${api.name}() {}');
        for (final Method method in api.methods) {
          final HostDatatype returnType = getHostDatatype(method.returnType,
              root.classes, root.enums, _baseCppTypeForBuiltinDartType);
          final String returnTypeName = _hostApiReturnType(returnType);

          final List<String> argSignature = <String>[];
          if (method.arguments.isNotEmpty) {
            final Iterable<String> argTypes =
                method.arguments.map((NamedType arg) {
              final HostDatatype hostType = getFieldHostDatatype(arg,
                  root.classes, root.enums, _baseCppTypeForBuiltinDartType);
              return _hostApiArgumentType(hostType);
            });
            final Iterable<String> argNames =
                method.arguments.map((NamedType e) => _makeVariableName(e));
            argSignature.addAll(
                map2(argTypes, argNames, (String argType, String argName) {
              return '$argType $argName';
            }));
          }

          addDocumentationComments(
              indent, method.documentationComments, _docCommentSpec);

          if (method.isAsynchronous) {
            argSignature
                .add('std::function<void($returnTypeName reply)> result');
            indent.writeln(
                'virtual void ${_makeMethodName(method)}(${argSignature.join(', ')}) = 0;');
          } else {
            indent.writeln(
                'virtual $returnTypeName ${_makeMethodName(method)}(${argSignature.join(', ')}) = 0;');
          }
        }
        indent.newln();
        indent.writeln('$_commentPrefix The codec used by ${api.name}.');
        indent
            .writeln('static const flutter::StandardMessageCodec& GetCodec();');
        indent.writeln(
            '$_commentPrefix Sets up an instance of `${api.name}` to handle messages through the `binary_messenger`.');
        indent.writeln(
            'static void SetUp(flutter::BinaryMessenger* binary_messenger, ${api.name}* api);');
        indent.writeln(
            'static flutter::EncodableValue WrapError(std::string_view error_message);');
        indent.writeln(
            'static flutter::EncodableValue WrapError(const FlutterError& error);');
      });
      indent.addScoped(' protected:', '', () {
        indent.writeln('${api.name}() = default;');
      });
    }, nestCount: 0);
  }

  void _writeCodec(
      CppOptions generatorOptions, Root root, Indent indent, Api api) {
    assert(getCodecClasses(api, root).isNotEmpty);
    final String codeSerializerName = _getCodecSerializerName(api);
    indent
        .write('class $codeSerializerName : public $_defaultCodecSerializer ');
    indent.addScoped('{', '};', () {
      indent.addScoped(' public:', '', () {
        indent.newln();
        indent.format('''
inline static $codeSerializerName& GetInstance() {
\tstatic $codeSerializerName sInstance;
\treturn sInstance;
}
''');
        indent.writeln('$codeSerializerName();');
      });
      indent.writeScoped(' public:', '', () {
        indent.writeln(
            'void WriteValue(const flutter::EncodableValue& value, flutter::ByteStreamWriter* stream) const override;');
      });
      indent.writeScoped(' protected:', '', () {
        indent.writeln(
            'flutter::EncodableValue ReadValueOfType(uint8_t type, flutter::ByteStreamReader* stream) const override;');
      });
    }, nestCount: 0);
    indent.newln();
  }

  void _writeErrorOr(Indent indent,
      {Iterable<String> friends = const <String>[]}) {
    final String friendLines = friends
        .map((String className) => '\tfriend class $className;')
        .join('\n');
    indent.format('''

class FlutterError {
 public:
\texplicit FlutterError(const std::string& code)
\t\t: code_(code) {}
\texplicit FlutterError(const std::string& code, const std::string& message)
\t\t: code_(code), message_(message) {}
\texplicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details)
\t\t: code_(code), message_(message), details_(details) {}

\tconst std::string& code() const { return code_; }
\tconst std::string& message() const { return message_; }
\tconst flutter::EncodableValue& details() const { return details_; }

 private:
\tstd::string code_;
\tstd::string message_;
\tflutter::EncodableValue details_;
};

template<class T> class ErrorOr {
 public:
\tErrorOr(const T& rhs) { new(&v_) T(rhs); }
\tErrorOr(const T&& rhs) { v_ = std::move(rhs); }
\tErrorOr(const FlutterError& rhs) {
\t\tnew(&v_) FlutterError(rhs);
\t}
\tErrorOr(const FlutterError&& rhs) { v_ = std::move(rhs); }

\tbool has_error() const { return std::holds_alternative<FlutterError>(v_); }
\tconst T& value() const { return std::get<T>(v_); };
\tconst FlutterError& error() const { return std::get<FlutterError>(v_); };

 private:
$friendLines
\tErrorOr() = default;
\tT TakeValue() && { return std::get<T>(std::move(v_)); }

\tstd::variant<T, FlutterError> v_;
};
''');
  }

  @override
  void writeCloseNamespace(
      CppOptions generatorOptions, Root root, Indent indent) {
    if (generatorOptions.namespace != null) {
      indent.writeln('}  // namespace ${generatorOptions.namespace}');
    }
    final String guardName = _getGuardName(generatorOptions.headerIncludePath);
    indent.writeln('#endif  // $guardName');
  }
}

/// Writes C++ source (.cpp) file to sink.
class CppSourceGenerator extends StructuredGenerator<CppOptions> {
  /// Constructor.
  const CppSourceGenerator();

  @override
  void writeFilePrologue(
      CppOptions generatorOptions, Root root, Indent indent) {
    if (generatorOptions.copyrightHeader != null) {
      addLines(indent, generatorOptions.copyrightHeader!, linePrefix: '// ');
    }
    indent.writeln('$_commentPrefix $generatedCodeWarning');
    indent.writeln('$_commentPrefix $seeAlsoWarning');
    indent.newln();
    indent.addln('#undef _HAS_EXCEPTIONS');
    indent.newln();
  }

  @override
  void writeFileImports(CppOptions generatorOptions, Root root, Indent indent) {
    indent.writeln('#include "${generatorOptions.headerIncludePath}"');
    indent.newln();
    _writeSystemHeaderIncludeBlock(indent, <String>[
      'flutter/basic_message_channel.h',
      'flutter/binary_messenger.h',
      'flutter/encodable_value.h',
      'flutter/standard_message_codec.h',
    ]);
    indent.newln();
    _writeSystemHeaderIncludeBlock(indent, <String>[
      'map',
      'string',
      'optional',
    ]);
    indent.newln();
  }

  @override
  void writeOpenNamespace(
      CppOptions generatorOptions, Root root, Indent indent) {
    if (generatorOptions.namespace != null) {
      indent.writeln('namespace ${generatorOptions.namespace} {');
    }
  }

  @override
  void writeGeneralUtilities(
      CppOptions generatorOptions, Root root, Indent indent) {
    final List<String> usingDirectives = <String>[
      'flutter::BasicMessageChannel',
      'flutter::CustomEncodableValue',
      'flutter::EncodableList',
      'flutter::EncodableMap',
      'flutter::EncodableValue',
    ];
    usingDirectives.sort();
    for (final String using in usingDirectives) {
      indent.writeln('using $using;');
    }
  }

  @override
  void writeDataClass(
      CppOptions generatorOptions, Root root, Indent indent, Class klass) {
    final Set<String> customClassNames =
        root.classes.map((Class x) => x.name).toSet();
    final Set<String> customEnumNames =
        root.enums.map((Enum x) => x.name).toSet();

    indent.newln();
    indent.writeln('$_commentPrefix ${klass.name}');
    indent.newln();

    // Getters and setters.
    for (final NamedType field in getFieldsInSerializationOrder(klass)) {
      _writeCppSourceClassField(generatorOptions, root, indent, klass, field);
    }

    // Serialization.
    writeClassEncode(generatorOptions, root, indent, klass, customClassNames,
        customEnumNames);

    // Default constructor.
    indent.writeln('${klass.name}::${klass.name}() {}');
    indent.newln();

    // Deserialization.
    writeClassDecode(generatorOptions, root, indent, klass, customClassNames,
        customEnumNames);
  }

  @override
  void writeClassEncode(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Class klass,
    Set<String> customClassNames,
    Set<String> customEnumNames,
  ) {
    indent.write('EncodableList ${klass.name}::ToEncodableList() const ');
    indent.addScoped('{', '}', () {
      indent.writeln('EncodableList list;');
      indent.writeln('list.reserve(${klass.fields.length});');
      for (final NamedType field in getFieldsInSerializationOrder(klass)) {
        final HostDatatype hostDatatype = getFieldHostDatatype(field,
            root.classes, root.enums, _shortBaseCppTypeForBuiltinDartType);
        final String encodableValue = _wrappedHostApiArgumentExpression(
            root, _makeInstanceVariableName(field), field.type, hostDatatype);
        indent.writeln('list.push_back($encodableValue);');
      }
      indent.writeln('return list;');
    });
    indent.newln();
  }

  @override
  void writeClassDecode(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Class klass,
    Set<String> customClassNames,
    Set<String> customEnumNames,
  ) {
    indent.write('${klass.name}::${klass.name}(const EncodableList& list) ');
    indent.addScoped('{', '}', () {
      enumerate(getFieldsInSerializationOrder(klass),
          (int index, final NamedType field) {
        final String instanceVariableName = _makeInstanceVariableName(field);
        final String pointerFieldName =
            '${_pointerPrefix}_${_makeVariableName(field)}';
        final String encodableFieldName =
            '${_encodablePrefix}_${_makeVariableName(field)}';
        indent.writeln('auto& $encodableFieldName = list[$index];');
        if (customEnumNames.contains(field.type.baseName)) {
          indent.writeln(
              'if (const int32_t* $pointerFieldName = std::get_if<int32_t>(&$encodableFieldName))\t$instanceVariableName = (${field.type.baseName})*$pointerFieldName;');
        } else {
          final HostDatatype hostDatatype = getFieldHostDatatype(field,
              root.classes, root.enums, _shortBaseCppTypeForBuiltinDartType);
          if (field.type.baseName == 'int') {
            indent.format('''
if (const int32_t* $pointerFieldName = std::get_if<int32_t>(&$encodableFieldName))
\t$instanceVariableName = *$pointerFieldName;
else if (const int64_t* ${pointerFieldName}_64 = std::get_if<int64_t>(&$encodableFieldName))
\t$instanceVariableName = *${pointerFieldName}_64;''');
          } else if (!hostDatatype.isBuiltin &&
              root.classes
                  .map((Class x) => x.name)
                  .contains(field.type.baseName)) {
            indent.write(
                'if (const EncodableList* $pointerFieldName = std::get_if<EncodableList>(&$encodableFieldName)) ');
            indent.addScoped('{', '}', () {
              indent.writeln(
                  '$instanceVariableName = ${hostDatatype.datatype}(*$pointerFieldName);');
            });
          } else {
            indent.write(
                'if (const ${hostDatatype.datatype}* $pointerFieldName = std::get_if<${hostDatatype.datatype}>(&$encodableFieldName)) ');
            indent.addScoped('{', '}', () {
              indent.writeln('$instanceVariableName = *$pointerFieldName;');
            });
          }
        }
      });
    });
  }

  @override
  void writeFlutterApi(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Api api,
  ) {
    assert(api.location == ApiLocation.flutter);
    if (getCodecClasses(api, root).isNotEmpty) {
      _writeCodec(generatorOptions, root, indent, api);
    }
    indent.writeln(
        '$_commentPrefix Generated class from Pigeon that represents Flutter messages that can be called from C++.');
    indent.write(
        '${api.name}::${api.name}(flutter::BinaryMessenger* binary_messenger) ');
    indent.addScoped('{', '}', () {
      indent.writeln('this->binary_messenger_ = binary_messenger;');
    });
    indent.newln();
    final String codeSerializerName = getCodecClasses(api, root).isNotEmpty
        ? _getCodecSerializerName(api)
        : _defaultCodecSerializer;
    indent.format('''
const flutter::StandardMessageCodec& ${api.name}::GetCodec() {
\treturn flutter::StandardMessageCodec::GetInstance(&$codeSerializerName::GetInstance());
}
''');
    for (final Method func in api.methods) {
      final String channelName = makeChannelName(api, func);
      final HostDatatype returnType = getHostDatatype(func.returnType,
          root.classes, root.enums, _shortBaseCppTypeForBuiltinDartType);

      // Determine the input paramater list, saved in a structured form for later
      // use as platform channel call arguments.
      final Iterable<_HostNamedType> hostParameters =
          indexMap(func.arguments, (int i, NamedType arg) {
        final HostDatatype hostType = getFieldHostDatatype(
            arg, root.classes, root.enums, _shortBaseCppTypeForBuiltinDartType);
        return _HostNamedType(_getSafeArgumentName(i, arg), hostType, arg.type);
      });
      final List<String> parameters = <String>[
        ...hostParameters.map((_HostNamedType arg) =>
            '${_flutterApiArgumentType(arg.hostType)} ${arg.name}'),
        ..._flutterApiCallbackParameters(returnType),
      ];
      indent.write(
          'void ${api.name}::${_makeMethodName(func)}(${parameters.join(', ')}) ');
      indent.writeScoped('{', '}', () {
        const String channel = 'channel';
        indent.writeln(
            'auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, '
            '"$channelName", &GetCodec());');

        // Convert arguments to EncodableValue versions.
        const String argumentListVariableName = 'encoded_api_arguments';
        indent.write('EncodableValue $argumentListVariableName = ');
        if (func.arguments.isEmpty) {
          indent.addln('EncodableValue();');
        } else {
          indent.addScoped('EncodableValue(EncodableList{', '});', () {
            for (final _HostNamedType param in hostParameters) {
              final String encodedArgument = _wrappedHostApiArgumentExpression(
                  root, param.name, param.originalType, param.hostType);
              indent.writeln('$encodedArgument,');
            }
          });
        }

        indent.write('$channel->Send($argumentListVariableName, '
            // ignore: missing_whitespace_between_adjacent_strings
            '[on_success = std::move(on_success), on_error = std::move(on_error)]'
            '(const uint8_t* reply, size_t reply_size) ');
        indent.addScoped('{', '});', () {
          final String successCallbackArgument;
          if (func.returnType.isVoid) {
            successCallbackArgument = '';
          } else {
            successCallbackArgument = 'return_value';
            final String encodedReplyName =
                'encodable_$successCallbackArgument';
            indent.writeln(
                'std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);');
            indent.writeln('const auto& $encodedReplyName = *response;');
            _writeEncodableValueArgumentUnwrapping(indent, returnType,
                argName: successCallbackArgument,
                encodableArgName: encodedReplyName);
          }
          indent.writeln('on_success($successCallbackArgument);');
        });
      });
    }
  }

  @override
  void writeHostApi(
      CppOptions generatorOptions, Root root, Indent indent, Api api) {
    assert(api.location == ApiLocation.host);
    if (getCodecClasses(api, root).isNotEmpty) {
      _writeCodec(generatorOptions, root, indent, api);
    }

    final String codeSerializerName = getCodecClasses(api, root).isNotEmpty
        ? _getCodecSerializerName(api)
        : _defaultCodecSerializer;
    indent.format('''
/// The codec used by ${api.name}.
const flutter::StandardMessageCodec& ${api.name}::GetCodec() {
\treturn flutter::StandardMessageCodec::GetInstance(&$codeSerializerName::GetInstance());
}
''');
    indent.writeln(
        '$_commentPrefix Sets up an instance of `${api.name}` to handle messages through the `binary_messenger`.');
    indent.write(
        'void ${api.name}::SetUp(flutter::BinaryMessenger* binary_messenger, ${api.name}* api) ');
    indent.addScoped('{', '}', () {
      for (final Method method in api.methods) {
        final String channelName = makeChannelName(api, method);
        indent.write('');
        indent.addScoped('{', '}', () {
          indent.writeln(
              'auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, '
              '"$channelName", &GetCodec());');
          indent.write('if (api != nullptr) ');
          indent.addScoped('{', '} else {', () {
            indent.write(
                'channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) ');
            indent.addScoped('{', '});', () {
              indent.write('try ');
              indent.addScoped('{', '}', () {
                final List<String> methodArgument = <String>[];
                if (method.arguments.isNotEmpty) {
                  indent.writeln(
                      'const auto& args = std::get<EncodableList>(message);');

                  enumerate(method.arguments, (int index, NamedType arg) {
                    final HostDatatype hostType = getHostDatatype(
                        arg.type,
                        root.classes,
                        root.enums,
                        (TypeDeclaration x) =>
                            _shortBaseCppTypeForBuiltinDartType(x));
                    final String argName = _getSafeArgumentName(index, arg);

                    final String encodableArgName =
                        '${_encodablePrefix}_$argName';
                    indent.writeln(
                        'const auto& $encodableArgName = args.at($index);');
                    if (!arg.type.isNullable) {
                      indent.write('if ($encodableArgName.IsNull()) ');
                      indent.addScoped('{', '}', () {
                        indent.writeln(
                            'reply(WrapError("$argName unexpectedly null."));');
                        indent.writeln('return;');
                      });
                    }
                    _writeEncodableValueArgumentUnwrapping(indent, hostType,
                        argName: argName, encodableArgName: encodableArgName);
                    methodArgument.add(argName);
                  });
                }

                final HostDatatype returnType = getHostDatatype(
                    method.returnType,
                    root.classes,
                    root.enums,
                    _shortBaseCppTypeForBuiltinDartType);
                final String returnTypeName = _hostApiReturnType(returnType);
                if (method.isAsynchronous) {
                  methodArgument.add(
                    '[reply]($returnTypeName&& output) {${indent.newline}'
                    '${_wrapResponse(indent, root, method.returnType, prefix: '\t')}${indent.newline}'
                    '}',
                  );
                }
                final String call =
                    'api->${_makeMethodName(method)}(${methodArgument.join(', ')})';
                if (method.isAsynchronous) {
                  indent.format('$call;');
                } else {
                  indent.writeln('$returnTypeName output = $call;');
                  indent.format(_wrapResponse(indent, root, method.returnType));
                }
              }, addTrailingNewline: false);
              indent.add(' catch (const std::exception& exception) ');
              indent.addScoped('{', '}', () {
                // There is a potential here for `reply` to be called twice, which
                // is a violation of the API contract, because there's no way of
                // knowing whether or not the plugin code called `reply` before
                // throwing. Since use of `@async` suggests that the reply is
                // probably not sent within the scope of the stack, err on the
                // side of potential double-call rather than no call (which is
                // also an API violation) so that unexpected errors have a better
                // chance of being caught and handled in a useful way.
                indent.writeln('reply(WrapError(exception.what()));');
              });
            });
          });
          indent.addScoped(null, '}', () {
            indent.writeln('channel->SetMessageHandler(nullptr);');
          });
        });
      }
    });

    indent.newln();
    indent.format('''
EncodableValue ${api.name}::WrapError(std::string_view error_message) {
\treturn EncodableValue(EncodableList{
\t\tEncodableValue(std::string(error_message)),
\t\tEncodableValue("Error"),
\t\tEncodableValue()
\t});
}
EncodableValue ${api.name}::WrapError(const FlutterError& error) {
\treturn EncodableValue(EncodableList{
\t\tEncodableValue(error.message()),
\t\tEncodableValue(error.code()),
\t\terror.details()
\t});
}''');
    indent.newln();
  }

  void _writeCodec(
    CppOptions generatorOptions,
    Root root,
    Indent indent,
    Api api,
  ) {
    assert(getCodecClasses(api, root).isNotEmpty);
    final String codeSerializerName = _getCodecSerializerName(api);
    indent.newln();
    indent.writeln('$codeSerializerName::$codeSerializerName() {}');
    indent.write(
        'EncodableValue $codeSerializerName::ReadValueOfType(uint8_t type, flutter::ByteStreamReader* stream) const ');
    indent.addScoped('{', '}', () {
      indent.write('switch (type) ');
      indent.addScoped('{', '}', () {
        for (final EnumeratedClass customClass in getCodecClasses(api, root)) {
          indent.writeln('case ${customClass.enumeration}:');
          indent.nest(1, () {
            indent.writeln(
                'return CustomEncodableValue(${customClass.name}(std::get<EncodableList>(ReadValue(stream))));');
          });
        }
        indent.writeln('default:');
        indent.nest(1, () {
          indent.writeln(
              'return $_defaultCodecSerializer::ReadValueOfType(type, stream);');
        });
      });
    });
    indent.newln();
    indent.write(
        'void $codeSerializerName::WriteValue(const EncodableValue& value, flutter::ByteStreamWriter* stream) const ');
    indent.writeScoped('{', '}', () {
      indent.write(
          'if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) ');
      indent.addScoped('{', '}', () {
        for (final EnumeratedClass customClass in getCodecClasses(api, root)) {
          indent.write(
              'if (custom_value->type() == typeid(${customClass.name})) ');
          indent.addScoped('{', '}', () {
            indent.writeln('stream->WriteByte(${customClass.enumeration});');
            indent.writeln(
                'WriteValue(EncodableValue(std::any_cast<${customClass.name}>(*custom_value).ToEncodableList()), stream);');
            indent.writeln('return;');
          });
        }
      });
      indent.writeln('$_defaultCodecSerializer::WriteValue(value, stream);');
    });
    indent.newln();
  }

  void _writeCppSourceClassField(CppOptions generatorOptions, Root root,
      Indent indent, Class klass, NamedType field) {
    final HostDatatype hostDatatype = getFieldHostDatatype(
        field, root.classes, root.enums, _shortBaseCppTypeForBuiltinDartType);
    final String instanceVariableName = _makeInstanceVariableName(field);
    final String qualifiedGetterName =
        '${klass.name}::${_makeGetterName(field)}';
    final String qualifiedSetterName =
        '${klass.name}::${_makeSetterName(field)}';
    final String returnExpression = hostDatatype.isNullable
        ? '$instanceVariableName ? &(*$instanceVariableName) : nullptr'
        : instanceVariableName;

    // Generates the string for a setter treating the type as [type], to allow
    // generating multiple setter variants.
    String makeSetter(HostDatatype type) {
      const String setterArgumentName = 'value_arg';
      final String valueExpression = type.isNullable
          ? '$setterArgumentName ? ${_valueType(type)}(*$setterArgumentName) : std::nullopt'
          : setterArgumentName;
      return 'void $qualifiedSetterName(${_unownedArgumentType(type)} $setterArgumentName) '
          '{ $instanceVariableName = $valueExpression; }';
    }

    indent.writeln(
        '${_getterReturnType(hostDatatype)} $qualifiedGetterName() const '
        '{ return $returnExpression; }');
    indent.writeln(makeSetter(hostDatatype));
    if (hostDatatype.isNullable) {
      // Write the non-nullable variant; see _writeCppHeaderDataClass.
      final HostDatatype nonNullType = _nonNullableType(hostDatatype);
      indent.writeln(makeSetter(nonNullType));
    }

    indent.newln();
  }

  String _wrapResponse(Indent indent, Root root, TypeDeclaration returnType,
      {String prefix = ''}) {
    final String nonErrorPath;
    final String errorCondition;
    final String errorGetter;

    const String nullValue = 'EncodableValue()';
    if (returnType.isVoid) {
      nonErrorPath = '${prefix}wrapped.push_back($nullValue);';
      errorCondition = 'output.has_value()';
      errorGetter = 'value';
    } else {
      final HostDatatype hostType = getHostDatatype(returnType, root.classes,
          root.enums, _shortBaseCppTypeForBuiltinDartType);
      const String extractedValue = 'std::move(output).TakeValue()';
      final String wrapperType =
          hostType.isBuiltin ? 'EncodableValue' : 'CustomEncodableValue';
      if (returnType.isNullable) {
        // The value is a std::optional, so needs an extra layer of
        // handling.
        nonErrorPath = '''
${prefix}auto output_optional = $extractedValue;
${prefix}if (output_optional) {
$prefix\twrapped.push_back($wrapperType(std::move(output_optional).value()));
$prefix} else {
$prefix\twrapped.push_back($nullValue);
$prefix}''';
      } else {
        nonErrorPath =
            '${prefix}wrapped.push_back($wrapperType($extractedValue));';
      }
      errorCondition = 'output.has_error()';
      errorGetter = 'error';
    }
    // Ideally this code would use an initializer list to create
    // an EncodableList inline, which would be less code. However,
    // that would always copy the element, so the slightly more
    // verbose create-and-push approach is used instead.
    return '''
${prefix}if ($errorCondition) {
$prefix\treply(WrapError(output.$errorGetter()));
$prefix\treturn;
$prefix}
${prefix}EncodableList wrapped;
$nonErrorPath
${prefix}reply(EncodableValue(std::move(wrapped)));''';
  }

  @override
  void writeCloseNamespace(
      CppOptions generatorOptions, Root root, Indent indent) {
    if (generatorOptions.namespace != null) {
      indent.writeln('}  // namespace ${generatorOptions.namespace}');
    }
  }

  /// Returns the expression to create an EncodableValue from a host API argument
  /// with the given [variableName] and types.
  String _wrappedHostApiArgumentExpression(Root root, String variableName,
      TypeDeclaration dartType, HostDatatype hostType) {
    final String encodableValue;
    if (!hostType.isBuiltin &&
        root.classes.any((Class c) => c.name == dartType.baseName)) {
      final String operator = hostType.isNullable ? '->' : '.';
      encodableValue =
          'EncodableValue($variableName${operator}ToEncodableList())';
    } else if (!hostType.isBuiltin &&
        root.enums.any((Enum e) => e.name == dartType.baseName)) {
      final String nonNullValue =
          hostType.isNullable ? '(*$variableName)' : variableName;
      encodableValue = 'EncodableValue((int)$nonNullValue)';
    } else {
      final String operator = hostType.isNullable ? '*' : '';
      encodableValue = 'EncodableValue($operator$variableName)';
    }

    if (hostType.isNullable) {
      return '$variableName ? $encodableValue : EncodableValue()';
    }
    return encodableValue;
  }

  /// Writes the code to declare and populate a variable of type [hostType]
  /// called [argName] to use as a parameter to an API method call, from an
  /// existing EncodableValue variable called [encodableArgName].
  void _writeEncodableValueArgumentUnwrapping(
    Indent indent,
    HostDatatype hostType, {
    required String argName,
    required String encodableArgName,
  }) {
    if (hostType.isNullable) {
      // Nullable arguments are always pointers, with nullptr corresponding to
      // null.
      if (hostType.datatype == 'int64_t') {
        // The EncodableValue will either be an int32_t or an int64_t depending
        // on the value, but the generated API requires an int64_t so that it can
        // handle any case. Create a local variable for the 64-bit value...
        final String valueVarName = '${argName}_value';
        indent.writeln(
            'const int64_t $valueVarName = $encodableArgName.IsNull() ? 0 : $encodableArgName.LongValue();');
        // ... then declare the arg as a reference to that local.
        indent.writeln(
            'const auto* $argName = $encodableArgName.IsNull() ? nullptr : &$valueVarName;');
      } else if (hostType.datatype == 'EncodableValue') {
        // Generic objects just pass the EncodableValue through directly.
        indent.writeln('const auto* $argName = &$encodableArgName;');
      } else if (hostType.isBuiltin) {
        indent.writeln(
            'const auto* $argName = std::get_if<${hostType.datatype}>(&$encodableArgName);');
      } else {
        indent.writeln(
            'const auto* $argName = &(std::any_cast<const ${hostType.datatype}&>(std::get<CustomEncodableValue>($encodableArgName)));');
      }
    } else {
      // Non-nullable arguments are either passed by value or reference, but the
      // extraction doesn't need to distinguish since those are the same at the
      // call site.
      if (hostType.datatype == 'int64_t') {
        // The EncodableValue will either be an int32_t or an int64_t depending
        // on the value, but the generated API requires an int64_t so that it can
        // handle any case.
        indent
            .writeln('const int64_t $argName = $encodableArgName.LongValue();');
      } else if (hostType.datatype == 'EncodableValue') {
        // Generic objects just pass the EncodableValue through directly. This
        // creates an alias just to avoid having to special-case the
        // argName/encodableArgName distinction at a higher level.
        indent.writeln('const auto& $argName = $encodableArgName;');
      } else if (hostType.isBuiltin) {
        indent.writeln(
            'const auto& $argName = std::get<${hostType.datatype}>($encodableArgName);');
      } else {
        indent.writeln(
            'const auto& $argName = std::any_cast<const ${hostType.datatype}&>(std::get<CustomEncodableValue>($encodableArgName));');
      }
    }
  }

  /// A wrapper for [_baseCppTypeForBuiltinDartType] that generated Flutter
  /// types without the namespace, since the implementation file uses `using`
  /// directives.
  String? _shortBaseCppTypeForBuiltinDartType(TypeDeclaration type) {
    return _baseCppTypeForBuiltinDartType(type, includeFlutterNamespace: false);
  }
}

/// Contains information about a host function argument.
///
/// This is comparable to a [NamedType], but has already gone through host type
/// and variable name mapping, and it tracks the original [NamedType] that it
/// was created from.
class _HostNamedType {
  const _HostNamedType(this.name, this.hostType, this.originalType);
  final String name;
  final HostDatatype hostType;
  final TypeDeclaration originalType;
}

String _getCodecSerializerName(Api api) => '${api.name}CodecSerializer';

const String _pointerPrefix = 'pointer';
const String _encodablePrefix = 'encodable';

String _getArgumentName(int count, NamedType argument) =>
    argument.name.isEmpty ? 'arg$count' : _makeVariableName(argument);

/// Returns an argument name that can be used in a context where it is possible to collide.
String _getSafeArgumentName(int count, NamedType argument) =>
    '${_getArgumentName(count, argument)}_arg';

/// Returns a non-nullable variant of [type].
HostDatatype _nonNullableType(HostDatatype type) {
  return HostDatatype(
      datatype: type.datatype, isBuiltin: type.isBuiltin, isNullable: false);
}

String _pascalCaseFromCamelCase(String camelCase) =>
    camelCase[0].toUpperCase() + camelCase.substring(1);

String _snakeCaseFromCamelCase(String camelCase) {
  return camelCase.replaceAllMapped(RegExp(r'[A-Z]'),
      (Match m) => '${m.start == 0 ? '' : '_'}${m[0]!.toLowerCase()}');
}

String _pascalCaseFromSnakeCase(String snakeCase) {
  final String camelCase = snakeCase.replaceAllMapped(
      RegExp(r'_([a-z])'), (Match m) => m[1]!.toUpperCase());
  return _pascalCaseFromCamelCase(camelCase);
}

String _makeMethodName(Method method) => _pascalCaseFromCamelCase(method.name);

String _makeGetterName(NamedType field) => _snakeCaseFromCamelCase(field.name);

String _makeSetterName(NamedType field) =>
    'set_${_snakeCaseFromCamelCase(field.name)}';

String _makeVariableName(NamedType field) =>
    _snakeCaseFromCamelCase(field.name);

String _makeInstanceVariableName(NamedType field) =>
    '${_makeVariableName(field)}_';

// TODO(stuartmorgan): Remove this in favor of _isPodType once callers have
// all been updated to using HostDatatypes.
bool _isReferenceType(String dataType) {
  switch (dataType) {
    case 'bool':
    case 'int64_t':
    case 'double':
      return false;
    default:
      return true;
  }
}

/// Returns the parameters to use for the success and error callbacks in a
/// Flutter API function signature.
List<String> _flutterApiCallbackParameters(HostDatatype returnType) {
  return <String>[
    'std::function<void(${_flutterApiReturnType(returnType)})>&& on_success',
    'std::function<void(const FlutterError&)>&& on_error',
  ];
}

/// Returns true if [type] corresponds to a plain-old-data type (i.e., one that
/// should generally be passed by value rather than pointer/reference) in C++.
bool _isPodType(HostDatatype type) {
  return !_isReferenceType(type.datatype);
}

String? _baseCppTypeForBuiltinDartType(
  TypeDeclaration type, {
  bool includeFlutterNamespace = true,
}) {
  final String flutterNamespace = includeFlutterNamespace ? 'flutter::' : '';
  final Map<String, String> cppTypeForDartTypeMap = <String, String>{
    'void': 'void',
    'bool': 'bool',
    'int': 'int64_t',
    'String': 'std::string',
    'double': 'double',
    'Uint8List': 'std::vector<uint8_t>',
    'Int32List': 'std::vector<int32_t>',
    'Int64List': 'std::vector<int64_t>',
    'Float64List': 'std::vector<double>',
    'Map': '${flutterNamespace}EncodableMap',
    'List': '${flutterNamespace}EncodableList',
    'Object': '${flutterNamespace}EncodableValue',
  };
  if (cppTypeForDartTypeMap.containsKey(type.baseName)) {
    return cppTypeForDartTypeMap[type.baseName];
  } else {
    return null;
  }
}

/// Returns the C++ type to use in a value context (variable declaration,
/// pass-by-value, etc.) for the given C++ base type.
String _valueType(HostDatatype type) {
  final String baseType = type.datatype;
  return type.isNullable ? 'std::optional<$baseType>' : baseType;
}

/// Returns the C++ type to use in an argument context without ownership
/// transfer for the given base type.
String _unownedArgumentType(HostDatatype type) {
  final bool isString = type.datatype == 'std::string';
  final String baseType = isString ? 'std::string_view' : type.datatype;
  if (isString || _isPodType(type)) {
    return type.isNullable ? 'const $baseType*' : baseType;
  }
  // TODO(stuartmorgan): Consider special-casing `Object?` here, so that there
  // aren't two ways of representing null (nullptr or an isNull EncodableValue).
  return type.isNullable ? 'const $baseType*' : 'const $baseType&';
}

/// Returns the C++ type to use for arguments to a host API. This is slightly
/// different from [_unownedArgumentType] since passing `std::string_view*` in
/// to the host API implementation when the actual type is `std::string*` is
/// needlessly complicated, so it uses `std::string` directly.
String _hostApiArgumentType(HostDatatype type) {
  final String baseType = type.datatype;
  if (_isPodType(type)) {
    return type.isNullable ? 'const $baseType*' : baseType;
  }
  return type.isNullable ? 'const $baseType*' : 'const $baseType&';
}

/// Returns the C++ type to use for arguments to a Flutter API.
String _flutterApiArgumentType(HostDatatype type) {
  // Nullable strings use std::string* rather than std::string_view*
  // since there's no implicit conversion for the pointer types, making them
  // more awkward to use. For consistency, and since EncodableValue will end
  // up making a std::string internally anyway, std::string is used for the
  // non-nullable case as well.
  if (type.datatype == 'std::string') {
    return type.isNullable ? 'const std::string*' : 'const std::string&';
  }
  return _unownedArgumentType(type);
}

/// Returns the C++ type to use for the return of a getter for a field of type
/// [type].
String _getterReturnType(HostDatatype type) {
  final String baseType = type.datatype;
  if (_isPodType(type)) {
    // Use pointers rather than optionals even for nullable POD, since the
    // semantics of using them is essentially identical and this makes them
    // consistent with non-POD.
    return type.isNullable ? 'const $baseType*' : baseType;
  }
  return type.isNullable ? 'const $baseType*' : 'const $baseType&';
}

/// Returns the C++ type to use for the return of a host API method returning
/// [type].
String _hostApiReturnType(HostDatatype type) {
  if (type.datatype == 'void') {
    return 'std::optional<FlutterError>';
  }
  String valueType = type.datatype;
  if (type.isNullable) {
    valueType = 'std::optional<$valueType>';
  }
  return 'ErrorOr<$valueType>';
}

/// Returns the C++ type to use for the paramer to the asyncronous "return"
/// callback of a Flutter API method returning [type].
String _flutterApiReturnType(HostDatatype type) {
  if (type.datatype == 'void') {
    return 'void';
  }
  // For anything other than void, handle it the same way as a host API argument
  // since it has the same basic structure of being a function defined by the
  // client, being called by the generated code.
  return _hostApiArgumentType(type);
}

String _getGuardName(String? headerFileName) {
  const String prefix = 'PIGEON_';
  if (headerFileName != null) {
    return '$prefix${headerFileName.replaceAll('.', '_').toUpperCase()}_';
  } else {
    return '${prefix}H_';
  }
}

void _writeSystemHeaderIncludeBlock(Indent indent, List<String> headers) {
  headers.sort();
  for (final String header in headers) {
    indent.writeln('#include <$header>');
  }
}

/// Validates an AST to make sure the cpp generator supports everything.
List<Error> validateCpp(CppOptions options, Root root) {
  final List<Error> result = <Error>[];
  for (final Api api in root.apis) {
    for (final Method method in api.methods) {
      for (final NamedType arg in method.arguments) {
        if (isEnum(root, arg.type)) {
          // TODO(gaaclarke): Add line number and filename.
          result.add(Error(
              message:
                  "Nullable enum types aren't supported in C++ arguments in method:${api.name}.${method.name} argument:(${arg.type.baseName} ${arg.name})."));
        }
      }
    }
  }
  return result;
}
