// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// WARNING: This file is machine generated by fidlgen.

library fidl_test_name_async;

import 'dart:async';
import 'dart:developer';
import 'dart:typed_data';

import 'package:fidl/fidl.dart' as $fidl;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart';

// These imports improve deduplication by making uses of {fidl.dart},
// {fidl_async.dart} and {fidl.dart, fidl_async.dart} generate equivalent
// packages. In AOT, the dead code will be removed by tree shaking.
// ignore: unused_import
import 'fidl.dart' as $strongly_connect_sync;

// 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: unused_element, avoid_private_typedef_functions
typedef _VoidCallback = void Function();

// ordinalFive: ()
const int _kSwitchingOrdinals_OrdinalFive_Ordinal = 2005164903;
const $fidl.MethodType _kSwitchingOrdinals_OrdinalFive_Type =
    const $fidl.MethodType(
  request: null,
  response: null,
  name: r"SwitchingOrdinals.OrdinalFive",
);
// onlyGeneratedOrdinal: ()
const int _kSwitchingOrdinals_OnlyGeneratedOrdinal_Ordinal = 667506719;
const $fidl.MethodType _kSwitchingOrdinals_OnlyGeneratedOrdinal_Type =
    const $fidl.MethodType(
  request: null,
  response: null,
  name: r"SwitchingOrdinals.OnlyGeneratedOrdinal",
);
// eventOrdinalFifteen:  -> ()
const int _kSwitchingOrdinals_EventOrdinalFifteen_Ordinal = 1467258273;
const $fidl.MethodType _kSwitchingOrdinals_EventOrdinalFifteen_Type =
    const $fidl.MethodType(
  request: null,
  response: null,
  name: r"SwitchingOrdinals.EventOrdinalFifteen",
);
// eventOnlyGeneratedOrdinal:  -> ()
const int _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Ordinal = 2146190926;
const $fidl.MethodType _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type =
    const $fidl.MethodType(
  request: null,
  response: null,
  name: r"SwitchingOrdinals.EventOnlyGeneratedOrdinal",
);

abstract class SwitchingOrdinals extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const SwitchingOrdinalsData();
  Future<void> ordinalFive();
  Future<void> onlyGeneratedOrdinal();
  Stream<void> get eventOrdinalFifteen;
  Stream<void> get eventOnlyGeneratedOrdinal;
}

class SwitchingOrdinalsData implements $fidl.ServiceData<SwitchingOrdinals> {
  const SwitchingOrdinalsData();

  @override
  String getName() {
    return SwitchingOrdinals.$serviceName;
  }

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

class SwitchingOrdinalsProxy extends $fidl.AsyncProxy<SwitchingOrdinals>
    implements SwitchingOrdinals {
  SwitchingOrdinalsProxy()
      : super(new $fidl.AsyncProxyController<SwitchingOrdinals>(
            $serviceName: null, $interfaceName: r'SwitchingOrdinals')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _eventOrdinalFifteenEventStreamController.close();
      _eventOnlyGeneratedOrdinalEventStreamController.close();
    }, onError: (_) {});
  }

  @override
  $fidl.ServiceData get $serviceData => SwitchingOrdinalsData();

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kSwitchingOrdinals_EventOrdinalFifteen_Ordinal:
        final String _name = _kSwitchingOrdinals_EventOrdinalFifteen_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_EventOrdinalFifteen_Type.response;
          $decoder.claimMemory(16);
          _eventOrdinalFifteenEventStreamController.add(null);
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(
              new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Ordinal:
        final String _name =
            _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type.response;
          $decoder.claimMemory(16);
          _eventOnlyGeneratedOrdinalEventStreamController.add(null);
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(
              new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(new $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 Completer $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(new $fidl.FidlError(
            'Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

  @override
  Future<void> ordinalFive() async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException('The proxy is closed.'));
    }

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(_kSwitchingOrdinals_OrdinalFive_Ordinal, 0);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  @override
  Future<void> onlyGeneratedOrdinal() async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException('The proxy is closed.'));
    }

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kSwitchingOrdinals_OnlyGeneratedOrdinal_Ordinal, 0);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _eventOrdinalFifteenEventStreamController =
      new StreamController<void>.broadcast();
  @override
  Stream<void> get eventOrdinalFifteen =>
      _eventOrdinalFifteenEventStreamController.stream;

  final _eventOnlyGeneratedOrdinalEventStreamController =
      new StreamController<void>.broadcast();
  @override
  Stream<void> get eventOnlyGeneratedOrdinal =>
      _eventOnlyGeneratedOrdinalEventStreamController.stream;
}

class SwitchingOrdinalsBinding extends $fidl.AsyncBinding<SwitchingOrdinals> {
  SwitchingOrdinalsBinding() : super(r"SwitchingOrdinals") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.eventOrdinalFifteen != null) {
        $subscriptions.add(impl.eventOrdinalFifteen.listen(($response) {
          final $fidl.Encoder $encoder = new $fidl.Encoder();
          $encoder.encodeMessageHeader(
              _kSwitchingOrdinals_EventOrdinalFifteen_Ordinal, 0);
          $encoder.alloc(16 - $fidl.kMessageHeaderSize);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_EventOrdinalFifteen_Type.response;

          sendMessage($encoder.message);
        }));
      }
      if (impl.eventOnlyGeneratedOrdinal != null) {
        $subscriptions.add(impl.eventOnlyGeneratedOrdinal.listen(($response) {
          final $fidl.Encoder $encoder = new $fidl.Encoder();
          $encoder.encodeMessageHeader(
              _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Ordinal, 0);
          $encoder.alloc(16 - $fidl.kMessageHeaderSize);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_EventOnlyGeneratedOrdinal_Type.response;

          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kSwitchingOrdinals_OrdinalFive_Ordinal:
        final String _name = _kSwitchingOrdinals_OrdinalFive_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_OrdinalFive_Type.request;
          $decoder.claimMemory(16);
          final Future<void> $future = impl.ordinalFive();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kSwitchingOrdinals_OnlyGeneratedOrdinal_Ordinal:
        final String _name = _kSwitchingOrdinals_OnlyGeneratedOrdinal_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSwitchingOrdinals_OnlyGeneratedOrdinal_Type.request;
          $decoder.claimMemory(16);
          final Future<void> $future = impl.onlyGeneratedOrdinal();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw new $fidl.FidlError(
            'Unexpected message name for SwitchingOrdinalsBinding');
    }
  }
}
