// 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:developer';
import 'dart:typed_data';

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

// 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._(UnionTag tag, Object data)
      : _tag = tag,
        _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 r'Union.field($field)';
      default:
        return null;
    }
  }

  /// union comment #1
  ///
  /// union comment #3

  UnionTag get $tag => _tag;
  // TODO: remove, see: FIDL-587
  UnionTag get tag => _tag;

  @override
  int get $index => _tag.index;

  @override
  Object get $data => _data;

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

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<Union> kUnion_Type = $fidl.UnionType<Union>(
  encodedSize: 8,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $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) => Struct._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<Struct> kStruct_Type = $fidl.StructType<Struct>(
  encodedSize: 4,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $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) => Table._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<Table> kTable_Type = $fidl.TableType<Table>(
  encodedSize: 16,
  members: <int, $fidl.FidlType>{
    1: $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 = $fidl.MethodType(
  request: null,
  response: null,
  name: r"Interface.Method",
);

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $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 = $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 = $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 = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kInterface_Method_Ordinal:
        final String _name = _kInterface_Method_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kInterface_Method_Type.request;
          $decoder.claimMemory(16);
          impl.method();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for InterfaceBinding');
    }
  }
}
