#import "RNWechat.h"
#import "FormatConversion.h"
#import "WXImageScale.h"

#define ASSIGN_EMPTY_STRING(assign, string) \
if (string != nil) { \
assign = string; \
} else { \
assign = @""; \
}

//#define YFLog(format, ...) printf("class: < %s:(%d行) > method: %s \n%s\n", [[[NSString stringWithUTF8String:__FILE__] lastPathComponent] UTF8String], __LINE__, __PRETTY_FUNCTION__, [[NSString stringWithFormat:(format), ##__VA_ARGS__] UTF8String] )

#define RNWechatEventName @"RNWechatEvent"

static NSString *const kOpenURLNotification = @"RCTOpenURLNotification";

@implementation RNWechat {
    BOOL _isWXApiRegisteSuccess;
}

RCT_EXPORT_MODULE()

+ (BOOL)requiresMainQueueSetup
{
    return YES;
}

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}


#pragma lifecycle

- (instancetype)init
{
    self = [super init];
    if (self) {
        [[NSNotificationCenter defaultCenter]
         addObserver:self
         selector:@selector(openURL:)
         name:kOpenURLNotification
         object:nil];
    }
    return self;
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}


#pragma 初始化

RCT_REMAP_METHOD(registerApp,
                 appId:(NSString *)anAppId
                 isDebug:(BOOL)isDebug
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    if(![anAppId isEqualToString:@""]) {
        if (isDebug) {
            [WXApi startLogByLevel:WXLogLevelDetail
                          logBlock:^(NSString *log) { NSLog(@"WXApi: %@", log); }];
        }
        _isWXApiRegisteSuccess = [WXApi registerApp:anAppId];
        if (_isWXApiRegisteSuccess) {
            NSLog(@"WXApi register success. appId: %@", anAppId);
        } else {
            NSLog(@"WXApi register failed. appId: %@", anAppId);
        }
    } else {
        _isWXApiRegisteSuccess = NO;
        NSLog(@"There is no appId for WXApi.");
    }
    
    resolve([self getResolveResFromBool:_isWXApiRegisteSuccess]);
}

RCT_REMAP_METHOD(isWXApiRegisteSuccess,
                 isWXApiRegisteSuccessResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:_isWXApiRegisteSuccess]);
}


#pragma 基本信息

RCT_REMAP_METHOD(isWXAppInstalled,
                 isWXAppInstalledResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApi isWXAppInstalled]]);
}

RCT_REMAP_METHOD(isWXAppSupportApi,
                 isWXAppSupportApiResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApi isWXAppSupportApi]]);
}

RCT_REMAP_METHOD(getWXAppInstallUrl,
                 getWXAppInstallUrlResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([WXApi getWXAppInstallUrl]);
}


#pragma 基本操作

RCT_REMAP_METHOD(openWXApp,
                 openWXAppResolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApi openWXApp]]);
}

RCT_REMAP_METHOD(launchMiniProgram,
                 launchMiniProgramWithUserName:(NSString *)anUserName
                 path:(NSString *)aPath
                 miniProgramType:(NSInteger *)aMiniProgramType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApiRequestHandler launchMiniProgramWithUserName:anUserName
                                                                                      path:aPath
                                                                           miniProgramType:(WXMiniProgramType)aMiniProgramType]]);
}


#pragma OAuth2

RCT_REMAP_METHOD(sendAuthRequest,
                 sendAuthRequestScope:(NSString *)aScope
                 state:(NSString *)aState
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendAuthRequestScope:aScope
                                                                            State:aState]]);
}


#pragma Share

RCT_REMAP_METHOD(sendText,
                 sendText:(NSString *)aText
                 sceneType:(NSInteger *)aSceneType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendText:aText
                                                              InScene:(enum WXScene)aSceneType]]);
}

RCT_REMAP_METHOD(sendImage,
                 sendImage:(NSString *)anImageString
                 sceneType:(NSInteger *)aSceneType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    NSData *anImageData = [FormatConversion stringToData:anImageString];
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendImage:anImageData
                                                               InScene:(enum WXScene)aSceneType]]);
}

RCT_REMAP_METHOD(sendMusic,
                 musicUrl:(NSString *)aMusicUrl
                 musicDataUrl:(NSString *)aMusicDataUrl
                 title:(NSString *)aTitle
                 description:(NSString *)aDescription
                 thumbString:(NSString *)aThumbString
                 sceneType:(NSInteger *)aSceneType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    NSData *aThumbData = [FormatConversion stringToData:aThumbString];
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendMusic:aMusicUrl
                                                          musicDataUrl:aMusicDataUrl
                                                                 title:aTitle
                                                           description:aDescription
                                                            thumbImage:aThumbData
                                                               InScene:(enum WXScene)aSceneType]]);
}

RCT_REMAP_METHOD(sendVideo,
                 videoUrl:(NSString *)aVideoUrl
                 title:(NSString *)aTitle
                 description:(NSString *)aDescription
                 thumbString:(NSString *)aThumbString
                 sceneType:(NSInteger *)aSceneType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    NSData *aThumbData = [FormatConversion stringToData:aThumbString];
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendVideo:aVideoUrl
                                                                 title:aTitle
                                                           description:aDescription
                                                            thumbImage:aThumbData
                                                               InScene:(enum WXScene)aSceneType]]);
}

RCT_REMAP_METHOD(sendLink,
                 sendLinkString:(NSString *)aLinkString
                 title:(NSString *)aTitle
                 description:(NSString *)aDescription
                 thumbString:(NSString *)aThumbString
                 sceneType:(NSInteger *)aSceneType
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    NSData *aThumbData = [FormatConversion stringToData:aThumbString];
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendLink:aLinkString
                                                                title:aTitle
                                                          description:aDescription
                                                           thumbImage:aThumbData
                                                              InScene:(enum WXScene)aSceneType]]);
}

RCT_REMAP_METHOD(sendMiniProgram,
                 sendMiniProgramUserName:(NSString *)anUserName
                 miniProgramType:(NSInteger *)aMiniProgramType
                 path:(NSString *)aPath
                 hdThumbString:(NSString *)aHdThumbString
                 title:(NSString *)aTitle
                 description:(NSString *)aDescription
                 webpageUrl:(NSString *)aWebpageUrl
                 thumbString:(NSString *)aThumbString
                 resolver:(RCTPromiseResolveBlock)resolve
                 rejecter:(RCTPromiseRejectBlock)reject)
{
    // 小程序只支持会话分享
    NSData *aThumbData = [FormatConversion stringToData:aThumbString];
    NSData *aHdThumbData = [FormatConversion stringToData:aHdThumbString];
    
    UIImage *thumbImage = [WXImageScale scalingAndCroppingForSize:CGSizeMake(250, 200) withSourceImage:[UIImage imageWithData:aThumbData]];
    UIImage *hdImage = [WXImageScale scalingAndCroppingForSize:CGSizeMake(500, 400) withSourceImage:[UIImage imageWithData:aHdThumbData]];
   
    
    aThumbData = [WXImageScale compressionImageByType:[FormatConversion typeForImageData:aThumbData] withImage:thumbImage];
    aHdThumbData = [WXImageScale compressionImageByType:[FormatConversion typeForImageData:aHdThumbData] withImage:hdImage];
    
//    NSString *decodeStrThumb = [aThumbData base64EncodedStringWithOptions:0];
//    NSString *decodeStrHd = [aHdThumbData base64EncodedStringWithOptions:0];
//
//    decodeStrThumb = [NSString stringWithFormat:@"data:%@;base64,%@",[FormatConversion typeForImageData:aThumbData], decodeStrThumb];
//    decodeStrHd = [NSString stringWithFormat:@"data:%@;base64,%@",[FormatConversion typeForImageData:aHdThumbData], decodeStrHd];
    
//    YFLog(@"dddd----->[aHdThumbData]-----%@", decodeStrHd);
    
    resolve([self getResolveResFromBool:[WXApiRequestHandler sendMiniProgram:anUserName
                                                             miniProgramType:(WXMiniProgramType)aMiniProgramType
                                                                        path:aPath
                                                                hdThumbImage:aHdThumbData
                                                                       title:aTitle
                                                                 description:aDescription
                                                                  webpageUrl:aWebpageUrl
                                                                  thumbImage:aThumbData]]);
}


#pragma WXApiDelegate

// 发送一个sendReq后，收到微信的回应
- (void)onResp:(BaseResp *)resp {
    NSMutableDictionary *body = @{}.mutableCopy;
    body[@"errCode"] = @(resp.errCode);
    ASSIGN_EMPTY_STRING(body[@"errStr"], resp.errStr)
    
    if ([resp isKindOfClass:[SendAuthResp class]]) {
        // 身份认证
        SendAuthResp *authResp = (SendAuthResp *)resp;
        body[@"eventType"] = @"SendAuthResp";
        ASSIGN_EMPTY_STRING(body[@"code"], authResp.code)
        ASSIGN_EMPTY_STRING(body[@"state"], authResp.state)
        ASSIGN_EMPTY_STRING(body[@"lang"], authResp.lang)
        ASSIGN_EMPTY_STRING(body[@"country"], authResp.country)
    } else if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]]) {
        // 启动小程序
        WXLaunchMiniProgramResp *miniProgramResp = (WXLaunchMiniProgramResp *)resp;
        body[@"eventType"] = @"WXLaunchMiniProgramResp";
        ASSIGN_EMPTY_STRING(body[@"extMsg"], miniProgramResp.extMsg);
    } else if ([resp isKindOfClass:[SendMessageToWXResp class]]) {
        // 发送文字、图片、音乐、视频、链接、小程序
        SendMessageToWXResp *messageResp = (SendMessageToWXResp *)resp;
        body[@"eventType"] = @"SendMessageToWXResp";
        ASSIGN_EMPTY_STRING(body[@"lang"], messageResp.lang)
        ASSIGN_EMPTY_STRING(body[@"country"], messageResp.country)
    }
  
    [self sendEvent:body];
}

// 收到一个来自微信的请求，第三方应用程序处理完后调用sendResp向微信发送结果
- (void)onReq:(BaseReq *)req {
    // TODO: 收到微信请求，后续处理 可以自动打开，但是没有参数
    //    if ([req isKindOfClass:[GetMessageFromWXReq class]]) {
    //        GetMessageFromWXReq *getMessageReq = (GetMessageFromWXReq *)req;
    //    } else if ([req isKindOfClass:[ShowMessageFromWXReq class]]) {
    //        ShowMessageFromWXReq *showMessageReq = (ShowMessageFromWXReq *)req;
    //    } else if ([req isKindOfClass:[LaunchFromWXReq class]]) {
    //        LaunchFromWXReq *launchReq = (LaunchFromWXReq *)req;
    //    }
}

- (NSNumber *)getResolveResFromBool:(BOOL)boolValue
{
    return [NSNumber numberWithBool:boolValue];
}


#pragma event

- (NSArray<NSString *> *)supportedEvents
{
    return @[RNWechatEventName];
}

- (void)sendEvent:(id)body {
    [self sendEventWithName:RNWechatEventName body:body];
}


#pragma wxapi handle url

- (BOOL)openURL:(NSNotification *)aNotification
{
    NSURL *aURL = [NSURL URLWithString:[aNotification userInfo][@"url"]];
    return [WXApi handleOpenURL:aURL delegate:self];
}

@end
