// 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: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


/// const comment #1
///
/// const comment #3
const int c = 4;

enum UnionTag {
  field,
}
/// union comment #1
///
/// union comment #3
class Union extends $fidl.Union {

  const Union.withField(int value)
    : _data = value, tag = UnionTag.field;

  Union._(this.tag, Object data) : _data = data;

  final UnionTag tag;
  final _data;
  int get field {
    if (tag != UnionTag.field) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (tag) {
      case UnionTag.field:
        return 'Union.field($field)';
      default:
        return null;
    }
  }
  /// union comment #1
  ///
  /// union comment #3
  @override
  int get $index => tag.index;

  @override
  Object get $data => _data;

  static Union _ctor(int index, Object data) {
    return new Union._(UnionTag.values[index], data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<Union> kUnion_Type = const $fidl.UnionType<Union>(
  encodedSize: 8,
  members: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int32Type(), offset: 4),
  ],
  ctor: Union._ctor,
);


/// struct comment #1
///
/// struct comment #3
class Struct extends $fidl.Struct {
  const Struct({
    @required this.field,
  });
  Struct.clone(Struct $orig, {
  int field,
  }) : this(
      field: field ?? $orig.field,
    );


  

  Struct._(List<Object> argv)
    : field = argv[0];
  /// struct member comment #1
  ///
  /// struct member comment #3
  final int field;

  @override
  List<Object> get $fields {
    return <Object>[
      field,
    ];
  }

  @override
  String toString() {
    // ignore: prefer_interpolation_to_compose_strings
    return r'Struct' r'(field: ' + field.toString() + r')';
  }

  static Struct _ctor(List<Object> argv) => new Struct._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<Struct> kStruct_Type = const $fidl.StructType<Struct>(
  encodedSize: 4,
  members: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int32Type(), offset: 0),
  ],
  ctor: Struct._ctor,
);


/// table comment #1
///
/// table comment #3
class Table extends $fidl.Table {
  const Table({
    this.field,
  });

  Table._(Map<int, dynamic> argv)
    : field = argv[1];
  /// table field comment #1
  ///
  /// table field comment #3
  final int field;

  @override
  Map<int, dynamic> get $fields {
    return {
    1: field,
    };
  }

  static Table _ctor(Map<int, dynamic> argv) => new Table._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<Table> kTable_Type = const $fidl.TableType<Table>(
  encodedSize: 16,
  members: const <int, $fidl.FidlType>{
    1: const $fidl.Int32Type(),
  },
  ctor: Table._ctor,
);

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


// method: ()
const int _kInterface_Method_Ordinal = 1061382220;
const $fidl.MethodType _kInterface_Method_Type = const $fidl.MethodType(
    request: null,
	response: null,
	name: r"Interface.Method",
  );
/// interface comment #1
///
/// interface comment #3
abstract class Interface extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const InterfaceData();
    /// method comment #1
    ///
    /// method comment #3
    Future<void> method()
      ;
}

class InterfaceData implements $fidl.ServiceData<Interface> {

  const InterfaceData();

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

  @override
  $fidl.AsyncBinding getBinding() {
    return InterfaceBinding();
  }
}
/// interface comment #1
///
/// interface comment #3
class InterfaceProxy extends $fidl.AsyncProxy<Interface>
    implements Interface {
  InterfaceProxy() : super(new $fidl.AsyncProxyController<Interface>($serviceName: null, $interfaceName: r'Interface')) {
    ctrl.onResponse = _handleResponse;

  }

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

  void _handleEvent($fidl.Message $message) {
    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;
    }
  }

  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;
    }
  }
    /// method comment #1
    ///
    /// method comment #3
    @override
    Future<void> method() async {
      if (!ctrl.isBound) {
        return new Future.error(new $fidl.FidlStateException('The proxy is closed.'));
      }

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

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

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


