// 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) {
    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;
    }
    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!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage($message,
              _kTop_GetFoo_Type.decodeResponseInlineSize(), $types[0]);

          $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) {
    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!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<lib$bottom.Foo> $future = $fidl
              .decodeMessageWithCallback<$async.Future<lib$bottom.Foo>>(
                  $message, _kTop_GetFoo_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.getFoo();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(_kTop_GetFoo_Ordinal, $message.txid);
            final List<$fidl.MemberType> $types = _kTop_GetFoo_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kTop_GetFoo_Type.encodingResponseInlineSize(),
                $types[0],
                $response);
            $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');
    }
  }
}
