// WARNING: This file is machine generated by fidlgen_dart.
// @dart = 2.12

library fidl_test_foreigntypeinresponseusedthroughcompose_async;

import 'dart:async' as $async;
import 'dart:core' hide Set;
import 'dart:developer';
import 'dart:typed_data';

import 'package:fidl/fidl.dart' as $fidl;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart' as $zircon;

import 'package:fidl_test_bottom/fidl_async.dart' as lib$test_bottom;
import 'package:fidl_test_middle/fidl_async.dart' as lib$test_middle;
// ignore_for_file: always_specify_types
// ignore_for_file: avoid_positional_boolean_parameters
// ignore_for_file: avoid_returning_null
// ignore_for_file: cascade_invocations
// ignore_for_file: constant_identifier_names
// ignore_for_file: directives_ordering
// ignore_for_file: one_member_abstracts
// ignore_for_file: prefer_constructors_over_static_methods
// ignore_for_file: prefer_single_quotes
// ignore_for_file: public_member_api_docs
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: library_prefixes
// ignore_for_file: prefer_typing_uninitialized_variables
// ignore_for_file: avoid_js_rounded_ints
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: prefer_generic_function_type_aliases
// ignore_for_file: prefer_equal_for_default_values
// ignore_for_file: avoid_catches_without_on_clauses
// ignore_for_file: unused_shown_name
// ignore_for_file: unnecessary_lambdas
// ignore_for_file: comment_references
// ignore_for_file: avoid_unused_constructor_parameters
// ignore_for_file: prefer_interpolation_to_compose_strings

// getFoo: () -> (lib$test_bottom.Foo foo)
const int _kTop_GetFoo_Ordinal = 0x401a9ffa95a4c333;
const $fidl.MethodType _kTop_GetFoo_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<lib$test_bottom.Foo>(
        type: lib$test_bottom.kFoo_Type, offset: 0),
  ],
  name: r"Top.GetFoo",
  requestInlineSizeV2: 0,
  responseInlineSizeV2: 4,
);

abstract class Top {
  $fidl.ServiceData? get $serviceData => TopData();
  $async.Future<lib$test_bottom.Foo> getFoo();
} // TODO: Remove ServiceData for non-service

class TopData implements $fidl.ServiceData<Top> {
  const TopData();

  @override
  String getName() {
    return "";
  }

  @override
  $fidl.AsyncBinding getBinding() {
    return TopBinding();
  }
}

class TopProxy extends $fidl.AsyncProxy<Top> implements Top {
  TopProxy() : super($fidl.AsyncProxyController<Top>($interfaceName: r'Top')) {
    ctrl.onResponse = _handleResponse;
  }
  @override
  Null get $serviceData => null;

  void _handleEvent($fidl.IncomingMessage $message) {
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }

  void _handleResponse($fidl.IncomingMessage $message) {
    final int $txid = $message.txid;
    if ($txid == 0) {
      _handleEvent($message);
      return;
    }
    final $async.Completer? $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    switch ($message.ordinal) {
      case _kTop_GetFoo_Ordinal:
        final String _name = _kTop_GetFoo_Type.name;
        $fidl.performCtrlWithExceptionHandling(
            _name, ctrl, 'method response', $completer.completeError, () {
          final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.response!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage(
              $message,
              _kTop_GetFoo_Type.responseInlineSize($message.wireFormat),
              $types[0]);

          $completer.complete($response);
        });
        break;
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }

  @override
  $async.Future<lib$test_bottom.Foo> getFoo() {
    if (!ctrl.isBound) {
      return $async.Future.error(
          $fidl.FidlStateException('Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = $fidl.Encoder($fidl.kWireFormatDefault);
    $encoder.encodeMessageHeader(
        _kTop_GetFoo_Ordinal, 0, $fidl.CallStrictness.strict);
    final $completer = $async.Completer<lib$test_bottom.Foo>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class TopBinding extends $fidl.AsyncBinding<Top> {
  TopBinding() : super(r"Top");

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      case _kTop_GetFoo_Ordinal:
        final String _name = _kTop_GetFoo_Type.name;
        $fidl.performWithExceptionHandling(_name, () {
          final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<lib$test_bottom.Foo> $future = $fidl
              .decodeMessageWithCallback<$async.Future<lib$test_bottom.Foo>>(
                  $message,
                  _kTop_GetFoo_Type.requestInlineSize($message.wireFormat),
                  ($fidl.Decoder decoder) {
            return _impl.getFoo();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder =
                $fidl.Encoder($fidl.kWireFormatDefault);
            $encoder.encodeMessageHeader(_kTop_GetFoo_Ordinal, $message.txid,
                $fidl.CallStrictness.strict);
            final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kTop_GetFoo_Type.responseInlineSize($encoder.wireFormat),
                $types[0],
                $response);
            $respond($encoder.message);
          }, onError: (_e) {
            $fidl.handleException(_name, _e, close);
          });
        }, close);
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for TopBinding');
    }
  }
}
