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

library fidl_fidl_test_protocolrequest_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;

// 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();

abstract class Child {
  $fidl.ServiceData? get $serviceData => ChildData();
}

// TODO: Remove ServiceData for non-service
class ChildData implements $fidl.ServiceData<Child> {
  const ChildData();

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

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

class ChildProxy extends $fidl.AsyncProxy<Child> implements Child {
  ChildProxy()
      : super($fidl.AsyncProxyController<Child>($interfaceName: r'Child')) {
    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}'));
        ctrl.close();
        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) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }
}

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

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      default:
        throw $fidl.FidlError(r'Unexpected message name for ChildBinding');
    }
  }
}

// getChild: () -> ($fidl.InterfaceHandle<Child> c)
const int _kParent_GetChild_Ordinal = 0x6e0c789be8dbb77e;
const $fidl.MethodType _kParent_GetChild_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(), offset: 0),
  ],
  name: r"Parent.GetChild",
  requestInlineSize: 0,
  responseInlineSize: 8,
);
// getChildRequest: () -> ($fidl.InterfaceRequest<Child> r)
const int _kParent_GetChildRequest_Ordinal = 0x193e7d6949a9df98;
const $fidl.MethodType _kParent_GetChildRequest_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(), offset: 0),
  ],
  name: r"Parent.GetChildRequest",
  requestInlineSize: 0,
  responseInlineSize: 8,
);
// takeChild: ($fidl.InterfaceHandle<Child> c)
const int _kParent_TakeChild_Ordinal = 0x5311bd7214c0f6e;
const $fidl.MethodType _kParent_TakeChild_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(), offset: 0),
  ],
  response: [],
  name: r"Parent.TakeChild",
  requestInlineSize: 8,
  responseInlineSize: 0,
);
// takeChildRequest: ($fidl.InterfaceRequest<Child> r)
const int _kParent_TakeChildRequest_Ordinal = 0x15dae312bad5a9cc;
const $fidl.MethodType _kParent_TakeChildRequest_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(), offset: 0),
  ],
  response: [],
  name: r"Parent.TakeChildRequest",
  requestInlineSize: 8,
  responseInlineSize: 0,
);

abstract class Parent {
  $fidl.ServiceData? get $serviceData => ParentData();
  $async.Future<$fidl.InterfaceHandle<Child>> getChild();
  $async.Future<$fidl.InterfaceRequest<Child>> getChildRequest();
  $async.Future<void> takeChild($fidl.InterfaceHandle<Child> c);
  $async.Future<void> takeChildRequest($fidl.InterfaceRequest<Child> r);
}

// TODO: Remove ServiceData for non-service
class ParentData implements $fidl.ServiceData<Parent> {
  const ParentData();

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

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

class ParentProxy extends $fidl.AsyncProxy<Parent> implements Parent {
  ParentProxy()
      : super($fidl.AsyncProxyController<Parent>($interfaceName: r'Parent')) {
    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}'));
        ctrl.close();
        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 _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_GetChild_Type.response!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage($message,
              _kParent_GetChild_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;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.response!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage(
              $message,
              _kParent_GetChildRequest_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<$fidl.InterfaceHandle<Child>> getChild() 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(_kParent_GetChild_Ordinal, 0);
    final $completer = $async.Completer<$fidl.InterfaceHandle<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  @override
  $async.Future<$fidl.InterfaceRequest<Child>> getChildRequest() 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(_kParent_GetChildRequest_Ordinal, 0);
    final $completer = $async.Completer<$fidl.InterfaceRequest<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  @override
  $async.Future<void> takeChild($fidl.InterfaceHandle<Child> c) 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(_kParent_TakeChild_Ordinal, 0);
    final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request!;
    $fidl.encodeMessageWithCallback(
        $encoder, _kParent_TakeChild_Type.encodingRequestInlineSize(), () {
      $types[0].encode($encoder, c, $fidl.kMessageHeaderSize, 1);
    });
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  @override
  $async.Future<void> takeChildRequest($fidl.InterfaceRequest<Child> r) 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(_kParent_TakeChildRequest_Ordinal, 0);
    final List<$fidl.MemberType> $types =
        _kParent_TakeChildRequest_Type.request!;
    $fidl.encodeMessageWithCallback(
        $encoder, _kParent_TakeChildRequest_Type.encodingRequestInlineSize(),
        () {
      $types[0].encode($encoder, r, $fidl.kMessageHeaderSize, 1);
    });
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }
}

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

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      case _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kParent_GetChild_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<$fidl.InterfaceHandle<Child>> $future = $fidl
              .decodeMessageWithCallback<
                      $async.Future<$fidl.InterfaceHandle<Child>>>(
                  $message, _kParent_GetChild_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.getChild();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kParent_GetChild_Ordinal, $message.txid);
            final List<$fidl.MemberType> $types =
                _kParent_GetChild_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kParent_GetChild_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;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<$fidl.InterfaceRequest<Child>> $future = $fidl
              .decodeMessageWithCallback<
                      $async.Future<$fidl.InterfaceRequest<Child>>>($message,
                  _kParent_GetChildRequest_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.getChildRequest();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kParent_GetChildRequest_Ordinal, $message.txid);
            final List<$fidl.MemberType> $types =
                _kParent_GetChildRequest_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kParent_GetChildRequest_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;
      case _kParent_TakeChild_Ordinal:
        final String _name = _kParent_TakeChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_TakeChild_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>(
                  $message, _kParent_TakeChild_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.takeChild(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize, 1),
            );
          });
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kParent_TakeChildRequest_Ordinal:
        final String _name = _kParent_TakeChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_TakeChildRequest_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>($message,
                  _kParent_TakeChildRequest_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.takeChildRequest(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize, 1),
            );
          });
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for ParentBinding');
    }
  }
}
