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

library fidl_test_transitivedependenciescompose_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 = 0x245770d9d719c667;
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');
    }
  }
}
