//
//  VideoConvertor4.swift
//  tdvideo
//
//  Created by mac on 2024/2/22.
//

import UIKit


import Foundation
import AVKit
import VideoToolbox
import CoreImage
import ImageIO

class VideoConvertor4 {
    
   
    ///在立体视频中，正在处理的当前帧的左眼视图。
    var leftEyeImage: CVPixelBuffer?
    
    ///在立体视频中，正在处理的当前帧的右眼视图。
    var rightEyeImage: CVPixelBuffer?
    
    
    func convertVideo( asset : AVAsset, outputFile: URL, progress: ((Float)->())? = nil ) async throws {
        do {
            try FileManager.default.removeItem(atPath: outputFile.path)
            print("视频文件删除成功")
        } catch {
            print("删除视频文件出错：\(error)")
        }
        
        let assetReader = try AVAssetReader(asset: asset)
        
        
        //检查是否为空间视频 print("该视频不是空间视频或图片")
        let userDataItems = try await asset.loadMetadata(for:.quickTimeMetadata)
        let spacialCharacteristics = userDataItems.filter { $0.identifier?.rawValue == "mdta/com.apple.quicktime.spatial.format-version" }
        if spacialCharacteristics.count == 0 {
            print("不是空间视频")
        }
        
        //获取输入视频的方向和大小(用于设置输出方向)
        let (orientation, videoSize) = try await getOrientationAndResolutionSizeForVideo(asset: asset)
        
        //输出宽度为宽度的一半
        //我们有两个并排的视频，我们保持长宽比
        let vw:VideoWriter?
        vw = VideoWriter(url: outputFile, width: Int(videoSize.width), height: Int(videoSize.height), orientation: orientation, sessionStartTime: CMTime(value: 1,  timescale: 30 ), isRealTime: false, queue: .main)
        
        
        
        //加载音轨
        let output = try await AVAssetReaderTrackOutput(
            track: asset.loadTracks(withMediaType: .video).first!,
            outputSettings: [
                AVVideoDecompressionPropertiesKey: [
                    kVTDecompressionPropertyKey_RequestedMVHEVCVideoLayerIDs: [0, 1] as CFArray,
                ],
            ]
        )
        assetReader.add(output)
        assetReader.startReading()
        
        let duration = try await asset.load(.duration)
        
        while let nextSampleBuffer = output.copyNextSampleBuffer() {
            
            guard let taggedBuffers = nextSampleBuffer.taggedBuffers else { return }
            
            let leftEyeBuffer = taggedBuffers.first(where: {
                $0.tags.first(matchingCategory: .stereoView) == .stereoView(.leftEye)
            })?.buffer
            let rightEyeBuffer = taggedBuffers.first(where: {
                $0.tags.first(matchingCategory: .stereoView) == .stereoView(.rightEye)
            })?.buffer
           
            
            if let leftEyeBuffer,
               let rightEyeBuffer,
               case let .pixelBuffer(leftEyePixelBuffer) = leftEyeBuffer,
               case let .pixelBuffer(rightEyePixelBuffer) = rightEyeBuffer {
                
                leftEyeImage = leftEyePixelBuffer
                rightEyeImage = rightEyePixelBuffer
                
                let lciImage = CIImage(cvPixelBuffer: leftEyePixelBuffer)
                let rciImage = CIImage(cvPixelBuffer: rightEyePixelBuffer)
                
                let compositeFilter = CIFilter(name: "CIScreenBlendMode")!
                compositeFilter.setValue(lciImage, forKey: kCIInputImageKey)
                compositeFilter.setValue(rciImage, forKey: kCIInputBackgroundImageKey)
                let time = CMSampleBufferGetOutputPresentationTimeStamp(nextSampleBuffer)
                _ = vw!.add(image: compositeFilter.outputImage!, presentationTime: time)
                
                print( "Added frame at \(time)")
                progress?( Float(time.value)/Float(duration.value))
                try await Task.sleep(nanoseconds: 3_000_000)
                
            }
        }
        
        print( "status - \(assetReader.status)")
        print( "status - \(assetReader.error?.localizedDescription ?? "None")")
        print( "Finished")
        _ = try await vw!.finish()
        
        
    }
    
    
    func getOrientationAndResolutionSizeForVideo(asset:AVAsset) async throws -> (CGAffineTransform, CGSize) {
        guard let track = try await asset.loadTracks(withMediaType: AVMediaType.video).first
        else{throw VideoReaderError.invalidVideo}
        let naturalSize = try await track.load(.naturalSize)
        let naturalTransform = try await track.load(.preferredTransform)
        let size = naturalSize.applying(naturalTransform)
        return (naturalTransform, CGSize(width: abs(size.width), height: abs(size.height)) )
    }
    
    
}

