#import "RNZoomVideoSdkSubSession.h"
#import "RCTConvert+RNZoomVideoSdk.h"

@implementation RNZoomVideoSdkSubSession

// Static variables to store SubSession instances
static NSMutableDictionary<NSString *, ZoomVideoSDKSubSessionKit *> *subSessionMap;
static ZoomVideoSDKSubSessionManager *subSessionManager;
static ZoomVideoSDKSubSessionParticipant *subSessionParticipant;
static ZoomVideoSDKSubSessionUserHelpRequestHandler *subSessionUserHelpRequestHandler;

RCT_EXPORT_MODULE();

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

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

// MARK: - Static Storage Methods

+ (void)storeSubSessionManager:(ZoomVideoSDKSubSessionManager *)manager
{
    subSessionManager = manager;
}

+ (void)storeSubSessionParticipant:(ZoomVideoSDKSubSessionParticipant *)participant
{
    subSessionParticipant = participant;
}

+ (void)storeSubSessionUserHelpRequestHandler:(ZoomVideoSDKSubSessionUserHelpRequestHandler *)handler
{
    subSessionUserHelpRequestHandler = handler;
}

+ (void)updateSubSessionKit:(ZoomVideoSDKSubSessionKit *)subSessionKit
{
    if (!subSessionMap) {
        subSessionMap = [NSMutableDictionary dictionary];
    }
    [subSessionMap setObject:subSessionKit forKey:[subSessionKit getSubSessionID]];
}


RCT_EXPORT_METHOD(commitSubSessionList:(NSArray<NSString *> *)subSessionNameList
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (!subSessionNameList || subSessionNameList.count == 0) {
        reject(@"INVALID_PARAMS", @"subSessionNameList cannot be null or empty", nil);
        return;
    }

    ZoomVideoSDKSubSessionHelper *helper = [[ZoomVideoSDK shareInstance] getsubSessionHelper];
    if (!helper) {
        reject(@"SUBSESSION_HELPER_NULL", @"SubSession helper is not available", nil);
        return;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        [helper addSubSessionToPreList:subSessionNameList];
        ZoomVideoSDKError result = [helper commitSubSessionList];
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
    });
}

RCT_EXPORT_METHOD(withdrawSubSessionList:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    ZoomVideoSDKSubSessionHelper *helper = [[ZoomVideoSDK shareInstance] getsubSessionHelper];
    if (!helper) {
        reject(@"SUBSESSION_HELPER_NULL", @"SubSession helper is not available", nil);
        return;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        ZoomVideoSDKError result = [helper withdrawSubSessionList];
        resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
    });
}

RCT_EXPORT_METHOD(getCommittedSubSessionList:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    ZoomVideoSDKSubSessionHelper *helper = [[ZoomVideoSDK shareInstance] getsubSessionHelper];
    if (!helper) {
        reject(@"SUBSESSION_HELPER_NULL", @"SubSession helper is not available", nil);
        return;
    }

    dispatch_async(dispatch_get_main_queue(), ^{
        NSArray<ZoomVideoSDKSubSessionKit *> *kitList = [helper getCommittedSubSessionList];
        resolve([RNZoomVideoSdkSubSession mapSubSessionKitArray:kitList]);
    });
}


RCT_EXPORT_METHOD(startSubSession:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionManager != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionManager startSubSession];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"start_subsession_failed", @"subSessionManager is null", nil);
    }
}

RCT_EXPORT_METHOD(stopSubSession:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionManager != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionManager stopSubSession];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"stop_subsession_failed", @"subSessionManager is null", nil);
    }
}

RCT_EXPORT_METHOD(isSubSessionStarted:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionManager != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            BOOL isStarted = [subSessionManager isSubSessionStarted];
            resolve(@(isStarted));
        });
    } else {
        reject(@"is_subsession_started_failed", @"subSessionManager is null", nil);
    }
}

RCT_EXPORT_METHOD(broadcastMessage:(NSString *)message
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionManager != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionManager broadcastMessage:message];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"broadcast_message_failed", @"subSessionManager is null", nil);
    }
}


RCT_EXPORT_METHOD(returnToMainSession:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionParticipant != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionParticipant returnToMainSession];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"return_to_main_session_failed", @"subSessionParticipant is null", nil);
    }
}

RCT_EXPORT_METHOD(requestForHelp:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionParticipant != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionParticipant requestForHelp];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"request_for_help_failed", @"subSessionParticipant is null", nil);
    }
}


RCT_EXPORT_METHOD(joinSubSession:(NSString *)subSessionID
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (!subSessionID || subSessionID.length == 0) {
        reject(@"INVALID_PARAMS", @"subSessionID cannot be null or empty", nil);
        return;
    }

    if (!subSessionMap) {
        subSessionMap = [NSMutableDictionary dictionary];
    }

    ZoomVideoSDKSubSessionKit *subSessionKit = [subSessionMap objectForKey:subSessionID];
    if (subSessionKit != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionKit joinSubSession];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"join_subsession_failed", @"subSessionKit is null", nil);
    }
}


RCT_EXPORT_METHOD(getRequestUserName:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionUserHelpRequestHandler != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *userName = [subSessionUserHelpRequestHandler getRequestUserName];
            resolve(userName ?: @"");
        });
    } else {
        reject(@"get_request_username_failed", @"subSessionUserHelpRequestHandler is null", nil);
    }
}

RCT_EXPORT_METHOD(getRequestSubSessionName:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionUserHelpRequestHandler != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            NSString *subSessionName = [subSessionUserHelpRequestHandler getRequestSubSessionName];
            resolve(subSessionName ?: @"");
        });
    } else {
        reject(@"get_request_subsession_name_failed", @"subSessionUserHelpRequestHandler is null", nil);
    }
}

RCT_EXPORT_METHOD(ignore:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionUserHelpRequestHandler != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionUserHelpRequestHandler ignore];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"ignore_request_failed", @"subSessionUserHelpRequestHandler is null", nil);
    }
}

RCT_EXPORT_METHOD(joinSubSessionByUserRequest:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject)
{
    if (subSessionUserHelpRequestHandler != nil) {
        dispatch_async(dispatch_get_main_queue(), ^{
            ZoomVideoSDKError result = [subSessionUserHelpRequestHandler joinSubSessionByUserRequest];
            resolve([[RCTConvert ZoomVideoSDKErrorValuesReversed] objectForKey: @(result)]);
        });
    } else {
        reject(@"join_subsession_by_user_request_failed", @"subSessionUserHelpRequestHandler is null", nil);
    }
}

+ (NSDictionary *)mapSubSessionKit:(ZoomVideoSDKSubSessionKit *)subSession
{
    NSMutableDictionary *kitDict = [NSMutableDictionary dictionary];
    [kitDict setObject:subSession.getSubSessionName ?: @"" forKey:@"subSessionName"];
    [kitDict setObject:subSession.getSubSessionID ?: @"" forKey:@"subSessionID"];
    [kitDict setObject:[self mapSubSessionUserArray:[subSession getSubSessionUserList]] forKey:@"subSessionUserList"];

    if (!subSessionMap) {
        subSessionMap = [NSMutableDictionary dictionary];
    }
    [subSessionMap setObject:subSession forKey:[subSession getSubSessionID]];

    return kitDict;
}

+ (NSArray *)mapSubSessionUserArray:(NSArray<ZoomVideoSDKSubSessionUser *> *)userList
{
    NSMutableArray *result = [NSMutableArray array];

    for (ZoomVideoSDKSubSessionUser *user in userList) {
        NSDictionary *userDict = @{
            @"userName": user.getUserName ?: @"",
            @"userGUID": user.getUserGUID ?: @""
        };
        [result addObject:userDict];
    }

    return result;
}

+ (NSArray *)mapSubSessionKitArray:(NSArray<ZoomVideoSDKSubSessionKit *> *)kitList
{
    NSMutableArray *result = [NSMutableArray array];

    for (ZoomVideoSDKSubSessionKit *kit in kitList) {
        NSDictionary * item = [self mapSubSessionKit: kit];
        [result addObject: item];
    }

    return result;
}

@end
