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

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_async.dart' as $strongly_connect_async;

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


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

abstract class Interface {
  static const String $serviceName = null;
  void method();
}


// method: ()
const int _kInterface_Method_Ordinal = 1061382220;
const $fidl.MethodType _kInterface_Method_Type = const $fidl.MethodType(
    request: null,
	response: null,
	name: r"Interface.Method",
  );



class InterfaceProxy extends $fidl.Proxy<Interface>
    implements Interface {

  InterfaceProxy() : super(new $fidl.ProxyController<Interface>($serviceName: null, $interfaceName: r'Interface')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }
  @override
  void method() {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

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

class InterfaceBinding extends $fidl.Binding<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);
          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');
    }
  }
}


