// 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 (v3.2.5), 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, unnecessary_import
// ignore_for_file: avoid_relative_lib_imports
import 'dart:async';
import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List;
import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer;
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

// ignore: directives_ordering
import 'package:file_selector_windows/src/messages.g.dart';

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

  @override
  Object? readValueOfType(int type, ReadBuffer buffer) {
    switch (type) {
      case 128:
        return SelectionOptions.decode(readValue(buffer)!);

      case 129:
        return TypeGroup.decode(readValue(buffer)!);

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

abstract class TestFileSelectorApi {
  static const MessageCodec<Object?> codec = _TestFileSelectorApiCodec();

  List<String?> showOpenDialog(SelectionOptions options,
      String? initialDirectory, String? confirmButtonText);
  List<String?> showSaveDialog(
      SelectionOptions options,
      String? initialDirectory,
      String? suggestedName,
      String? confirmButtonText);
  static void setup(TestFileSelectorApi? api,
      {BinaryMessenger? binaryMessenger}) {
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.FileSelectorApi.showOpenDialog', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.FileSelectorApi.showOpenDialog was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final SelectionOptions? arg_options = (args[0] as SelectionOptions?);
          assert(arg_options != null,
              'Argument for dev.flutter.pigeon.FileSelectorApi.showOpenDialog was null, expected non-null SelectionOptions.');
          final String? arg_initialDirectory = (args[1] as String?);
          final String? arg_confirmButtonText = (args[2] as String?);
          final List<String?> output = api.showOpenDialog(
              arg_options!, arg_initialDirectory, arg_confirmButtonText);
          return <Object?, Object?>{'result': output};
        });
      }
    }
    {
      final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
          'dev.flutter.pigeon.FileSelectorApi.showSaveDialog', codec,
          binaryMessenger: binaryMessenger);
      if (api == null) {
        channel.setMockMessageHandler(null);
      } else {
        channel.setMockMessageHandler((Object? message) async {
          assert(message != null,
              'Argument for dev.flutter.pigeon.FileSelectorApi.showSaveDialog was null.');
          final List<Object?> args = (message as List<Object?>?)!;
          final SelectionOptions? arg_options = (args[0] as SelectionOptions?);
          assert(arg_options != null,
              'Argument for dev.flutter.pigeon.FileSelectorApi.showSaveDialog was null, expected non-null SelectionOptions.');
          final String? arg_initialDirectory = (args[1] as String?);
          final String? arg_suggestedName = (args[2] as String?);
          final String? arg_confirmButtonText = (args[3] as String?);
          final List<String?> output = api.showSaveDialog(arg_options!,
              arg_initialDirectory, arg_suggestedName, arg_confirmButtonText);
          return <Object?, Object?>{'result': output};
        });
      }
    }
  }
}
