// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Autogenerated from Pigeon (v4.2.9), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import
import 'dart:async';
import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List;

import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer;
import 'package:flutter/services.dart';

class Everything {
  Everything({
    this.aBool,
    this.anInt,
    this.aDouble,
    this.aString,
    this.aByteArray,
    this.a4ByteArray,
    this.a8ByteArray,
    this.aFloatArray,
    this.aList,
    this.aMap,
    this.nestedList,
    this.mapWithAnnotations,
    this.mapWithObject,
  });

  bool? aBool;

  int? anInt;

  double? aDouble;

  String? aString;

  Uint8List? aByteArray;

  Int32List? a4ByteArray;

  Int64List? a8ByteArray;

  Float64List? aFloatArray;

  List<Object?>? aList;

  Map<Object?, Object?>? aMap;

  List<List<bool?>?>? nestedList;

  Map<String?, String?>? mapWithAnnotations;

  Map<String?, Object?>? mapWithObject;

  Object encode() {
    final List<Object?> pigeonList = <Object?>[];
    pigeonList.add(aBool);
    pigeonList.add(anInt);
    pigeonList.add(aDouble);
    pigeonList.add(aString);
    pigeonList.add(aByteArray);
    pigeonList.add(a4ByteArray);
    pigeonList.add(a8ByteArray);
    pigeonList.add(aFloatArray);
    pigeonList.add(aList);
    pigeonList.add(aMap);
    pigeonList.add(nestedList);
    pigeonList.add(mapWithAnnotations);
    pigeonList.add(mapWithObject);
    return pigeonList;
  }

  static Everything decode(Object result) {
    result as List<Object?>;
    return Everything(
      aBool: result[0] as bool?,
      anInt: result[1] as int?,
      aDouble: result[2] as double?,
      aString: result[3] as String?,
      aByteArray: result[4] as Uint8List?,
      a4ByteArray: result[5] as Int32List?,
      a8ByteArray: result[6] as Int64List?,
      aFloatArray: result[7] as Float64List?,
      aList: result[8] as List<Object?>?,
      aMap: result[9] as Map<Object?, Object?>?,
      nestedList: (result[10] as List<Object?>?)?.cast<List<bool?>?>(),
      mapWithAnnotations:
          (result[11] as Map<Object?, Object?>?)?.cast<String?, String?>(),
      mapWithObject:
          (result[12] as Map<Object?, Object?>?)?.cast<String?, Object?>(),
    );
  }
}

class _HostEverythingCodec extends StandardMessageCodec {
  const _HostEverythingCodec();
  @override
  void writeValue(WriteBuffer buffer, Object? value) {
    if (value is Everything) {
      buffer.putUint8(128);
      writeValue(buffer, value.encode());
    } else {
      super.writeValue(buffer, value);
    }
  }

  @override
  Object? readValueOfType(int type, ReadBuffer buffer) {
    switch (type) {
      case 128:
        return Everything.decode(readValue(buffer)! as List<Object?>);

      default:
        return super.readValueOfType(type, buffer);
    }
  }
}

class HostEverything {
  /// Constructor for [HostEverything].  The [binaryMessenger] named argument is
  /// available for dependency injection.  If it is left null, the default
  /// BinaryMessenger will be used which routes to the host platform.
  HostEverything({BinaryMessenger? binaryMessenger})
      : _binaryMessenger = binaryMessenger;
  final BinaryMessenger? _binaryMessenger;

  static const MessageCodec<Object?> codec = _HostEverythingCodec();

  Future<Everything> giveMeEverything() async {
    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
        'dev.flutter.pigeon.HostEverything.giveMeEverything', codec,
        binaryMessenger: _binaryMessenger);
    final List<Object?>? replyList = await channel.send(null) as List<Object?>?;
    if (replyList == null) {
      throw PlatformException(
        code: 'channel-error',
        message: 'Unable to establish connection on channel.',
      );
    } else if (replyList.length > 1) {
      throw PlatformException(
        code: (replyList[0] as String?)!,
        message: replyList[1] as String?,
        details: replyList[2],
      );
    } else if (replyList[0] == null) {
      throw PlatformException(
        code: 'null-error',
        message: 'Host platform returned null value for non-null return value.',
      );
    } else {
      return (replyList[0] as Everything?)!;
    }
  }

  Future<Everything> echo(Everything arg_everything) async {
    final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
        'dev.flutter.pigeon.HostEverything.echo', codec,
        binaryMessenger: _binaryMessenger);
    final List<Object?>? replyList =
        await channel.send(<Object?>[arg_everything]) as List<Object?>?;
    if (replyList == null) {
      throw PlatformException(
        code: 'channel-error',
        message: 'Unable to establish connection on channel.',
      );
    } else if (replyList.length > 1) {
      throw PlatformException(
        code: (replyList[0] as String?)!,
        message: replyList[1] as String?,
        details: replyList[2],
      );
    } else if (replyList[0] == null) {
      throw PlatformException(
        code: 'null-error',
        message: 'Host platform returned null value for non-null return value.',
      );
    } else {
      return (replyList[0] as Everything?)!;
    }
  }
}

class _FlutterEverythingCodec extends StandardMessageCodec {
  const _FlutterEverythingCodec();
  @override
  void writeValue(WriteBuffer buffer, Object? value) {
    if (value is Everything) {
      buffer.putUint8(128);
      writeValue(buffer, value.encode());
    } else {
      super.writeValue(buffer, value);
    }
  }

  @override
  Object? readValueOfType(int type, ReadBuffer buffer) {
    switch (type) {
      case 128:
        return Everything.decode(readValue(buffer)! as List<Object?>);

      default:
        return super.readValueOfType(type, buffer);
    }
  }
}

abstract class FlutterEverything {
  static const MessageCodec<Object?> codec = _FlutterEverythingCodec();

  Everything giveMeEverything();

  Everything echo(Everything everything);

  static void setup(FlutterEverything? api,
      {BinaryMessenger? binaryMessenger}) {
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.FlutterEverything.giveMeEverything', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMessageHandler(null);
      } else {
        channel.setMessageHandler((Object? message) async {
          // ignore message
          final Everything output = api.giveMeEverything();
          return output;
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.FlutterEverything.echo', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMessageHandler(null);
      } else {
        channel.setMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.FlutterEverything.echo was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final Everything? arg_everything = (args[0] as Everything?);
          assert(arg_everything != null,
              'Argument for dev.flutter.pigeon.FlutterEverything.echo was null, expected non-null Everything.');
          final Everything output = api.echo(arg_everything!);
          return output;
        });
      }
    }
  }
}
