//
//  NvDouyinEditViewController.m
//  SDKDemo
//
//  Created by shizhouhu on 2018/8/31.
 //
//

#import "NvDouyinEditViewController.h"
#import "NvDouyinEditView.h"
#import "NvUtils.h"
#import "NvTimelineUtils.h"
#import "NvTimelineFilterUtils.h"
#import "NvTimelineDataModel.h"
#import "NvFileConvert.h"
#import "NvsTimelineVideoFx.h"
#import "NvRecordingInfo.h"
#import "NvsVideoClip.h"
#import "NvCompileViewController.h"
#import "NvTipsView.h"
#import "NvSDKUtils.h"

typedef NS_ENUM(NSUInteger, Type) {
    None,
    PlayRevert,
    Repeat,
    Slow,
};

@interface NvDouyinEditViewController () <NvsStreamingContextDelegate, NvDouyinEditViewDelegate, NvCompileViewControllerDelegate>

@property (nonatomic, strong) NvsTimeline *timeline;
@property (nonatomic, strong) NvFileConvert *fileConvert;

//是否是长按添加滤镜的状态
@property (nonatomic, assign) BOOL isAddFx;

//用于记录每次添加录制的数据
@property (nonatomic, strong) NSMutableArray *fxInfoArray;
//去掉重复的数据
@property (nonatomic, strong) NSMutableArray *fxNewArray;
//去掉重复的倒放数据
@property (nonatomic, strong) NSMutableArray *fxRevertArray;

//转码是否完成
@property (atomic, assign) BOOL convertFinish;
//是否正在动画
@property (atomic, assign) BOOL isAnimation;

//是否是时间特效
@property (atomic, assign) BOOL isTimeFx;
//当前正在播放的位置
@property (atomic, assign) int64_t currentPlayTime;

@property (assign, nonatomic) Type type;//当前转码时的实际状态
@property (assign, nonatomic) Type currentSelectType;//当前选择的状态

@property (nonnull, strong) NSString *compileFilePath;

@end

@implementation NvDouyinEditViewController {
    NvDouyinEditView *contentView;
    NvsStreamingContext *context;
    NvTimeFilterInfoModel *currentFilterModel;
}

- (void)dealloc {
    [self.fileConvert cancel];
    self.fileConvert = nil;
    NSLog(@"%s",__func__);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:[self rightNavigationBarItemView]];
    self.fxInfoArray = [NSMutableArray array];
    
    //为倒放转码
    [self convert];
    self.view.backgroundColor = [UIColor nv_colorWithHexRGB:@"#242728"];
    contentView = [[NvDouyinEditView alloc] initWithFrame:CGRectMake(0, 0, SCREANWIDTH, SCREANHEIGHT - NV_STATUSBARHEIGHT - 44)];
    contentView.delegate = self;
    [self.view addSubview:contentView];
    contentView.revertBtn.hidden = YES;
    
    context = [NvSDKUtils getSDKContext];
    self.timeline = [NvTimelineUtils createTimeline:NvEditMode9v16];
    [self addClips:self.videoPathArray toTimeline:self.timeline];
    
    if (![context connectTimeline:self.timeline withLiveWindow:contentView.getLiveWindow]) {
        NSLog(@"连接时间线失败");
    }
    
    context.delegate = self;
    [NvTimelineUtils seekTimeline:self.timeline atTime:0];
    
    [contentView setupEffectWrapper:[NvTimelineUtils getThumbnailSequenceDescArray:self.timeline] duration:self.timeline.duration];
    [contentView setupTimelineEditor:[NvTimelineUtils getThumbnailSequenceDescArray:self.timeline] duration:self.timeline.duration];
    contentView.delegate = self;
    
    [self prefersStatusBarHidden];
    [self performSelector:@selector(setNeedsStatusBarAppearanceUpdate)];
    
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:NO];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (UIView *)leftNavigationBarItemView {
    UIButton *back = [UIButton nv_buttonWithTitle:nil textColor:nil fontSize:-1 image:[NvUtils imageWithName:@"Nvback"]];
    back.frame = CGRectMake(0, 0, 30, 44);
    back.imageEdgeInsets = UIEdgeInsetsMake(0, -15*SCREANSCALE, 0, 0);
    __weak typeof(self)weakSelf = self;
    [back nv_BtnClickHandler:^{
        [weakSelf.navigationController popViewControllerAnimated:YES];
    }];
    return back;
}
#pragma mark 生成视频
- (UIView *)rightNavigationBarItemView {
    UIButton *compile = [UIButton nv_buttonWithTitle:@"生成" textColor:[UIColor nv_colorWithHexARGB:@"#FF4A90E2"] fontSize:18];
    compile.frame = CGRectMake(SCREANWIDTH-50*SCREANSCALE, 0, 44, 44);
    __weak typeof(self)weakSelf = self;
    [compile nv_BtnClickHandler:^{
        [weakSelf compileTimeline:weakSelf.timeline];
    }];
    return compile;
}

- (void)compileTimeline:(NvsTimeline *)timeline {
    _compileFilePath = [VIDEO_PATH(@"Compile") stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.mp4", [NvUtils currentDateAndTime]]];
    NvCompileViewController *compileViewController = [NvCompileViewController new];
    compileViewController.delegate = self;
    compileViewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
    [self presentViewController:compileViewController animated:NO completion:nil];
    [compileViewController compileTimeline:_timeline outputPath:_compileFilePath];
    
}

- (void)compileFinished:(BOOL)needDelete {
    [context connectTimeline:self.timeline withLiveWindow:contentView.getLiveWindow];
    context.delegate = self;
    if (needDelete) {
        [[NSFileManager defaultManager] removeItemAtPath:_compileFilePath error:nil];
    } else {
        UISaveVideoAtPathToSavedPhotosAlbum(_compileFilePath, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);
    }
}

//保存相册的回调
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
    NvTipsView *tip = [[NvTipsView alloc]initWithFrame:self.view.frame withTitle:@"保存成功！" withColor:[UIColor nv_colorWithHexRGB:@"#4D4F51"] withCenter:NO];
    [self.view addSubview:tip];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [tip removeFromSuperview];
    });
    
}
#pragma mark 添加clip
- (void)addClips:(NSArray <NvRecordingInfo *>*)clips toTimeline:(NvsTimeline *)timeline {
    NvsVideoTrack *videoTrack = [timeline getVideoTrackByIndex:0];
    NvsAudioTrack *audioTrack = [timeline getAudioTrackByIndex:0];
    [videoTrack setVolumeGain:0 rightVolumeGain:0];
    for (NvRecordingInfo *info in clips) {
        NvsVideoClip *clip;
        if (info.asset!=nil) {
            clip = [videoTrack appendClip:info.asset.localIdentifier trimIn:info.trimIn trimOut:info.trimOut];
            [clip setExtraVideoRotation:info.rotaion];
        } else {
            if (info.recordingPath) {
                clip = [videoTrack appendClip:info.recordingPath];
                [clip setExtraVideoRotation:info.rotaion];
            } else {
                clip = [videoTrack appendClip:info.convertPath];
                [clip setExtraVideoRotation:info.rotaion];
            }
        }
        [clip changeSpeed:info.speed];
    }
    
    for (int i = 0; i < videoTrack.clipCount-1; i++) {
        [videoTrack setBuiltinTransition:i withName:NULL];
    }

    int64_t audioDuration = audioTrack.duration;
    if (self.musicPath) {
        while (audioDuration < videoTrack.duration) {
            [audioTrack appendClip:self.musicPath trimIn:self.trimIn trimOut:self.trimOut];
            audioDuration = audioTrack.duration;
        }
    }
    
}

// 定位某一时间戳的图像
- (void)seekTimeline:(int64_t)postion {
    int flag = 0;
    flag = NvsStreamingEngineSeekFlag_ShowCaptionPoster | NvsStreamingEngineSeekFlag_ShowAnimatedStickerPoster;
    if (![[NvSDKUtils getSDKContext] seekTimeline:self.timeline timestamp:postion videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize flags:flag])
        NSLog(@"定位时间线失败！");
    NSLog(@"seekTime:%lld",postion);
}

- (void)updateColorBarView:(NSMutableArray *)fxNewArray {
    [contentView.effectWrapper.colorBarView clearCurrentArray];
    
    for (int i = 0; i < fxNewArray.count; i++) {
        NvTimeFilterInfoModel *info = [fxNewArray objectAtIndex:i];
        int64_t inPoint = info.inPoint;
        int64_t outPoint = info.outPoint;
        NSString *fxUUID = info.name;
        if (!fxUUID) {
            fxUUID = info.name;
        }
        [contentView.effectWrapper.colorBarView addToCurrentArray:fxUUID inPoint:inPoint outPoint:outPoint];
    }

    [contentView.effectWrapper.colorBarView updateSubviewsByCurrentArray:NO withColor:nil];
}

#pragma mark NvDouyinEditViewDelegate
- (void)cancelBtnClicked {
    [self.navigationController popViewControllerAnimated:YES];
}

#pragma mark 开始滤镜
- (void)startFilter:(NSString *)filterId {
    //设置颜色控件开始绘制的位置
    int64_t currentTime = [context getTimelineCurrentPosition:self.timeline];
    if (self.type == PlayRevert) {
        contentView.effectWrapper.colorBarView.timelineStartPosition = self.timeline.duration - currentTime;
    } else {
        contentView.effectWrapper.colorBarView.timelineStartPosition = currentTime;
    }
    float posX = contentView.effectWrapper.sliderView.value * SCREANWIDTH;
    NSString *color = [NvSDKUtils getEffectColor:filterId];
    [contentView.effectWrapper.colorBarView addBar:posX width:0 color:color fxUuid:filterId];
    
    NvTimeFilterInfoModel *filterModel = NvTimeFilterInfoModel.new;
    filterModel.name = filterId;
    filterModel.inPoint = [context getTimelineCurrentPosition:self.timeline];
    filterModel.outPoint = self.timeline.duration - filterModel.inPoint;
    currentFilterModel = filterModel;
    
    if (self.type == PlayRevert) {//如果是倒放
        self.isAddFx = YES;
        
        //先移除所有特效
        [self removeAllTimelineFx:self.timeline];
        //重新添加特效
        [self addFx:self.timeline withPackgeId:filterId];
        
        //播放
        [context playbackTimeline:self.timeline startTime:currentTime endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
    } else {
        self.isAddFx = YES;
        //先移除所有特效
        [self removeAllTimelineFx:self.timeline];
        //重新添加特效
        [self addFx:self.timeline withPackgeId:filterId];
        
        [NvTimelineUtils playTimeline:self.timeline atTime:[context getTimelineCurrentPosition:self.timeline]];
    }
}

#pragma mark 结束滤镜
- (void)stopFilter {
    [context stop];
    contentView.revertBtn.hidden = NO;
    self.isAddFx = NO;
    currentFilterModel.outPoint = [context getTimelineCurrentPosition:self.timeline];
    //转换model
    //生成新的数组过滤后的不重叠的
    NvTimeFilterInfoModel *model = [self revertModel:currentFilterModel timeline:self.timeline];
    
    if (self.type == PlayRevert) {
        //移除所有特效根据记录数据添加特效
        [self removeAllTimelineFx:self.timeline];
        //生成新的数组过滤后的不重叠的
        self.fxNewArray = [self filterModele:self.fxNewArray withNewModel:model];
        self.fxRevertArray = [self filterModele:self.fxRevertArray withNewModel:currentFilterModel];
        //添加fx
        [self addFxsWithNewArray:self.fxRevertArray withTimeline:self.timeline];
        
    } else {
        //移除所有特效根据记录数据添加特效
        [self removeAllTimelineFx:self.timeline];
        //生成新的数组过滤后的不重叠的
        self.fxNewArray = [self filterModele:self.fxNewArray withNewModel:currentFilterModel];
        self.fxRevertArray = [self filterModele:self.fxRevertArray withNewModel:model];
        //添加fx
        [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
        
    }

    //记录历史操作
    [self.fxInfoArray addObject:[[NSMutableArray alloc] initWithArray:self.fxNewArray copyItems:YES]];
    //更新colorbarUI
    [self updateColorBarView:self.fxNewArray];
}

#pragma mark 撤销滤镜按钮点击
- (void)revertClick {
    if (self.fxInfoArray.count == 1) {
        NSMutableArray *arr = self.fxInfoArray.firstObject;
        NvTimeFilterInfoModel *model = arr.firstObject;
        int64_t seekTime = model.inPoint;
        if (self.type == PlayRevert) {
            seekTime = model.outPoint;
            [self seekTimeline:self.timeline.duration - seekTime];
            contentView.effectWrapper.sliderView.value = (float)seekTime/self.timeline.duration;
        } else {
            [self seekTimeline:seekTime];
            contentView.effectWrapper.sliderView.value = (float)seekTime/self.timeline.duration;
        }
    }
    [self.fxInfoArray removeLastObject];
    self.fxNewArray = self.fxInfoArray.lastObject;
    self.fxRevertArray = [self revertModelWith:self.fxNewArray withTimeline:self.timeline];
    //移除所有特效根据记录数据添加特效
    [self removeAllTimelineFx:self.timeline];
    //添加fx
    if (self.type == PlayRevert) {
        [self addFxsWithNewArray:self.fxRevertArray withTimeline:self.timeline];
    } else {
        [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
    }
    //更新控件
    [self updateColorBarView:self.fxNewArray];
    
    if (self.fxInfoArray.count > 0) {
        int64_t seekTime = [[contentView.effectWrapper.colorBarView.currentTimelineEndPositionArray lastObject] longLongValue];
        if (self.type == PlayRevert) {
            NvTimeFilterInfoModel *model = [self.fxNewArray lastObject];
            seekTime = model.inPoint;
            [self seekTimeline:self.timeline.duration - seekTime];
            contentView.effectWrapper.sliderView.value = (float)seekTime/self.timeline.duration;
        } else {
            [self seekTimeline:seekTime];
            contentView.effectWrapper.sliderView.value = (float)seekTime/self.timeline.duration;
        }
    } else {
        contentView.revertBtn.hidden = YES;
    }

}
#pragma mark 滑动seek
- (void)sliderValueChanged:(UISlider *)slider {
    if (self.type == PlayRevert) {
        [self seekTimeline:(1-slider.value) * self.timeline.duration];
    } else {
        [self seekTimeline:slider.value * self.timeline.duration];
    }
}

#pragma mark 时间特效
- (void)timeFxClick:(NSIndexPath*)indexPath {
    NSUInteger index = indexPath.item;
    [context stop];
    if (index == 0) {//无
        self.type = None;
        self.currentSelectType = None;
        [self none];
    } else if (index == 1) {//时光倒流
        //判断转码是否完成
        self.currentSelectType = PlayRevert;
        [self playRevert];
    } else if (index == 2) {//反复
        self.currentSelectType = Repeat;
        [self repeat];
    } else if (index == 3) {//慢动作
        self.currentSelectType = Slow;
        [self slowMotion];
    }
}
#pragma mark 时间特效
- (void)playRevert {
    if (self.convertFinish) {
        [contentView.timelineEditor showCoverView:YES];
        contentView.repeatView.hidden = YES;
        //rebuild倒放timeline
        [self rebuildTimeline:self.timeline isRevert:YES];
        self.type = PlayRevert;
        NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
        for (int i = 0; i < track.clipCount; i++) {
            [track setBuiltinTransition:i withName:NULL];
        }
        [self addFxsWithNewArray:self.fxRevertArray withTimeline:self.timeline];
        
        //播放
        [context playbackTimeline:self.timeline startTime:0 endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
    }
}

- (void)repeat {
    if (self.convertFinish) {
        [self rebuildTimeline:self.timeline isRevert:NO];
        [contentView.timelineEditor showCoverView:NO];
        contentView.repeatView.hidden = NO;
        contentView.repeatView.image = [NvUtils imageWithName:@"douyinRepeat"];
        contentView.repeatView.centerX = contentView.timelineEditor.centerX;
        self.type = Repeat;
        [NvTimelineUtils doRepeatTimeline:self.timeline.duration/2 videotrack:[self.timeline getVideoTrackByIndex:0] originCutTrimInfo:self.videoPathArray.firstObject];
        NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
        for (int i = 0; i < track.clipCount; i++) {
            [track setBuiltinTransition:i withName:NULL];
        }
        [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
        
        int64_t pos = [self playPosition:self.timeline forType:self.type current:0.5];
        [self seekTimeline:pos];
        contentView.effectWrapper.sliderView.value = 1.0*pos/self.timeline.duration;
        [contentView.timelineEditor setProgressValue:1.0*pos/self.timeline.duration];
        //播放
        [context playbackTimeline:self.timeline startTime:pos endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
    }
}

- (void)slowMotion {
    if (self.convertFinish) {
        [self rebuildTimeline:self.timeline isRevert:NO];
        [contentView.timelineEditor showCoverView:NO];
        contentView.repeatView.hidden = NO;
        contentView.repeatView.image = [NvUtils imageWithName:@"douyinSlow"];
        contentView.repeatView.centerX = contentView.timelineEditor.centerX;
        self.type = Slow;
        [NvTimelineUtils doSlowMotionTimeline:self.timeline.duration/2 videotrack:[self.timeline getVideoTrackByIndex:0]];
        NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
        for (int i = 0; i < track.clipCount; i++) {
            [track setBuiltinTransition:i withName:NULL];
        }
        [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
        
        int64_t pos = [self playPosition:self.timeline forType:self.type current:0.5];
        [self seekTimeline:pos];
        contentView.effectWrapper.sliderView.value = 1.0*pos/self.timeline.duration;
        [contentView.timelineEditor setProgressValue:1.0*pos/self.timeline.duration];
        //播放
        [context playbackTimeline:self.timeline startTime:pos endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
    }
}

- (void)none {
    [self rebuildTimeline:self.timeline isRevert:NO];
    NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
    for (int i = 0; i < track.clipCount; i++) {
        [track setBuiltinTransition:i withName:NULL];
    }
    [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
    [contentView.timelineEditor showCoverView:NO];
    contentView.repeatView.hidden = YES;
    [self seekTimeline:0];
    contentView.effectWrapper.sliderView.value = 0;
    [contentView.timelineEditor setProgressValue:0];
    //播放
    [context playbackTimeline:self.timeline startTime:0 endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
}

#pragma mark 转码
- (void)convert {
    self.fileConvert = [NvFileConvert new];
    [self.fileConvert convertFiles:self.videoPathArray];
    __weak typeof(self)weakSelf = self;
    [self.fileConvert finishBlock:^(BOOL isFinish) {
        __strong typeof(weakSelf)self = weakSelf;
        if (isFinish) {
            NSLog(@"转码成功");
        } else {
            NSLog(@"转码失败");
        }
        if (self) {
            self.convertFinish = YES;
            [self->contentView finishConvert];
            if (self.isTimeFx) {
                if (self.currentSelectType == Repeat) {
                    [self repeat];
                } else if (self.currentSelectType == PlayRevert) {
                    [self playRevert];
                }
            }
        }
    }];
    [self.fileConvert startConvert];
}
#pragma mark 当前转码状态的回调
- (BOOL)currentConvertStatus {
    return self.convertFinish;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark 点击滤镜特效
- (void)videoFxClick {
    [[NvSDKUtils getSDKContext] stop];
    self.isTimeFx = NO;
    if (!self.convertFinish) {
        [contentView selectIndex:0];
        [contentView finishConvert];
        self.currentSelectType = None;
    }
}

#pragma mark 点击时间特效
- (void)timeFxClick {
    [[NvSDKUtils getSDKContext] stop];
    self.isTimeFx = YES;
}
#pragma mark 时间特效拖动进度条
- (void)timelineEditor:(id)timelineEditor dragTimeAxis:(int64_t)timestamp {
    if (self.type == PlayRevert) {
        [self seekTimeline:self.timeline.duration-timestamp];
    } else {
        [self seekTimeline:timestamp];
    }
}

#pragma mark 重复
- (void)repeatPointValue:(float)value forStatus:(UIGestureRecognizerState)status{
    int64_t point = self.timeline.duration*value;
    if (status == UIGestureRecognizerStateEnded) {
        if (self.type == Slow) {
            [self rebuildTimeline:self.timeline isRevert:NO];
            [NvTimelineUtils doSlowMotionTimeline:point videotrack:[self.timeline getVideoTrackByIndex:0]];
            NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
            for (int i = 0; i < track.clipCount; i++) {
                [track setBuiltinTransition:i withName:NULL];
            }
            [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
            int64_t pos = [self playPosition:self.timeline forType:self.type current:value];
            [self seekTimeline:pos];
            contentView.effectWrapper.sliderView.value = 1.0*pos/self.timeline.duration;
            [contentView.timelineEditor setProgressValue:1.0*pos/self.timeline.duration];
            //播放
            [context playbackTimeline:self.timeline startTime:pos endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
        } else if (self.type == Repeat) {
            [self rebuildTimeline:self.timeline isRevert:NO];
            [NvTimelineUtils doRepeatTimeline:point videotrack:[self.timeline getVideoTrackByIndex:0] originCutTrimInfo:self.videoPathArray.firstObject];
            NvsVideoTrack *track = [self.timeline getVideoTrackByIndex:0];
            for (int i = 0; i < track.clipCount; i++) {
                [track setBuiltinTransition:i withName:NULL];
            }
            
            [self addFxsWithNewArray:self.fxNewArray withTimeline:self.timeline];
            int64_t pos = [self playPosition:self.timeline forType:self.type current:value];
            [self seekTimeline:pos];
            contentView.effectWrapper.sliderView.value = 1.0*pos/self.timeline.duration;
            [contentView.timelineEditor setProgressValue:1.0*pos/self.timeline.duration];
            //播放
            [context playbackTimeline:self.timeline startTime:pos endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
        }
        self.timeline = self.timeline;
    }
    
}

#pragma mark NvDouyinEditViewDelegate
- (void)liveWindowTappedStop {
    [[NvSDKUtils getSDKContext] stop];
}

- (void)imageViewTappedPlay {
    if ([NvSDKUtils getSDKContext].getStreamingEngineState != NvsStreamingEngineState_Playback) {
        if (![[NvSDKUtils getSDKContext] playbackTimeline:self.timeline startTime:[[NvSDKUtils getSDKContext] getTimelineCurrentPosition:self.self.timeline] endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0]) {
            NSLog(@"播放时间线失败！");
            return;
        }
    }
}

#pragma mark NvsStreamingContextDelegate
- (void)didStreamingEngineStateChanged:(NvsStreamingEngineState)state {
    if (state == NvsStreamingEngineState_Playback) {
        contentView.playImageView.hidden = YES;
    } else {
        contentView.playImageView.hidden = NO;
    }
}

- (void)didPlaybackTimelinePosition:(NvsTimeline *)timeline position:(int64_t)position {
    self.currentPlayTime = position;
    
    if (self.type == PlayRevert) {
        //倒放时播放进度条是倒着来
        contentView.effectWrapper.sliderView.value = 1 - ((float)position/timeline.duration);
        [contentView.timelineEditor setProgressValue:1 - ((float)position/timeline.duration)];
    } else {
        contentView.effectWrapper.sliderView.value = (float)position/timeline.duration;
        [contentView.timelineEditor setProgressValue:(float)position/timeline.duration];
    }
    
    if (self.isAddFx) {
        if (self.type == PlayRevert) {
            contentView.effectWrapper.colorBarView.timelineCurrentPosition = self.timeline.duration - position;
            [contentView.effectWrapper.colorBarView updateLastBar:YES];
        } else {
            contentView.effectWrapper.colorBarView.timelineCurrentPosition = position;
            [contentView.effectWrapper.colorBarView updateLastBar:NO];
        }
    }
}

- (void)didPlaybackStopped:(NvsTimeline *)timeline {
    
}

- (void)didPlaybackEOF:(NvsTimeline *)timeline {
    //如果正在添加滤镜则停就停了不用seek到0
    if (!self.isAddFx) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NvSDKUtils getSDKContext] seekTimeline:self.timeline timestamp:0 videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize flags:0];
            [[NvSDKUtils getSDKContext] playbackTimeline:self.timeline startTime:0 endTime:self.timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0];
        });
    }
}

#pragma mark 对timeline的操作
- (int64_t)playPosition:(NvsTimeline *)timeline forType:(Type)type current:(float)value {
    if(type == Slow || type == Repeat) {
        int64_t time = (int64_t) (timeline.duration * value);
        time = time - 1000000;
        if (time < 0)
            time = 0;
        return time;
    } else {
        return (int64_t) (timeline.duration * value);;
    }
}
//重新buildTimeline
- (void)rebuildTimeline:(NvsTimeline *)timeline isRevert:(BOOL)isRevert {
    NvsVideoTrack *track = [timeline getVideoTrackByIndex:0];
    [track removeAllClips];
    NvsAudioTrack *audioTrack = [timeline getAudioTrackByIndex:0];
    [audioTrack removeAllClips];
    
    [self removeAllTimelineFx:self.timeline];
    
    if (!isRevert) {
        [self addClips:self.videoPathArray toTimeline:timeline];
    } else {
        NSMutableArray *sortFiles = [NSMutableArray array];
        for (int i = 0; i < self.videoPathArray.count; i++) {
            NvRecordingInfo *info = self.videoPathArray[i];
            NvRecordingInfo *infoRevert = [NvRecordingInfo new];
            infoRevert.rotaion = info.rotaion;
            infoRevert.convertPath = info.convertPath;
            infoRevert.trimIn = info.trimIn;
            infoRevert.trimOut = info.trimOut;
            infoRevert.speed = info.speed;
            infoRevert.musicEndPos = info.musicEndPos;
            [sortFiles insertObject:infoRevert atIndex:0];
        }
        [self addClips:sortFiles toTimeline:self.timeline];
    }
    
    for (int i = 0; i < track.clipCount; i++) {
        [track setBuiltinTransition:i withName:NULL];
    }
}

//长按时添加特效
- (void)addFx:(NvsTimeline *)timeline withPackgeId:(NSString *)packageId {
    int64_t currentTime = [[NvSDKUtils getSDKContext] getTimelineCurrentPosition:timeline];
    if ([NvSDKUtils isBuiltinFilter:packageId]) {
        [timeline addBuiltinTimelineVideoFx:currentTime duration:timeline.duration - currentTime videoFxName:packageId];
    } else {
        [timeline addPackagedTimelineVideoFx:currentTime duration:timeline.duration - currentTime videoFxPackageId:packageId];
    }
}
//移除所有特效
- (void)removeAllTimelineFx:(NvsTimeline *)timeline {
    NvsTimelineVideoFx *videoFx = [timeline getFirstTimelineVideoFx];
    while (videoFx) {
        videoFx = [timeline removeTimelineVideoFx:videoFx];
    }
}
- (NvTimeFilterInfoModel *)revertModel:(NvTimeFilterInfoModel *)model timeline:(NvsTimeline *)timeline {
    NvTimeFilterInfoModel *modelInfo = [model copy];
    int64_t inpoint = timeline.duration - modelInfo.outPoint;
    modelInfo.outPoint = timeline.duration - modelInfo.inPoint;
    modelInfo.inPoint = inpoint;
    return modelInfo;
}
//转换为可以为倒放添加特效的model
- (NSMutableArray *)revertModelWith:(NSMutableArray<NvTimeFilterInfoModel *> *)fxNewArray withTimeline:(NvsTimeline *)timeline {
    NSMutableArray <NvTimeFilterInfoModel *>*array = [NSMutableArray array];
    
    for (NvTimeFilterInfoModel *model in fxNewArray) {
        NvTimeFilterInfoModel *tempModel = [model copy];
        int64_t inpoint = tempModel.inPoint;
        tempModel.inPoint = timeline.duration - tempModel.outPoint;
        tempModel.outPoint = timeline.duration - inpoint;
        [array addObject:tempModel];
    }
    
    return array;
}
//根据数据添加特效
- (void)addFxsWithNewArray:(NSMutableArray<NvTimeFilterInfoModel *> *)fxNewArray withTimeline:(NvsTimeline *)timeline {
    //添加特效
    for (int i = 0; i < fxNewArray.count; i++) {
        NvTimeFilterInfoModel *model = fxNewArray[i];
        if ([NvSDKUtils isBuiltinFilter:model.name]) {
            [timeline addBuiltinTimelineVideoFx:model.inPoint
                                            duration:model.outPoint - model.inPoint
                                         videoFxName:model.name];
        } else {
            [timeline addPackagedTimelineVideoFx:model.inPoint
                                             duration:model.outPoint - model.inPoint
                                     videoFxPackageId:model.name];
        }
    }
}

//生成新的不重复的序列
- (NSMutableArray<NvTimeFilterInfoModel *> *)filterModele:(NSMutableArray<NvTimeFilterInfoModel *> *)models withNewModel:(NvTimeFilterInfoModel *)model {
    
    int64_t inPoint = model.inPoint;
    int64_t outPoint = model.outPoint;
    NSMutableArray <NvTimeFilterInfoModel *>*array = [NSMutableArray array];
    for (int i = 0; i < models.count; i++) {
        NvTimeFilterInfoModel *info = models[i];
        int64_t tmpInPoint = info.inPoint;
        int64_t tmpOutPoint = info.outPoint;
        
        if (tmpInPoint < inPoint) {
            if (tmpOutPoint <= inPoint) {
                NvTimeFilterInfoModel *newInfo = [info copy];
                newInfo.inPoint = tmpInPoint;
                newInfo.outPoint = tmpOutPoint;
                [array addObject:newInfo];
            } else {
                NvTimeFilterInfoModel *newInfo = [info copy];
                newInfo.inPoint = tmpInPoint;
                newInfo.outPoint = inPoint;
                [array addObject:newInfo];
                
                if (tmpOutPoint > outPoint) {
                    NvTimeFilterInfoModel *newInfo = [info copy];
                    newInfo.inPoint = outPoint;
                    newInfo.outPoint = tmpOutPoint;
                    [array addObject:newInfo];
                }
            }
        } else if (tmpInPoint < outPoint) {
            if (tmpOutPoint <= outPoint) {
                // do nothing
            } else {
                NvTimeFilterInfoModel *newInfo = [info copy];
                newInfo.inPoint = outPoint;
                newInfo.outPoint = tmpOutPoint;
                [array addObject:newInfo];
            }
        } else {
            NvTimeFilterInfoModel *newInfo = [info copy];
            newInfo.inPoint = tmpInPoint;
            newInfo.outPoint = tmpOutPoint;
            [array addObject:newInfo];
        }
    }
    [array addObject:[model copy]];
    return [[NSMutableArray alloc] initWithArray:array copyItems:YES];
}

@end
