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

library fidl_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_bottom/fidl_async.dart' as lib$bottom;
import 'package:fidl_middle/fidl_async.dart' as lib$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: 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

// ignore: unused_element, avoid_private_typedef_functions
typedef _VoidCallback = void Function();

// getFoo: () -> (lib$bottom.Foo foo)
const int _kTop_GetFoo_Ordinal = 0x6ae8d19bc98f3d92;
const $fidl.MethodType _kTop_GetFoo_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<lib$bottom.Foo>(type: lib$bottom.kFoo_Type, offset: 0),
  ],
  name: r"Top.GetFoo",
  requestInlineSize: 0,
  responseInlineSize: 8,
);

abstract class Top {
  $fidl.ServiceData? get $serviceData => TopData();
  $async.Future<lib$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.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

  void _handleResponse($fidl.Message $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;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      case _kTop_GetFoo_Ordinal:
        final String _name = _kTop_GetFoo_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.response!;
          $decoder.claimMemory(
              _kTop_GetFoo_Type.decodeResponseInlineSize($decoder));
          // ignore: prefer_const_declarations
          final $response =
              $types[0].decode($decoder, $fidl.kMessageHeaderSize);

          $completer.complete($response);
        } catch (_e) {
          ctrl.proxyError($fidl.FidlError(
              'Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

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

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

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

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      case _kTop_GetFoo_Ordinal:
        final String _name = _kTop_GetFoo_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.request!;
          $decoder
              .claimMemory(_kTop_GetFoo_Type.decodeRequestInlineSize($decoder));
          final $async.Future<lib$bottom.Foo> $future = impl!.getFoo();
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(_kTop_GetFoo_Ordinal, $message.txid);
            $encoder
                .alloc(_kTop_GetFoo_Type.encodingResponseInlineSize($encoder));
            final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.response!;
            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for TopBinding');
    }
  }
}
