// 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 (v1.0.16), do not edit directly.
// See also: https://pub.dev/packages/pigeon
#import "messages.g.h"
#import <Flutter/Flutter.h>

#if !__has_feature(objc_arc)
#error File requires ARC to be enabled.
#endif

static NSDictionary<NSString *, id> *wrapResult(id result, FlutterError *error) {
  NSDictionary *errorDict = (NSDictionary *)[NSNull null];
  if (error) {
    errorDict = @{
      @"code" : (error.code ? error.code : [NSNull null]),
      @"message" : (error.message ? error.message : [NSNull null]),
      @"details" : (error.details ? error.details : [NSNull null]),
    };
  }
  return @{
    @"result" : (result ? result : [NSNull null]),
    @"error" : errorDict,
  };
}

@interface UserDefaultsApiCodecReader : FlutterStandardReader
@end
@implementation UserDefaultsApiCodecReader
@end

@interface UserDefaultsApiCodecWriter : FlutterStandardWriter
@end
@implementation UserDefaultsApiCodecWriter
@end

@interface UserDefaultsApiCodecReaderWriter : FlutterStandardReaderWriter
@end
@implementation UserDefaultsApiCodecReaderWriter
- (FlutterStandardWriter *)writerWithData:(NSMutableData *)data {
  return [[UserDefaultsApiCodecWriter alloc] initWithData:data];
}
- (FlutterStandardReader *)readerWithData:(NSData *)data {
  return [[UserDefaultsApiCodecReader alloc] initWithData:data];
}
@end

NSObject<FlutterMessageCodec> *UserDefaultsApiGetCodec() {
  static dispatch_once_t s_pred = 0;
  static FlutterStandardMessageCodec *s_sharedObject = nil;
  dispatch_once(&s_pred, ^{
    UserDefaultsApiCodecReaderWriter *readerWriter =
        [[UserDefaultsApiCodecReaderWriter alloc] init];
    s_sharedObject = [FlutterStandardMessageCodec codecWithReaderWriter:readerWriter];
  });
  return s_sharedObject;
}

void UserDefaultsApiSetup(id<FlutterBinaryMessenger> binaryMessenger,
                          NSObject<UserDefaultsApi> *api) {
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.remove"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(removeKey:error:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(removeKey:error:)", api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        NSArray *args = message;
        NSString *arg_key = args[0];
        FlutterError *error;
        [api removeKey:arg_key error:&error];
        callback(wrapResult(nil, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setBool"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(setBoolKey:value:error:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(setBoolKey:value:error:)",
                api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        NSArray *args = message;
        NSString *arg_key = args[0];
        NSNumber *arg_value = args[1];
        FlutterError *error;
        [api setBoolKey:arg_key value:arg_value error:&error];
        callback(wrapResult(nil, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setDouble"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(setDoubleKey:value:error:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(setDoubleKey:value:error:)",
                api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        NSArray *args = message;
        NSString *arg_key = args[0];
        NSNumber *arg_value = args[1];
        FlutterError *error;
        [api setDoubleKey:arg_key value:arg_value error:&error];
        callback(wrapResult(nil, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.setValue"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(setValueKey:value:error:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(setValueKey:value:error:)",
                api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        NSArray *args = message;
        NSString *arg_key = args[0];
        id arg_value = args[1];
        FlutterError *error;
        [api setValueKey:arg_key value:arg_value error:&error];
        callback(wrapResult(nil, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.getAll"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(getAllWithError:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(getAllWithError:)", api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        FlutterError *error;
        NSDictionary<NSString *, id> *output = [api getAllWithError:&error];
        callback(wrapResult(output, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
  {
    FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
        messageChannelWithName:@"dev.flutter.pigeon.UserDefaultsApi.clear"
               binaryMessenger:binaryMessenger
                         codec:UserDefaultsApiGetCodec()];
    if (api) {
      NSCAssert([api respondsToSelector:@selector(clearWithError:)],
                @"UserDefaultsApi api (%@) doesn't respond to @selector(clearWithError:)", api);
      [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) {
        FlutterError *error;
        [api clearWithError:&error];
        callback(wrapResult(nil, error));
      }];
    } else {
      [channel setMessageHandler:nil];
    }
  }
}
