// Copyright © 2022 BytePlusRTC All rights reserved.
// SPDX-License-Identifier: MIT

//
//  react-native-rtc
//

#import <Foundation/Foundation.h>
#import "RTCHeader.h"
#import <VertcHelper.h>

@interface VertcHelper ()
@property (nonatomic, strong) NSMutableDictionary *timerList;
@property (nonatomic, strong) NSRecursiveLock *lock;
@end
#pragma mark - Helper
@implementation VertcHelper

+ (instancetype) getInstance {
    static VertcHelper *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[VertcHelper alloc] init];
    });
    return instance;
}

- (instancetype)init {
    if (self = [super init]) {
        self.timerList = [NSMutableDictionary dictionary];
        self.lock = [[NSRecursiveLock alloc] init];
    }
    return self;
}

+ (bool)isUnionLiveModeEnable {
    #ifdef ENABLE_UNION_FOR_RTC_WITH_LIVE
    return true;
    #endif
    return false;
}

- (void)onStreamPushEvent:(ByteRTCSingleStreamPushEvent)event
                   taskId:(NSString *_Nonnull)taskID
                    error:(NSInteger)errorCode {
    NSLog(@"startPushSingleStreamToCDN: event=%ld, taskID=%@, error=%ld", (long)event, taskID, (long)errorCode);
}

- (int)invokeStartPushSingleStreamToCDN:(ByteRTCVideo *)rtc taskId:(NSString *_Nonnull)taskID singleStream:(ByteRTCPushSingleStreamParam *_Nonnull)singleStream {
    // Compatible live rtc version.
    if ([singleStream respondsToSelector:NSSelectorFromString(@"setPushType:")]) {
        // Can only use 1 magic number.
        [singleStream setValue:@(1) forKey:@"pushType"];
    }
    singleStream.isScreen = singleStream.isScreen || false;
    int res = [rtc startPushSingleStreamToCDN:taskID singleStream:singleStream observer:self];
    return res;
}

- (int)invokeSetAudioScene:(ByteRTCVideo *)rtc scene:(ByteRTCAudioSceneType)scene {
    int res = [rtc setAudioScene:scene];
    return res;
}

- (void)schedualTimerWithIdentifier:(NSString *)name
                           interval:(NSTimeInterval)interval
                              queue:(dispatch_queue_t)queue
                            repeats:(BOOL)repeats
                             action:(dispatch_block_t)action {
    if (!name || name.length == 0 || !action) {
        return;
    }
    [_lock lock];
    if (!queue) {
        queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    }
    
    dispatch_source_t timer = [self.timerList objectForKey:name];
    if (!timer) {
        timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
        dispatch_resume(timer);
        [self.timerList setValue:timer forKey:name];
    }
    
    dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, 0.01 * NSEC_PER_SEC);
    __weak __typeof(self)weakSelf = self;
    dispatch_source_set_event_handler(timer, ^{
        action();
        __strong __typeof(weakSelf)self = weakSelf;
        if (!repeats) {
            [self cancelTimerWithName:name];
        }
    });
    [_lock unlock];
}

- (void)cancelTimerWithName:(NSString *)name {
    [_lock lock];
    if (name == nil) {
        [_lock unlock];
        return;
    }
    dispatch_source_t timer = [self.timerList objectForKey:name];
    if (timer) {
        [self.timerList removeObjectForKey:name];
        dispatch_source_cancel(timer);
    }
    [_lock unlock];
}

- (void)cancelAllTimers {
    [_lock lock];
    for (dispatch_source_t timer in self.timerList) {
        dispatch_source_cancel(timer);
    }
    [self.timerList removeAllObjects];
    [_lock unlock];
}
@end

