//
//  ReactLightspeedSDK.m
//  ReactLightspeedSDK
//
//  Created by marc matta on 10/12/16.
//  Copyright © 2016 com.lightspeed. All rights reserved.
//

#import "RCTLSRegistrationCoordinator.h"
#import <LightspeedSDK/LightspeedSDK-Swift.h>
#import "LSUserProfile+RCTNativeModel.h"
#import "LSSingleAchievement+RCTNativeModel.h"
#import "LSBasicUserInfo+RCTNativeModel.h"
#import "LSCountryLanguages+RCTNativeModel.h"
#import <React/RCTUtils.h>

NSString *const RegistrationCoordinatorLogoutEvent = @"UserLoggedOutEvent";

@implementation RCTLSRegistrationCoordinator

RCT_EXPORT_MODULE(LSRegistrationCoordinator);

static LSRegistrationCoordinator *sharedInstance;
+ (LSRegistrationCoordinator *)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [LSRegistrationCoordinator new];
    });

    return sharedInstance;
}

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

- (NSDictionary<NSString *,id> *)constantsToExport {
    return @{
             @"UserLogoutNotification":RegistrationCoordinatorLogoutEvent
             };
}

- (void)startObserving {
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(handleLogoutNotification:)
                                                 name:[LSRegistrationCoordinator UserProfileDeletedNotificationName]
                                               object:nil];
}

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

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

- (void)handleLogoutNotification:(NSNotification *)notification {
    [self sendEventWithName:RegistrationCoordinatorLogoutEvent body:notification.userInfo];
}

+ (BOOL)requiresMainQueueSetup
{
    return YES;
}

RCT_EXPORT_METHOD(loggedInUser:(RCTResponseSenderBlock)callback) {
    NSDictionary *profile = [[LSRegistrationCoordinator loggedInUserProfile] reactNativeRepresentation];
    callback(@[RCTNullIfNil(profile)]);
}

RCT_EXPORT_METHOD(sessionClearedReason:(RCTResponseSenderBlock)callback) {
    callback(@[RCTNullIfNil([LSRegistrationCoordinator sessionClearedReason])]);
}

RCT_EXPORT_METHOD(register:(NSString * _Nonnull)email password:(NSString * _Nonnull)password firstName:(NSString * _Nonnull)firstName lastName:(NSString * _Nonnull)lastName zipCode:(NSString * _Nonnull)zipCode gender:(NSUInteger)gender birthdate:(NSString * _Nonnull)birthdate languageCode:(NSString * _Nonnull)languageCode countryCode:(NSString * _Nonnull)countryCode resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] register:email password:password firstName:firstName lastName:lastName zipCode:zipCode gender:gender birthdate:birthdate languageCode:languageCode countryCode:countryCode completion:^(LSUserProfile * _Nullable profile, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([profile reactNativeRepresentation]);
        }
    }];
}

RCT_EXPORT_METHOD(login:(NSString * _Nonnull)email password:(NSString * _Nonnull)password resolver:(RCTPromiseResolveBlock)resolver rejected:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] login:email password:password completion:^(LSUserProfile * _Nullable profile, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([profile reactNativeRepresentation]);
        }
    }];
}

RCT_EXPORT_METHOD(loginWithSocialProvider:(NSString * _Nonnull)gigyaId provider:(NSString * _Nonnull)provider providerUId:(NSString * _Nonnull)providerUId accessToken:(NSString * _Nonnull)accessToken email:(NSString * _Nonnull)email firstName:(NSString * _Nonnull)firstName lastName:(NSString * _Nonnull)lastName isSiteUID:(BOOL)isSiteUID languageCode:(NSString * _Nonnull)languageCode countryCode:(NSString * _Nonnull)countryCode resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] loginWithSocialProvider:gigyaId provider:provider providerUId:providerUId accessToken:accessToken email:email firstName:firstName lastName:lastName isSiteUID:isSiteUID languageCode:languageCode countryCode:countryCode completion:^(LSUserProfile * _Nullable profile, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([profile reactNativeRepresentation]);
        }
    }];
}

RCT_EXPORT_METHOD(socialLink:(NSString * _Nonnull)gigyaId provider:(NSString * _Nonnull)provider providerUId:(NSString *_Nonnull)providerUId accessToken:(NSString *_Nonnull)accessToken resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] socialLink:gigyaId provider:provider providerUId:providerUId accessToken:accessToken completion:^(LSSingleAchievement * _Nullable achievement, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([achievement reactNativeRepresentation]);
        }
    }];
}

RCT_EXPORT_METHOD(socialUnlink:(NSString * _Nonnull)provider resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] socialUnlink:provider completion:^(BOOL unlinked, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver(@(unlinked));
        }
    }];
}

RCT_EXPORT_METHOD(resetPassword:(NSString * _Nonnull)email resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] resetPassword:email completion:^(id _Nullable response, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([NSNull null]);
        }
    }];
}

RCT_EXPORT_METHOD(logout:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] logout:^(BOOL loggedOut, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver(@(loggedOut));
        }
    }];
}

RCT_EXPORT_METHOD(isEmailRegistered:(NSString* _Nonnull)email resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] isEmailRegistered:email completion:^(LSBasicUserInfo * _Nullable info, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([info reactNativeRepresentation]);
        }
    }];
}

RCT_REMAP_METHOD(getCountryLanguages, withResolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter) {
    [[RCTLSRegistrationCoordinator sharedInstance] getCountryLanguagesWithCompletion:^(LSCountryLanguages * _Nullable response, NSError * _Nullable error) {
        if (error) {
            rejecter([@(error.code) stringValue], error.localizedFailureReason, error);
        }else {
            resolver([response reactNativeRepresentation]);
        }
    }];
}
@end
