//
//  GCDTimer.m
//  Temperature
//
//  Created by RD on 2023/1/10.
//

#import "GCDTimer.h"

typedef enum : NSUInteger {
    Status_Running,
    Status_Pause,
    Status_Cancle,
} TimerStatus;

@interface GCDTimer ()

@property (nonatomic, strong) dispatch_source_t gcdTimer;
@property (nonatomic, assign) TimerStatus currentStatus;
@property (nonatomic, assign) NSTimeInterval interval;
@end

@implementation GCDTimer

- (void)scheduledTimerWithTimeInterval:(NSTimeInterval)interval afterTime:(NSTimeInterval)afterTime repeats:(BOOL)repeats block:(void (^)(void))block  {
    
    self.interval = interval;
    __weak typeof(self) wself = self;
    
    /** 创建定时器对象 dispatch_source_create
    * para1: DISPATCH_SOURCE_TYPE_TIMER 为定时器类型
    * para2-3: 中间两个参数对定时器无用
    * para4: queue  最后为在什么调度队列中使用
    */
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    self.gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    /** 设置定时器 dispatch_source_set_timer
    * para1: timer 定时器
    * para2: when 任务开始时间
    * para3: interval 任务的间隔
    * para4: 可接受的误差时间，设置0即不允许出现误差
    * Tips: 单位均为纳秒
    */
    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, afterTime * NSEC_PER_SEC);
    
    dispatch_source_set_timer(self.gcdTimer, when, interval * NSEC_PER_SEC, 1);
    dispatch_source_set_event_handler(self.gcdTimer, ^{
        if (!repeats) {
            dispatch_source_cancel(wself.gcdTimer);
        }
        block();
    });
    dispatch_resume(self.gcdTimer);
    self.currentStatus = Status_Running;
}

// 暂停
- (void)pauseTimer {
    if (self.currentStatus == Status_Running && self.gcdTimer) {
        dispatch_suspend(self.gcdTimer);
        self.currentStatus = Status_Pause;
    }
}

// 开始
- (void)resumeTimer {
    if (self.currentStatus == Status_Pause && self.gcdTimer) {
        dispatch_resume(self.gcdTimer);
        self.currentStatus = Status_Running;
    }
}

// 重新开始
- (void)restartTimer{
    [self pauseTimer];
    
    // *秒后重新开始执行
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_interval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self resumeTimer];
    });
}

// 取消
- (void)stopTimer {
    if (self.gcdTimer) {
        
        // 暂停的时候不能直接取消
        if (self.currentStatus == Status_Pause){
            [self resumeTimer];
        }
        
        dispatch_source_cancel(self.gcdTimer);
        self.currentStatus = Status_Cancle;
        self.gcdTimer = nil;
    }
}

@end
