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

library fidl_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_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 = 0x2c8ccb022c3c571f;
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');
    }
  }
}
