//
//  TimeVideoFxViewController.m
//  wangyi
//
//  Created by meishe01 on 2018/3/21.
//  Copyright © 2018年 meicam.com. All rights reserved.
//

#import "NvTimeVideoFxViewController.h"
#import "NvsStreamingContext.h"
#import "NvsTimeline.h"
#import "NvsLiveWindow.h"
#import "NvsVideoTrack.h"
#import "NvsAudioTrack.h"
#import "NvsVideoClip.h"
#import "NvsAudioClip.h"
#import "NvsVideoFx.h"
#import "NvsAudioFx.h"
#import "NvsFxDescription.h"
#import "NvsTimelineVideoFx.h"
#import "NvUtils.h"
#import "NvFilterCell.h"
#import "NvFilterItem.h"

#import "NvEditViewController.h"
#import "NvsTimelineEditor.h"
#import "NvEffectWrapper.h"
#import "NvsTimelineCaption.h"
#import "NvsTimelineAnimatedSticker.h"
#import "NVHeader.h"

#import "NvTimelineUtils.h"
#import "NvTimelineFilterUtils.h"

@interface NvTimeVideoFxViewController () <NvsStreamingContextDelegate, UICollectionViewDataSource, UICollectionViewDelegate, NvsTimelineEditorDelegate, NvEffectWrapperDelegate> {
    NvsStreamingContext *_streamingContext;
    NvsTimeline *_timeline;
    NvsLiveWindow *_liveWindow;
    NvsVideoTrack *_videoTrack;
    NvsVideoFx *_filter;
    UIButton *_cancelBtn;
    UIButton *_saveBtn;
    UIButton *_playBtn;
    UIView *_videoFxPanelView;
    UICollectionView *_timeVideoFxCollectionView;
    UICollectionView *_videoFxCollectionView;
    NvEffectWrapper *_effectWrapper;
    UIButton *_timeVideoFxBtn;
    UIButton *_videoFxBtn;
    UIButton *_revertBtn;
    UIView *_timeVideoFxView;
    UIView *_videoFxView;
    NSMutableArray *_timeVideoFxDataSource;
    NSMutableArray *_videoFxDataSource;
    unsigned int _currentTimeVideoFxIndex;
    unsigned int _currentVideoFxIndex;
    NvsTimelineEditor *_timelineEditor;
    NvsTimelineEditor *_videoFxTimelineEditor;
    NSMutableArray *_videoFxDataArray;
    NSMutableArray *_needRecovervVideoFxDataArray;
    NSMutableArray *_revertVideoFxDataArray;
    NSMutableArray *_revertPositionArray;
    NvsTimelineVideoFx *_currentVideoFx;
    BOOL _isAddingEffect;
    UIView *_liveWindowContainer;
    UIView *_playView;
    UIImageView *_playImageView;
    BOOL _isFirstCreate;
    NSString *_recoverBuildFxName;
    UIView *_filterLine;
    BOOL _hasModified;
}

@end

@implementation NvTimeVideoFxViewController

- (UIStatusBarStyle)preferredStatusBarStyle {
    return UIStatusBarStyleLightContent;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.navigationController setNavigationBarHidden:YES];
    _videoFxDataArray = [[NSMutableArray alloc] init];
    _needRecovervVideoFxDataArray = [[NSMutableArray alloc] init];
    _timeVideoFxDataSource = [[NSMutableArray alloc] init];
    _videoFxDataSource = [[NSMutableArray alloc] init];
    _currentTimeVideoFxIndex = 0;
    _currentVideoFxIndex = 0;
    _isFirstCreate = YES;
    _hasModified = NO;
    
    // 初始化美摄SDK
    _streamingContext = [NvsStreamingContext sharedInstance];
    if (!_streamingContext) {
        NSLog(@"初始化失败！");
        return;
    }
    
    _timeline = [NvTimelineUtils createTimeline:NvEditMode9v16];
//    self.reverseTimeline = [NvTimelineUtils createTimeline:NvEditMode9v16];
    [self addClips:self.files toTimeline:_timeline];
    
//    self.view.backgroundColor = [UIColor colorWithHexString:NV_EDIT_BACKGROUND_COLOR];
    // 设置回调接口
    _streamingContext.delegate = self;
    
    _liveWindowContainer = [[UIView alloc] initWithFrame:CGRectMake(82*SCREANSCALE, NV_STATUSBARHEIGHT+34*SCREANSCALE, 211*SCREANSCALE, 375*SCREANSCALE)];
    _liveWindowContainer.backgroundColor = [UIColor clearColor];
    [self.view addSubview:_liveWindowContainer];
    
    // 创建采集预览窗口并连接到时间线
    _liveWindow = [[NvsLiveWindow alloc] initWithFrame:CGRectMake(0, 0, 211*SCREANSCALE, 375*SCREANSCALE)];
    _liveWindow.fillMode = NvsLiveWindowFillModePreserveAspectFit;
    [_liveWindowContainer addSubview:_liveWindow];
    
    _playView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 211*SCREANSCALE, 375*SCREANSCALE)];
    UITapGestureRecognizer *tapLiveWindow = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(liveWindowTapped)];
    [_playView addGestureRecognizer:tapLiveWindow];
    [_liveWindowContainer addSubview:_playView];
    
    _playImageView = UIImageView.new;
    _playImageView.image = [NvUtils imageWithName:@"play-filled-icon"];
    [_liveWindowContainer addSubview:_playImageView];
    [_playImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(_liveWindowContainer);
    }];
    
    // 创建一个时间线
//    _timeline = self.oldTimeline;
    _videoTrack = [_timeline getVideoTrackByIndex:0];
    if (![_streamingContext connectTimeline:_timeline withLiveWindow:_liveWindow]) {
        NSLog(@"连接预览窗口失败！");
        return;
    }
    
    [self adjustLiveWindowFrame];
    
    [self seekTimeline:0];
    
    if (self.type == NvsTimeSpanType_Reverse) {
        _currentTimeVideoFxIndex = 3;
    } else if (self.type == NvsTimeSpanType_Repeat)
        _currentTimeVideoFxIndex = 1;
    else if (self.type == NvsTimeSpanType_Slow)
        _currentTimeVideoFxIndex = 2;
    else
        _currentTimeVideoFxIndex = 0;
    
    NSArray *videoFxArray = [NSArray arrayWithObjects:@"灵魂出窍", @"镜像", @"抖动", @"波浪", @"黑魔法", @"幻觉", nil];
    NSArray *timeVideoFxArray = [NSArray arrayWithObjects:@"无", @"反复", @"慢动作", @"时光倒流", nil];
    NSArray *videoFxIdArray = [NSArray arrayWithObjects:@"C6273A8F-C899-4765-8BFC-E683EE37AA84", @"6B7BE12C-9FA1-4ED0-8E81-E107632FFBC8", @"A8A4344D-45DA-460F-A18F-C0E2355FE864", @"1CEE3777-A813-4378-AD52-7B264BD0CC4D", @"C02204D0-F3C3-495E-B65C-9F2C79E68573", @"Video Echo", nil];
    NSArray *timelineVideoFxIconArray = [NSArray arrayWithObjects:@"NvsNone", @"NvsRepeat", @"NvsSlowMotion", @"NvsRevert", nil];
    for (int i = 0; i < videoFxArray.count; i++) {
        NvFilterItem *item = [NvFilterItem new];
        item.builtinName = nil;
        item.package = videoFxIdArray[i];
        item.cover = [NvUtils getEffectCoverName:videoFxIdArray[i]];
        item.displayName = videoFxArray[i];
        item.selected = NO;
        [_videoFxDataSource addObject:item];
    }
    
    for (int i = 0; i < timeVideoFxArray.count; i++) {
        NvFilterItem *item = [NvFilterItem new];
        item.builtinName = nil;
        item.package = nil;
        item.cover = timelineVideoFxIconArray[i];
        item.displayName = timeVideoFxArray[i];
        if (i == _currentTimeVideoFxIndex)
            item.selected = YES;
        else
            item.selected = NO;
        [_timeVideoFxDataSource addObject:item];
    }
    
    // 初始化UI
    int buttonSize = 30 * SCREANSCALE;
    int horizontalMargin = 0 * SCREANSCALE;
    int topMargin = NV_STATUSBARHEIGHT+10 * SCREANSCALE;
    int playBtnSize = 80;
    _cancelBtn = [[UIButton alloc] initWithFrame:CGRectMake(horizontalMargin, topMargin, buttonSize * 2, buttonSize)];
    _saveBtn = [[UIButton alloc] initWithFrame:CGRectMake(SCREANWIDTH - horizontalMargin - buttonSize * 2, topMargin, buttonSize * 2, buttonSize)];
    _playBtn = [[UIButton alloc] initWithFrame:CGRectMake((SCREANWIDTH - playBtnSize) / 2, _liveWindow.centerY - playBtnSize / 2, playBtnSize, playBtnSize)];
    
    [_cancelBtn setTitle:@"取消" forState:UIControlStateNormal];
    _cancelBtn.titleLabel.font = FONT16;
    [_saveBtn setTitle:@"保存" forState:UIControlStateNormal];
    _saveBtn.titleLabel.font = FONT16;
    
    [_cancelBtn addTarget:self action:@selector(cancelBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    [_saveBtn addTarget:self action:@selector(saveBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    [_playBtn addTarget:self action:@selector(playBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    
    [self.view addSubview:_cancelBtn];
    [self.view addSubview:_saveBtn];
    [self.view addSubview:_playBtn];
    
    int viewHeight = 223 * SCREANSCALE;
    int buttonHeight = 50 * SCREANSCALE;
    
    _isAddingEffect = NO;
    
    // 特效面板
    _videoFxPanelView = [[UIView alloc] initWithFrame:CGRectMake(0, SCREANHEIGHT - viewHeight, SCREANWIDTH, viewHeight)];
    _videoFxPanelView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.5];
    [self.view addSubview:_videoFxPanelView];
    
    // 滤镜特效按钮
    _videoFxBtn = [[UIButton alloc] initWithFrame:CGRectMake(0, _videoFxPanelView.height - buttonHeight, SCREANWIDTH / 2, buttonHeight)];
    [_videoFxBtn setTitle:@"滤镜特效" forState:UIControlStateNormal];
    [_videoFxBtn setTitleColor:STYLE_COLOR forState:UIControlStateNormal];
    _videoFxBtn.titleLabel.font = FONT16;
    _videoFxBtn.backgroundColor = [UIColor nv_colorWithHexARGB:@"#1AFFFFFF"];
    [_videoFxPanelView addSubview:_videoFxBtn];
    
    _filterLine = [[UIView alloc] initWithFrame:CGRectMake(0, _videoFxPanelView.height-2, 36*SCREANSCALE, 2)];
    _filterLine.backgroundColor = STYLE_COLOR;
    [_videoFxPanelView addSubview:_filterLine];
    _filterLine.centerX = _videoFxBtn.centerX;
    
    // 时间特效按钮
    _timeVideoFxBtn = [[UIButton alloc] initWithFrame:CGRectMake(SCREANWIDTH / 2, _videoFxPanelView.height - buttonHeight, SCREANWIDTH / 2, buttonHeight)];
    [_timeVideoFxBtn setTitle:@"时间特效" forState:UIControlStateNormal];
    [_timeVideoFxBtn setTitleColor:TEXT_DISABLE_COLOR forState:UIControlStateNormal];
    _timeVideoFxBtn.titleLabel.font = FONT16;
    _timeVideoFxBtn.backgroundColor = [UIColor nv_colorWithHexARGB:@"#1AFFFFFF"];
    [_videoFxPanelView addSubview:_timeVideoFxBtn];
    
    // 时间特效面板
    _timeVideoFxView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREANWIDTH, viewHeight - buttonHeight)];
    [_videoFxPanelView addSubview:_timeVideoFxView];
    _timeVideoFxView.hidden = YES;
    
    UILabel *timelineFxLabel = [[UILabel alloc] initWithFrame:CGRectMake(16 * SCREANSCALE, 50 * SCREANSCALE, 300, 14 * SCREANSCALE)];
    timelineFxLabel.text = @"点击选择时间特效";
    timelineFxLabel.textColor = TEXT_DISABLE_COLOR;
    timelineFxLabel.font = FONT14;
    [_timeVideoFxView addSubview:timelineFxLabel];
    
    
    int timelineEditorHeight = 30 * SCREANSCALE;
    _timelineEditor = [[NvsTimelineEditor alloc] initWithFrame:CGRectMake(0, 0, SCREANWIDTH, timelineEditorHeight)];
    _timelineEditor.delegate = self;
    _timelineEditor.caneditTimeSpan = true;
    _timelineEditor.canOverlapTimeSpan = true;
    [_timeVideoFxView addSubview:_timelineEditor];
//    [_timelineEditor setPointsPerMicrosecond:(double)SCREANWIDTH / _timeline.duration];
    
    NSMutableArray *descArray = [NSMutableArray array];
    for (int i = 0; i < _videoTrack.clipCount; i++) {
        NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
        NvsTimelineEditorInfo *info = [[NvsTimelineEditorInfo alloc] init];
        info.stillImageHint = NO;
        info.mediaFilePath = videoClip.filePath;
        info.trimIn = videoClip.trimIn;
        info.trimOut = videoClip.trimOut;
        info.inPoint = videoClip.inPoint;
        info.outPoint = videoClip.outPoint;
        [descArray addObject:info];
    }
    
    [_timelineEditor initTimelineEditor:descArray timelineDuration:_timeline.duration];
    
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    layout.itemSize = CGSizeMake(58*SCREANSCALE, 88*SCREANSCALE);
    layout.minimumLineSpacing = 30*SCREANSCALE;
    layout.minimumInteritemSpacing = 0;
    layout.sectionInset = UIEdgeInsetsMake(0, 16*SCREANSCALE, 0, 0);
    _timeVideoFxCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 82*SCREANSCALE, SCREANWIDTH, 88*SCREANSCALE) collectionViewLayout:layout];
    _timeVideoFxCollectionView.delegate = self;
    _timeVideoFxCollectionView.dataSource = self;
    _timeVideoFxCollectionView.backgroundColor = [UIColor clearColor];
    _timeVideoFxCollectionView.showsHorizontalScrollIndicator = NO;
    [_timeVideoFxView addSubview:_timeVideoFxCollectionView];
    [_timeVideoFxCollectionView registerClass:[NvFilterCell class] forCellWithReuseIdentifier:@"NvFilterCell"];
    [_timeVideoFxCollectionView selectItemAtIndexPath:[NSIndexPath indexPathForRow:_currentTimeVideoFxIndex inSection:0] animated:YES scrollPosition:UICollectionViewScrollPositionNone];
    
    [self updateTimelineVideoFxView];
    
    // 滤镜特效面板
    _videoFxView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREANWIDTH, viewHeight - buttonHeight)];
    [_videoFxPanelView addSubview:_videoFxView];

    _effectWrapper = [[NvEffectWrapper alloc] initWithFrame:CGRectMake(0, 0, SCREANWIDTH, timelineEditorHeight)];
    _effectWrapper.sliderView.value = (self.type == NvsTimeSpanType_Reverse ? 1 : 0);
    [self setupEffectWrapper];
    [_videoFxView addSubview:_effectWrapper];
    [self updateColorBarView];
    
    UILabel *videoFxLabel = [[UILabel alloc] initWithFrame:CGRectMake(16 * SCREANSCALE, 50 * SCREANSCALE, 300, 14 * SCREANSCALE)];
    videoFxLabel.text = @"选择位置后，按住使用效果";
    videoFxLabel.textColor = TEXT_DISABLE_COLOR;
    videoFxLabel.font = FONT14;
    [_videoFxView addSubview:videoFxLabel];
    
    _revertBtn = [[UIButton alloc] initWithFrame:CGRectMake(299 * SCREANSCALE, 42 * SCREANSCALE, 60 * SCREANSCALE, 30 * SCREANSCALE)];
    //_revertBtn.backgroundColor = BACKGROUND_DISABLE_COLOR;
    _revertBtn.backgroundColor = STYLE_COLOR;
    _revertBtn.layer.cornerRadius = _revertBtn.height / 2;
    _revertBtn.layer.masksToBounds = YES;
    _revertBtn.titleLabel.font = [UIFont fontWithName:@"PingFangSC-Regular" size:15];
    [_revertBtn setTitle:@"撤销" forState:UIControlStateNormal];
    //[_revertBtn setTitleColor:TEXT_DISABLE_COLOR forState:UIControlStateNormal];
    [_revertBtn setTitleColor:TEXT_ENABLE_COLOR forState:UIControlStateNormal];
    _revertBtn.hidden = !_revertVideoFxDataArray.count;
    [_videoFxView addSubview:_revertBtn];
    
    UICollectionViewFlowLayout *layout1 = [[UICollectionViewFlowLayout alloc] init];
    layout1.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    layout1.itemSize = CGSizeMake(58*SCREANSCALE, 88*SCREANSCALE);
    layout1.minimumLineSpacing = 30*SCREANSCALE;
    layout1.minimumInteritemSpacing = 0;
    layout1.sectionInset = UIEdgeInsetsMake(0, 16*SCREANSCALE, 0, 0);
    _videoFxCollectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 82 * SCREANSCALE, SCREANWIDTH, 88 * SCREANSCALE) collectionViewLayout:layout1];
    _videoFxCollectionView.delegate = self;
    _videoFxCollectionView.dataSource = self;
    _videoFxCollectionView.backgroundColor = [UIColor clearColor];
    _videoFxCollectionView.showsHorizontalScrollIndicator = NO;
    [_videoFxView addSubview:_videoFxCollectionView];
    [_videoFxCollectionView registerClass:[NvFilterCell class] forCellWithReuseIdentifier:@"NvFilterCell"];
    
    UILongPressGestureRecognizer *longPress =[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressAction:)];
    longPress.minimumPressDuration = 0.1;
    longPress.allowableMovement = 1;
    [_videoFxCollectionView addGestureRecognizer:longPress];

    
    // 按钮点击事件
    [_timeVideoFxBtn addTarget:self action:@selector(timeVideoFxBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    [_videoFxBtn addTarget:self action:@selector(videoFxBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    [_revertBtn addTarget:self action:@selector(revertBtnClicked) forControlEvents:(UIControlEventTouchUpInside)];
    
    // 设置监听应用通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
    
    [self seekTimeline:0];
}

- (void)addClips:(NSArray *)clips toTimeline:(NvsTimeline *)timeline {
    NvsVideoTrack *videoTrack = [timeline getVideoTrackByIndex:0];
    [videoTrack setVolumeGain:0 rightVolumeGain:0];
    for (NSString *path in clips) {
        [videoTrack appendClip:path];
    }
    NvsAudioTrack *audioTrack = [timeline getAudioTrackByIndex:0];
    
    int64_t audioDuration = audioTrack.duration;
    while (audioDuration < videoTrack.duration) {
        [audioTrack appendClip:self.musicPath];
        audioDuration = audioTrack.duration;
    }
}

- (void)adjustLiveWindowFrame {
    NvsVideoResolution videoRes = _timeline.videoRes;
    if (videoRes.imageWidth > videoRes.imageHeight) {
        float posY = (SCREANHEIGHT - 223*SCREANSCALE - SCREANWIDTH*9/16)/2;
        _liveWindowContainer.frame = CGRectMake(0, posY, SCREANWIDTH, SCREANWIDTH*9/16);
        _liveWindow.frame = CGRectMake(0, 0, SCREANWIDTH, SCREANWIDTH*9/16);
        _playView.frame = CGRectMake(0, 0, SCREANWIDTH, SCREANWIDTH*9/16);
    }
}

- (void)setRevertDataArray:(NSMutableArray *)array {
    _revertVideoFxDataArray = [[NSMutableArray alloc] init];
    for (NvVideoFxData *data in array)
        [_revertVideoFxDataArray addObject:data];
}

- (void)setRevertPositionArray:(NSMutableArray *)array {
    _revertPositionArray = [[NSMutableArray alloc] init];
    for (NvVideoFxData *data in array)
        [_revertPositionArray addObject:data];
}

- (void)updateTimelineVideoFxView {
//    if (self.type != NvsTimeSpanType_Invalid) {
//        NvsTimelineTimeSpanSticker *timeSpan = [_timelineEditor addTimeSpanSticker:self.timelineVideoFxPos outPoint:_timeline.duration];
//        timeSpan.type = self.type;
//    }
}

- (void)setupEffectWrapper {
    NSMutableArray *thumbnailSequenceDescArray = [NSMutableArray array];
    for (int i = 0; i < _videoTrack.clipCount; i++) {
        NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
        NvsThumbnailSequenceDesc *info = [[NvsThumbnailSequenceDesc alloc] init];
        info.stillImageHint = NO;
        info.mediaFilePath = videoClip.filePath;
        info.trimIn = videoClip.trimIn;
        info.trimOut = videoClip.trimOut;
        info.inPoint = videoClip.inPoint;
        info.outPoint = videoClip.outPoint;
        
        [thumbnailSequenceDescArray addObject:info];
    }
    _effectWrapper.sequenceView.descArray = thumbnailSequenceDescArray;
    _effectWrapper.sequenceView.pointsPerMicrosecond = SCREANWIDTH/_timeline.duration;
    _effectWrapper.colorBarView.timelineDuration = _timeline.duration;
    _effectWrapper.delegate = self;
}

- (void)sliderValueChanged {
//    if ([self isPlaying])
//        return;
    
    if (self.type == NvsTimeSpanType_Reverse) {
        int64_t timelinePos = (1 - _effectWrapper.sliderView.value) * _timeline.duration;
        [self seekTimeline:timelinePos];
    } else {
        int64_t timelinePos = _effectWrapper.sliderView.value * _timeline.duration;
        [self seekTimeline:timelinePos];
    }
}

- (void)liveWindowTapped {
    NvsStreamingEngineState state = [_streamingContext getStreamingEngineState];
    if (state == NvsStreamingEngineState_Playback) {
        [_streamingContext stop];
    }
    if (state != NvsStreamingEngineState_Playback) {
        int64_t startPosition = [_streamingContext getTimelineCurrentPosition:_timeline];
        [self playbackTimeline:startPosition];
    }
}

- (void)didStreamingEngineStateChanged:(NvsStreamingEngineState)state {
    if (state == NvsStreamingEngineState_Playback) {
        _playImageView.hidden = YES;
    } else {
        _playImageView.hidden = NO;
    }
}

- (void)dealloc {
    [self clear];
    NSLog(@"%s",__func__);
}

- (void)clear {
    // 取消监听应用通知
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (void)recreateTimeline:(BOOL)firstCreate {
    NSMutableArray *videoFxDataArray = [[NSMutableArray alloc] init];
    if (_isFirstCreate) {
        NvsVideoResolution videoEditRes;
        videoEditRes.imageWidth = self.oldOrgTimeline.videoRes.imageWidth;
        videoEditRes.imageHeight = self.oldOrgTimeline.videoRes.imageHeight;
        videoEditRes.imagePAR = (NvsRational){1, 1};
        NvsRational videoFps = {25, 1};
        NvsAudioResolution audioEditRes;
        audioEditRes.sampleRate = 48000;
        audioEditRes.channelCount = 2;
        audioEditRes.sampleFormat = NvsAudSmpFmt_S16;
        _timeline = [_streamingContext createTimeline:&videoEditRes videoFps:&videoFps audioEditRes:&audioEditRes];
        if (!_timeline) {
            NSLog(@"创建时间线失败！");
            return;
        }
        
        for (int i = 0; i < self.oldOrgTimeline.audioTrackCount; i++) {
            NvsAudioTrack *oldAudioTrack = [self.oldOrgTimeline getAudioTrackByIndex:i];
            NvsAudioTrack *audioTrack = [_timeline appendAudioTrack];
            for (int j = 0; j < oldAudioTrack.clipCount; j++) {
                NvsAudioClip *oldAudioClip = [oldAudioTrack getClipWithIndex:j];
                NvsAudioClip *audioClip = [audioTrack appendClip:oldAudioClip.filePath trimIn:oldAudioClip.trimIn trimOut:oldAudioClip.trimOut];
                [audioClip appendFx:[oldAudioClip getFxWithIndex:0].description.name];
                [audioClip changeSpeed:[oldAudioClip getSpeed]];
            }
            float leftVolumn, rightVolumn;
            [oldAudioTrack getVolumeGain:&leftVolumn rightVolumeGain:&rightVolumn];
            [audioTrack setVolumeGain:leftVolumn rightVolumeGain:rightVolumn];
        }
    } else {
        NvsTimelineVideoFx *timelineVideoFx = [_timeline getFirstTimelineVideoFx];
        while (timelineVideoFx) {
            NvVideoFxData *data = [[NvVideoFxData alloc] init];
            data.inPoint = timelineVideoFx.inPoint;
            data.duration = timelineVideoFx.outPoint - timelineVideoFx.inPoint;
            data.type = timelineVideoFx.timelineVideoFxType;
            if (data.type == NvsTimelineVideoFxType_Builtin)
                data.package = timelineVideoFx.bultinTimelineVideoFxName;
            else
                data.package = timelineVideoFx.timelineVideoFxPackageId;
            [videoFxDataArray addObject:data];
            timelineVideoFx = [_timeline removeTimelineVideoFx:timelineVideoFx];
        }
        [_timeline removeVideoTrack:0];
    }
    
    // 添加一个视频轨道，以便后面添加片段时使用
    _videoTrack = [_timeline appendVideoTrack];
    if (!_videoTrack) {
        NSLog(@"创建视频轨道失败！");
        return;
    }
    
    NvsVideoTrack *oldVideoTrack = [self.oldOrgTimeline getVideoTrackByIndex:0];
    for (int i = 0; i < oldVideoTrack.clipCount; i++) {
        NvsVideoClip *oldVideoClip = [oldVideoTrack getClipWithIndex:i];
        double speed = [oldVideoClip getSpeed];
        NvsVideoClip *clip = [_videoTrack appendClip:oldVideoClip.filePath];
        if (clip) {
            [clip setExtraVideoRotation:[oldVideoClip getExtraVideoRotation]];
            for (int j = 0; j < oldVideoClip.fxCount; j++) {
                NvsVideoFx *videoFx = [oldVideoClip getFxWithIndex:j];
                if (videoFx.videoFxType == NvsVideoFxType_Builtin) {
                    //[clip appendBuiltinFx:videoFx.bultinVideoFxName];
                    _recoverBuildFxName = videoFx.bultinVideoFxName;
                } else if (videoFx.videoFxType == NvsVideoFxType_Package)
                    [clip appendPackagedFx:videoFx.videoFxPackageId];
            }
            if (firstCreate)
                [clip setPlayInReverse:self.type == NvsTimeSpanType_Reverse];
            [clip changeSpeed:speed];
            if (clip.index > 0)
                [_videoTrack setBuiltinTransition:clip.index - 1 withName:@""];
        }
    }
    
    [_videoTrack setVolumeGain:0 rightVolumeGain:0];
    
    if (_isFirstCreate) {
        NvsTimelineVideoFx *timelineVideoFx = [self.oldTimeline getFirstTimelineVideoFx];
        while (timelineVideoFx) {
            if (timelineVideoFx.timelineVideoFxType == NvsTimelineVideoFxType_Builtin)
                [_timeline addBuiltinTimelineVideoFx:timelineVideoFx.inPoint duration:timelineVideoFx.outPoint - timelineVideoFx.inPoint videoFxName:timelineVideoFx.bultinTimelineVideoFxName];
            else
                [_timeline addPackagedTimelineVideoFx:timelineVideoFx.inPoint duration:timelineVideoFx.outPoint - timelineVideoFx.inPoint videoFxPackageId:timelineVideoFx.timelineVideoFxPackageId];
            timelineVideoFx = [self.oldTimeline getNextTimelineVideoFx:timelineVideoFx];
        }
    } else {
        for (NvVideoFxData *data in videoFxDataArray) {
            if (data.type == NvsTimelineVideoFxType_Builtin)
                [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:data.duration videoFxName:data.package];
            else
                [_timeline addPackagedTimelineVideoFx:data.inPoint duration:data.duration videoFxPackageId:data.package];
        }
    }
    _isFirstCreate = NO;
}

- (void)copyCaptionsAndStickers {
    NvsTimelineCaption *caption = [self.oldTimeline getFirstCaption];
    while (caption) {
        NvsTimelineCaption *newCaption = [_timeline addCaption:[caption getText] inPoint:caption.inPoint duration:caption.outPoint - caption.inPoint captionStylePackageId:caption.captionStylePackageId];
        NvsColor color = [caption getTextColor];
        [newCaption setTextColor:&color];
        [newCaption setCaptionTranslation:[caption getCaptionTranslation]];
        [newCaption setScaleX:[caption getScaleX]];
        [newCaption setScaleY:[caption getScaleY]];
        [newCaption setRotationZ:[caption getRotationZ]];
        caption = [self.oldTimeline getNextCaption:caption];
    }
    
    NvsTimelineAnimatedSticker *sticker = [self.oldTimeline getFirstAnimatedSticker];
    while (sticker) {
        NvsTimelineAnimatedSticker *newSticker = [_timeline addAnimatedSticker:sticker.inPoint duration:sticker.outPoint - sticker.inPoint animatedStickerPackageId:[sticker getAnimatedStickerPackageId]];
        [newSticker setTranslation:[sticker getTransltion]];
        [newSticker setScale:[sticker getScale]];
        [newSticker setRotationZ:[sticker getRotationZ]];
        [newSticker setHorizontalFlip:[sticker getHorizontalFlip]];
        float leftVolume, rightVolume;
        [sticker getVolumeGain:&leftVolume rightVolumeGain:&rightVolume];
        [newSticker setVolumeGain:leftVolume rightVolumeGain:rightVolume];
        sticker = [self.oldTimeline getNextAnimatedSticker:sticker];
    }
}

- (void)reverseCaptions {
    NvsTimelineCaption *caption = [self.oldTimeline getFirstCaption];
    while (caption) {
        NvsTimelineCaption *newCaption = [_timeline addCaption:[caption getText] inPoint:_timeline.duration - caption.outPoint duration:caption.outPoint - caption.inPoint captionStylePackageId:caption.captionStylePackageId];
        NvsColor color = [caption getTextColor];
        [newCaption setTextColor:&color];
        [newCaption setCaptionTranslation:[caption getCaptionTranslation]];
        [newCaption setScaleX:[caption getScaleX]];
        [newCaption setScaleY:[caption getScaleY]];
        [newCaption setRotationZ:[caption getRotationZ]];
        caption = [self.oldTimeline getNextCaption:caption];
    }
}

- (void)reverseStickers {
    NvsTimelineAnimatedSticker *sticker = [self.oldTimeline getFirstAnimatedSticker];
    while (sticker) {
        NvsTimelineAnimatedSticker *newSticker = [_timeline addAnimatedSticker:_timeline.duration - sticker.outPoint duration:sticker.outPoint - sticker.inPoint animatedStickerPackageId:[sticker getAnimatedStickerPackageId]];
        [newSticker setTranslation:[sticker getTransltion]];
        [newSticker setScale:[sticker getScale]];
        [newSticker setRotationZ:[sticker getRotationZ]];
        [newSticker setHorizontalFlip:[sticker getHorizontalFlip]];
        sticker = [self.oldTimeline getNextAnimatedSticker:sticker];
    }
}

- (void)playbackTimeline:(int64_t)startPoint {
    if (![_streamingContext playbackTimeline:_timeline startTime:startPoint endTime:_timeline.duration videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize preload:YES flags:0])
        NSLog(@"播放时间线失败！");
}

- (void)seekTimeline:(int64_t)position {
    if (![_streamingContext seekTimeline:_timeline timestamp:position videoSizeMode:NvsVideoPreviewSizeModeLiveWindowSize flags:0])
        NSLog(@"定位时间线失败！");
}

- (BOOL)isPlaying {
    return [_streamingContext getStreamingEngineState] == NvsStreamingEngineState_Playback;
}

- (void)showCancelAlert {
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"放弃特效？" message:@"" preferredStyle:UIAlertControllerStyleAlert];
    
    UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"放弃" style:UIAlertActionStyleDefault
                                                          handler:^(UIAlertAction * action) {
                                                              [self doCancel];
                                                          }];
    
    UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault
                                                         handler:^(UIAlertAction * action) {                                                }];
    [alert addAction:cancelAction];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)doCancel {
    [self clear];

    [self.navigationController popViewControllerAnimated:YES];
}

- (void)cancelBtnClicked {
    if (_hasModified)
        [self showCancelAlert];
    else {
        [self doCancel];
    }
}

- (void)saveBtnClicked {
    [self clear];

    [self.navigationController popViewControllerAnimated:YES];
}

- (void)playBtnClicked {
    if ([self isPlaying])
        [_streamingContext stop];
    else
        [self playbackTimeline:0];
}

- (void)timeVideoFxBtnClicked {
    _videoFxView.hidden = YES;
    _timeVideoFxView.hidden = NO;
    int64_t timelinePos = [_streamingContext getTimelineCurrentPosition:_timeline];
    if (self.type == NvsTimeSpanType_Reverse)
        timelinePos = _timeline.duration - timelinePos;
//    [_timelineEditor setProgressValue:(float)timelinePos / _timeline.duration];
    [_videoFxBtn setTitleColor:TEXT_DISABLE_COLOR forState:UIControlStateNormal];
    [_timeVideoFxBtn setTitleColor:STYLE_COLOR forState:UIControlStateNormal];
    _filterLine.centerX = _timeVideoFxBtn.centerX;
}

- (void)videoFxBtnClicked {
    _timeVideoFxView.hidden = YES;
    _videoFxView.hidden = NO;
    int64_t timelinePos = [_streamingContext getTimelineCurrentPosition:_timeline];
    if (self.type == NvsTimeSpanType_Reverse)
        timelinePos = _timeline.duration - timelinePos;
    _effectWrapper.sliderView.value = (float)timelinePos / _timeline.duration;
    [_timeVideoFxBtn setTitleColor:TEXT_DISABLE_COLOR forState:UIControlStateNormal];
    [_videoFxBtn setTitleColor:STYLE_COLOR forState:UIControlStateNormal];
    _filterLine.centerX = _videoFxBtn.centerX;
}

- (void)revertBtnClicked {
    NvsTimelineVideoFx *timelineVideoFx = [_timeline getFirstTimelineVideoFx];
    while (timelineVideoFx)
        timelineVideoFx = [_timeline removeTimelineVideoFx:timelineVideoFx];
    
    int64_t pos = [[_revertPositionArray lastObject] longLongValue];
    [_revertPositionArray removeLastObject];
    [_revertVideoFxDataArray removeLastObject];
    NSMutableArray *videoFxDataArray = [_revertVideoFxDataArray lastObject];
    _revertBtn.hidden = !_revertVideoFxDataArray.count;
    for (NvVideoFxData *data in videoFxDataArray) {
        int64_t inPoint = data.inPoint;
        if (self.type == NvsTimeSpanType_Reverse) {
            inPoint = _timeline.duration - data.inPoint - data.duration;
        }
        if (data.type == NvsTimelineVideoFxType_Builtin)
            [_timeline addBuiltinTimelineVideoFx:inPoint duration:data.duration videoFxName:data.package];
        else
            [_timeline addPackagedTimelineVideoFx:inPoint duration:data.duration videoFxPackageId:data.package];
    }
    [self updateColorBarView];
    if (self.type == NvsTimeSpanType_Reverse)
        [self seekTimeline:_timeline.duration - pos];
    else
        [self seekTimeline:pos];
    _effectWrapper.sliderView.value = (float)pos / _timeline.duration;
}

- (void)didPlaybackTimelinePosition:(NvsTimeline *)timeline position:(int64_t)position {
    if (_timeVideoFxView.hidden) {
//        [_videoFxTimelineEditor setProgressValue:(float)position / timeline.duration];
    } else {
        if (self.type == NvsTimeSpanType_Reverse) {
//            [_timelineEditor setProgressValue:(float)(timeline.duration - position) / timeline.duration];
        } else {
//            [_timelineEditor setProgressValue:(float)position / timeline.duration];
        }
    }
    
    if (_isAddingEffect) {
        _effectWrapper.colorBarView.timelineCurrentPosition = position;
        [_effectWrapper.colorBarView updateLastBar:self.type == NvsTimeSpanType_Reverse];
    }
    
    if (self.type == NvsTimeSpanType_Reverse) {
        _effectWrapper.sliderView.value = (float)(_timeline.duration - position) / _timeline.duration;
    } else {
        _effectWrapper.sliderView.value = (float)position / _timeline.duration;
    }
}

// 播放至时间线结尾的回调函数
- (void)didPlaybackEOF:(NvsTimeline *)timeline {
    if (_isAddingEffect) {
        _effectWrapper.colorBarView.timelineCurrentPosition = _timeline.duration;
        [_effectWrapper.colorBarView updateLastBar:self.type == NvsTimeSpanType_Reverse];
        _effectWrapper.sliderView.value = (self.type == NvsTimeSpanType_Reverse ? 1 : 0);
        _isAddingEffect = NO;
        [self finishAddVideoFx];
        [self seekTimeline:0];
        return;
    }
    
    if (self.type == NvsTimeSpanType_Reverse) {
//        [_timelineEditor setProgressValue:1];
        _effectWrapper.sliderView.value = 1;
    } else {
//        [_timelineEditor setProgressValue:0];
        _effectWrapper.sliderView.value = 0;
    }
    
    dispatch_async(dispatch_get_main_queue(), ^{
        //[self playbackTimeline:0];
        [self seekTimeline:0];
    });
}

// 应用进入后台，停止播放
- (void)applicationWillResignActive:(NSNotification*)notification {
    [_streamingContext stop];
}

// 应用进入前台，恢复播放
- (void)applicationDidBecomeActive:(NSNotification*)notification {
    //[self playbackTimeline];
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    if ([collectionView isEqual:_timeVideoFxCollectionView])
        return _timeVideoFxDataSource.count;
    return _videoFxDataSource.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    if ([collectionView isEqual:_timeVideoFxCollectionView]) {
        NvFilterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NvFilterCell" forIndexPath:indexPath];
        [cell renderCellWithItem:_timeVideoFxDataSource[indexPath.row]];
        return cell;
    }
    NvFilterCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"NvFilterCell" forIndexPath:indexPath];
    [cell renderCellWithItem:_videoFxDataSource[indexPath.row]];
    return cell;
}

#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    if (![collectionView isEqual:_timeVideoFxCollectionView])
        return;
    
    if (_currentTimeVideoFxIndex == (unsigned int)indexPath.row)
        return;
    
    _hasModified = YES;
    
    NvFilterItem *item = _timeVideoFxDataSource[_currentTimeVideoFxIndex];
    item.selected = NO;
    _currentTimeVideoFxIndex = (unsigned int)indexPath.row;
    item = _timeVideoFxDataSource[indexPath.row];
    item.selected = YES;
    [_timeVideoFxCollectionView reloadData];
    
    //BOOL isPlaying = [self isPlaying];
    //int64_t startPosition = [_streamingContext getTimelineCurrentPosition:_timeline];
    int64_t startPosition = _timeline.duration / 2;
    [self recreateTimeline:_isFirstCreate];
    
    if (self.type == NvsTimeSpanType_Reverse) {
        for (int i = 0; i < _videoTrack.clipCount; i++) {
            [[_videoTrack getClipWithIndex:i] setPlayInReverse:NO];
        }
        [self reverseTimelineVideoFx];
    }
    
    self.type = NvsTimeSpanType_Invalid;
    if ([item.displayName isEqualToString:@"反复"]) {
//        [NvUtils doRepeatTimeline:startPosition videotrack:_videoTrack];
        self.type = NvsTimeSpanType_Repeat;
    } else if ([item.displayName isEqualToString:@"慢动作"]) {
//        [NvUtils doSlowMotionTimeline:startPosition videotrack:_videoTrack];
        self.type = NvsTimeSpanType_Slow;
    } else if ([item.displayName isEqualToString:@"时光倒流"]) {
        NvsVideoTrack *videoTrack = [_timeline appendVideoTrack];
        [videoTrack setVolumeGain:0 rightVolumeGain:0];
        for (int i = 0; i < _videoTrack.clipCount; i++) {
            NvsVideoClip *videoClip = [_videoTrack getClipWithIndex:i];
            NvsVideoClip *newVideoClip = [videoTrack insertClip:videoClip.filePath trimIn:videoClip.trimIn trimOut:videoClip.trimOut clipIndex:0];
            [newVideoClip changeSpeed:[videoClip getSpeed]];
            [newVideoClip setExtraVideoRotation:[videoClip getExtraVideoRotation]];
            [newVideoClip setPlayInReverse:YES];
            [newVideoClip appendBuiltinFx:[videoClip getFxWithIndex:0].bultinVideoFxName];
        }
        
        [_timeline removeVideoTrack:_videoTrack.index];
        _videoTrack = videoTrack;
        
        [self reverseTimelineVideoFx];
        
        self.type = NvsTimeSpanType_Reverse;
        startPosition = 0;
    }
    
    NvsVideoTrack *videoTrack = [_timeline getVideoTrackByIndex:0];
    for (int i = 0; i < videoTrack.clipCount; i++) {
        NvsVideoClip *videoClip = [videoTrack getClipWithIndex:i];
        [videoClip appendBuiltinFx:_recoverBuildFxName];
        [videoTrack setBuiltinTransition:i withName:@""];
    }
    
    [self copyCaptionsAndStickers];
    
    self.timelineVideoFxPos = startPosition;
    
    if (self.type != NvsTimeSpanType_Invalid) {
//        NvsTimelineTimeSpanSticker *timeSpan = [_timelineEditor addTimeSpanSticker:startPosition outPoint:_timeline.duration];
//        timeSpan.type = self.type;
    } else {
        [_timelineEditor deleteAllTimeSpan];
    }
    
    if (![_streamingContext connectTimeline:_timeline withLiveWindow:_liveWindow]) {
        NSLog(@"连接预览窗口失败！");
        return;
    }
    
    int64_t pos = startPosition - 1000000;
    if (pos < 0)
        pos = 0;
    if (self.type == NvsTimeSpanType_Reverse || self.type == NvsTimeSpanType_Invalid)
        pos = 0;
    [self seekTimeline:pos];
    [self playbackTimeline:pos];
}

- (void)reverseTimelineVideoFx {
    NSMutableArray *videoFxDataArray = [[NSMutableArray alloc] init];
    NvsTimelineVideoFx *timelineVideoFx = [_timeline getFirstTimelineVideoFx];
    while (timelineVideoFx) {
        NvVideoFxData *data = [[NvVideoFxData alloc] init];
        data.inPoint = _timeline.duration - timelineVideoFx.outPoint;
        data.duration = timelineVideoFx.outPoint - timelineVideoFx.inPoint;
        data.type = timelineVideoFx.timelineVideoFxType;
        if (data.type == NvsTimelineVideoFxType_Builtin)
            data.package = timelineVideoFx.bultinTimelineVideoFxName;
        else
            data.package = timelineVideoFx.timelineVideoFxPackageId;
        [videoFxDataArray addObject:data];
        timelineVideoFx = [_timeline removeTimelineVideoFx:timelineVideoFx];
    }
    
    for (NvVideoFxData *data in videoFxDataArray) {
        if (data.type == NvsTimelineVideoFxType_Builtin)
            [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:data.duration videoFxName:data.package];
        else
            [_timeline addPackagedTimelineVideoFx:data.inPoint duration:data.duration videoFxPackageId:data.package];
    }
}

- (void)longPressAction:(UILongPressGestureRecognizer *)recognizer {
    if (self.type == NvsTimeSpanType_Reverse) {
        if (_effectWrapper.sliderView.value == 0) {
            [self resetLongPressStatus];
            return;
        }
    } else {
        if (_effectWrapper.sliderView.value == 1) {
            [self resetLongPressStatus];
            return;
        }
    }
    
    _hasModified = YES;
    
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        CGPoint point = [recognizer locationInView:_videoFxCollectionView];
        NSIndexPath *indexPath = [_videoFxCollectionView indexPathForItemAtPoint:point];
        if (indexPath != nil) {
            NvFilterItem *item = _videoFxDataSource[indexPath.row];
            item.longPressed = YES;
            [_videoFxCollectionView reloadData];
            int64_t startPosition = [_streamingContext getTimelineCurrentPosition:_timeline];
            // 删除起始点后面的所有时间线特效
            [_needRecovervVideoFxDataArray removeAllObjects];
            NvsTimelineVideoFx *videoFx = [_timeline getLastTimelineVideoFx];
            while (videoFx) {
                if (videoFx.outPoint <= startPosition)
                    break;
                NvVideoFxData *data = [[NvVideoFxData alloc] init];
                data.type = videoFx.timelineVideoFxType;
                data.inPoint = videoFx.inPoint;
                data.duration = videoFx.outPoint - videoFx.inPoint;
                if (data.type == NvsTimelineVideoFxType_Builtin)
                    data.package = videoFx.bultinTimelineVideoFxName;
                else
                    data.package = videoFx.timelineVideoFxPackageId;
                [_needRecovervVideoFxDataArray addObject:data];
                NvsTimelineVideoFx *tempVideoFx = videoFx;
                videoFx = [_timeline getPrevTimelineVideoFx:videoFx];
                [_timeline removeTimelineVideoFx:tempVideoFx];
            }
            
            if ([item.displayName isEqualToString:@"幻觉"])
                _currentVideoFx = [_timeline addBuiltinTimelineVideoFx:startPosition duration:_timeline.duration - startPosition videoFxName:item.package];
            else
                _currentVideoFx = [_timeline addPackagedTimelineVideoFx:startPosition duration:_timeline.duration - startPosition videoFxPackageId:item.package];
            
            if (![self isPlaying])
                [self playbackTimeline:startPosition];
            
            _isAddingEffect = YES;
            _effectWrapper.colorBarView.timelineStartPosition = startPosition;
            float posX = _effectWrapper.sliderView.value * SCREANWIDTH;
            NSString *color = [NvUtils getEffectColor:item.package];
            [_effectWrapper.colorBarView addBar:posX width:0 color:color fxUuid:item.package];
        }
    } else if (recognizer.state == UIGestureRecognizerStateEnded) {
        [self resetLongPressStatus];
        if (!_isAddingEffect)
            return;
        
        [_streamingContext stop];
        int64_t endPosition = [_streamingContext getTimelineCurrentPosition:_timeline];
        if (endPosition <= _currentVideoFx.inPoint) {
            [_timeline removeTimelineVideoFx:_currentVideoFx];
            
            for (NvVideoFxData *data in _needRecovervVideoFxDataArray) {
                if (data.type == NvsTimelineVideoFxType_Builtin)
                    [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:data.duration videoFxName:data.package];
                else
                    [_timeline addPackagedTimelineVideoFx:data.inPoint duration:data.duration videoFxPackageId:data.package];
            }
            
            _isAddingEffect = NO;
            [self updateColorBarView];
            return;
        }
        
        [self seekTimeline:endPosition];
        [_currentVideoFx changeOutPoint:endPosition];
        [self finishAddVideoFx];
    }
}

- (void)resetLongPressStatus {
    for (int i = 0; i < _videoFxDataSource.count; i++) {
        NvFilterItem *item = _videoFxDataSource[i];
        if (item)
            item.longPressed = NO;
    }
    [_videoFxCollectionView reloadData];
}

- (void)finishAddVideoFx {
    // 恢复有效的其他部分时间线特效
    for (NvVideoFxData *data in _needRecovervVideoFxDataArray) {
        int64_t outPoint = data.inPoint + data.duration;
        if (outPoint > _currentVideoFx.inPoint && outPoint < _currentVideoFx.outPoint) {
            if (data.inPoint < _currentVideoFx.inPoint) {
                if (data.type == NvsTimelineVideoFxType_Builtin)
                    [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:_currentVideoFx.inPoint - data.inPoint videoFxName:data.package];
                else
                    [_timeline addPackagedTimelineVideoFx:data.inPoint duration:_currentVideoFx.inPoint - data.inPoint videoFxPackageId:data.package];
            }
        } else if (outPoint >= _currentVideoFx.outPoint) {
            if (data.inPoint < _currentVideoFx.inPoint) {
                if (data.type == NvsTimelineVideoFxType_Builtin) {
                    [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:_currentVideoFx.inPoint - data.inPoint videoFxName:data.package];
                    [_timeline addBuiltinTimelineVideoFx:_currentVideoFx.outPoint duration:outPoint - _currentVideoFx.outPoint videoFxName:data.package];
                } else {
                    [_timeline addPackagedTimelineVideoFx:data.inPoint duration:_currentVideoFx.inPoint - data.inPoint videoFxPackageId:data.package];
                    [_timeline addPackagedTimelineVideoFx:_currentVideoFx.outPoint duration:outPoint - _currentVideoFx.outPoint videoFxPackageId:data.package];
                }
            } else if (data.inPoint >= _currentVideoFx.inPoint && data.inPoint < _currentVideoFx.outPoint) {
                if (data.type == NvsTimelineVideoFxType_Builtin)
                    [_timeline addBuiltinTimelineVideoFx:_currentVideoFx.outPoint duration:outPoint - _currentVideoFx.outPoint videoFxName:data.package];
                else
                    [_timeline addPackagedTimelineVideoFx:_currentVideoFx.outPoint duration:outPoint - _currentVideoFx.outPoint videoFxPackageId:data.package];
            } else {
                if (data.type == NvsTimelineVideoFxType_Builtin)
                    [_timeline addBuiltinTimelineVideoFx:data.inPoint duration:data.duration videoFxName:data.package];
                else
                    [_timeline addPackagedTimelineVideoFx:data.inPoint duration:data.duration videoFxPackageId:data.package];
            }
        }
    }
    
    NSMutableArray *videoFxDataArray = [[NSMutableArray alloc] init];
    NvsTimelineVideoFx *timelineVideoFx = [_timeline getFirstTimelineVideoFx];
    while (timelineVideoFx) {
        NvVideoFxData *data = [[NvVideoFxData alloc] init];
        if (self.type == NvsTimeSpanType_Reverse)
            data.inPoint = _timeline.duration - timelineVideoFx.outPoint;
        else
            data.inPoint = timelineVideoFx.inPoint;
        data.duration = timelineVideoFx.outPoint - timelineVideoFx.inPoint;
        data.type = timelineVideoFx.timelineVideoFxType;
        if (data.type == NvsTimelineVideoFxType_Builtin)
            data.package = timelineVideoFx.bultinTimelineVideoFxName;
        else
            data.package = timelineVideoFx.timelineVideoFxPackageId;
        [videoFxDataArray addObject:data];
        timelineVideoFx = [_timeline getNextTimelineVideoFx:timelineVideoFx];
    }
    [_revertVideoFxDataArray addObject:videoFxDataArray];
    if (self.type == NvsTimeSpanType_Reverse)
        [_revertPositionArray addObject:[NSString stringWithFormat:@"%lld", _timeline.duration - _currentVideoFx.inPoint]];
    else
        [_revertPositionArray addObject:[NSString stringWithFormat:@"%lld", _currentVideoFx.inPoint]];
    
    _revertBtn.hidden = NO;
    
    NvVideoFxData *data = [[NvVideoFxData alloc] init];
    data.inPoint = _currentVideoFx.inPoint;
    data.duration = _currentVideoFx.outPoint - _currentVideoFx.inPoint;
    data.type = _currentVideoFx.timelineVideoFxType;
    if (data.type == NvsTimelineVideoFxType_Builtin)
        data.package = _currentVideoFx.bultinTimelineVideoFxName;
    else
        data.package = _currentVideoFx.timelineVideoFxPackageId;
    [_videoFxDataArray addObject:data];
    
    _isAddingEffect = NO;
    [self updateColorBarView];
}

- (void)timelineEditor:(id)timelineEditor draggingHandle:(int64_t)timestamp isInPoint:(bool)isInPoint {
    [self seekTimeline:timestamp];
}

- (void)timelineEditor:(id)timelineEditor dragHandleEnded:(int64_t)timestamp isInPoint:(bool)isInPoint {
    _hasModified = YES;
    [self recreateTimeline:_isFirstCreate];
//    NvsTimelineTimeSpanSticker *timeSpan = [_timelineEditor getSelectedTimeSpanSticker];
//    if (timeSpan.type == NvsTimeSpanType_Repeat) {
//        self.timelineVideoFxPos = timestamp;
//        [NvUtils doRepeatTimeline:timestamp videotrack:_videoTrack];
//    } else if (timeSpan.type == NvsTimeSpanType_Slow) {
//        self.timelineVideoFxPos = timestamp;
//        [NvUtils doSlowMotionTimeline:timestamp videotrack:_videoTrack];
//    }
    
    NvsVideoTrack *videoTrack = [_timeline getVideoTrackByIndex:0];
    for (int i = 0; i < videoTrack.clipCount; i++) {
        NvsVideoClip *videoClip = [videoTrack getClipWithIndex:i];
        [videoClip appendBuiltinFx:_recoverBuildFxName];
        [videoTrack setBuiltinTransition:i withName:@""];
    }
    
    [self copyCaptionsAndStickers];
    
    if (![_streamingContext connectTimeline:_timeline withLiveWindow:_liveWindow]) {
        NSLog(@"连接预览窗口失败！");
        return;
    }
    int64_t pos = timestamp - 1000000;
    if (pos < 0)
        pos = 0;
    [self seekTimeline:pos];
    [self playbackTimeline:pos];
}

- (void)timelineEditor:(id)timelineEditor dragTimeAxis:(int64_t)timestamp {
    if (self.type == NvsTimeSpanType_Reverse)
        [self seekTimeline:_timeline.duration - timestamp];
    else
        [self seekTimeline:timestamp];
}

- (void)updateColorBarView {
    [_effectWrapper.colorBarView clearCurrentArray];
    NvsTimelineVideoFx *videoFx = [_timeline getFirstTimelineVideoFx];
    while (videoFx) {
        int64_t inPoint = videoFx.inPoint;
        int64_t outPoint = videoFx.outPoint;
        NSString *fxUUID = videoFx.bultinTimelineVideoFxName;
        if (!fxUUID) {
            fxUUID = videoFx.timelineVideoFxPackageId;
        }
//        NSLog(@"updateColorBarView: %lld, %lld, %@, %lld", inPoint, outPoint, fxUUID, _timeline.duration);
        [_effectWrapper.colorBarView addToCurrentArray:fxUUID inPoint:inPoint outPoint:outPoint];
        
        videoFx = [_timeline getNextTimelineVideoFx:videoFx];
    }
    [_effectWrapper.colorBarView updateSubviewsByCurrentArray:self.type == NvsTimeSpanType_Reverse];
}

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

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
