//
//  PlayContoller5.swift
//  tdvideo
//
//  Created by mac on 2024/2/2.
//


import UIKit
import AVFoundation
import Photos

class PlayContoller5: UIViewController, AVCaptureFileOutputRecordingDelegate {

    var session = AVCaptureMultiCamSession()
    var backCameraDeviceInput: AVCaptureDeviceInput?
    var frontCameraDeviceInput: AVCaptureDeviceInput?
    var backCameraVideoPreviewLayer: AVCaptureVideoPreviewLayer?
    var frontCameraVideoPreviewLayer: AVCaptureVideoPreviewLayer?
    var startRecordingButton: UIButton?
    var backCameraMovieOutput: AVCaptureMovieFileOutput?
    var frontCameraMovieOutput: AVCaptureMovieFileOutput?
    var isRecording = false

    var imgs:NSMutableArray = NSMutableArray()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white

        imgs.removeAllObjects()
        configureSession()
        setupUI()
    }

    private func configureSession() {
        session.beginConfiguration()
        defer {
            session.commitConfiguration()
        }
        
        //builtInWideAngleCamera
        //builtInWideAngleCamera
        //builtInTrueDepthCamera
        // 配置后置摄像头
        guard let backCamera = AVCaptureDevice.default(.builtInUltraWideCamera, for: .video, position: .back) else {
            print("Could not find the back camera")
            return
        }

        do {
            backCameraDeviceInput = try AVCaptureDeviceInput(device: backCamera)

            guard let backCameraDeviceInput = backCameraDeviceInput,
                  session.canAddInput(backCameraDeviceInput) else {
                print("Could not add back camera input")
                return
            }
            session.addInput(backCameraDeviceInput)
        } catch {
            print("Could not create back camera device input: \(error)")
            return
        }

        // 配置前置摄像头
        guard let frontCamera = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back) else {
            print("Could not find the main camera")
            return
        }

        do {
            frontCameraDeviceInput = try AVCaptureDeviceInput(device: frontCamera)

            guard let frontCameraDeviceInput = frontCameraDeviceInput,
                  session.canAddInput(frontCameraDeviceInput) else {
                print("Could not add front camera input")
                return
            }
            session.addInput(frontCameraDeviceInput)
        } catch {
            print("Could not create front camera device input: \(error)")
            return
        }
        
        // 配置音频输入设备
        guard let audioDevice = AVCaptureDevice.default(for: .audio) else {
            print("Could not find audio device")
            return
        }

        do {
            let audioDeviceInput = try AVCaptureDeviceInput(device: audioDevice)

            guard session.canAddInput(audioDeviceInput) else {
                print("Could not add audio input")
                return
            }

            session.addInput(audioDeviceInput)
        } catch {
            print("Could not create audio device input: \(error)")
            return
        }

        // 配置后置摄像头输出
        backCameraMovieOutput = AVCaptureMovieFileOutput()
        guard let backCameraMovieOutput = backCameraMovieOutput,
              session.canAddOutput(backCameraMovieOutput) else {
            print("Could not add the back camera movie output")
            return
        }
        session.addOutput(backCameraMovieOutput)

        // 配置前置摄像头输出
        frontCameraMovieOutput = AVCaptureMovieFileOutput()
        guard let frontCameraMovieOutput = frontCameraMovieOutput,
              session.canAddOutput(frontCameraMovieOutput) else {
            print("Could not add the front camera movie output")
            return
        }
        session.addOutput(frontCameraMovieOutput)

        // 配置预览图层
        backCameraVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
        backCameraVideoPreviewLayer?.frame = CGRect(x: 0, y: 0, width: view.frame.size.width / 2, height: view.frame.size.height / 2)
        if let backCameraVideoPreviewLayer = backCameraVideoPreviewLayer {
            view.layer.addSublayer(backCameraVideoPreviewLayer)
        }

        frontCameraVideoPreviewLayer = AVCaptureVideoPreviewLayer(session: session)
        frontCameraVideoPreviewLayer?.frame = CGRect(x: view.frame.size.width / 2, y: 0, width: view.frame.size.width / 2, height: view.frame.size.height / 2)
        if let frontCameraVideoPreviewLayer = frontCameraVideoPreviewLayer {
            view.layer.addSublayer(frontCameraVideoPreviewLayer)
        }

        DispatchQueue.global().async {
            self.session.startRunning()
        }
    }

    private func setupUI() {
        startRecordingButton = UIButton(type: .system)
        startRecordingButton?.setTitle("Start Recording", for: .normal)
        startRecordingButton?.setTitleColor(UIColor.brown, for: UIControl.State.normal)
        startRecordingButton?.addTarget(self, action: #selector(toggleRecording(_:)), for: .touchUpInside)
        startRecordingButton?.frame = CGRect(x: 0, y: view.frame.size.height - 250, width: view.frame.size.width, height: 50)
        view.addSubview(startRecordingButton!)
    }

    @objc private func toggleRecording(_ sender: UIButton) {
        startRecording()
    }

    private func startRecording() {
        
        imgs.removeAllObjects()
        guard let backCameraMovieOutput = backCameraMovieOutput,
              let frontCameraMovieOutput = frontCameraMovieOutput else {
            print("Movie output not configured")
            return
        }
        
        //快门声音
        let soundID: SystemSoundID = 1108
        AudioServicesPlaySystemSound(soundID)

        let time = Date().timeIntervalSince1970
        let name1 = "back" + String(time) + ".mov"
        let name2 = "front" + String(time) + ".mov"
        let backCameraOutputURL = URL.documentsDirectory.appending(path:name1)
        let frontCameraOutputURL = URL.documentsDirectory.appending(path:name2)

        backCameraMovieOutput.startRecording(to: backCameraOutputURL, recordingDelegate: self)
        frontCameraMovieOutput.startRecording(to: frontCameraOutputURL, recordingDelegate: self)

        //摄像头录像，取0.1秒长度，如果是拍摄照片去两张，拍摄成功会听到两次声音，所以这里用摄像的方式取图片
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
            self.stopRecording()
        }
    }

    private func stopRecording() {
        guard let backCameraMovieOutput = backCameraMovieOutput,
              let frontCameraMovieOutput = frontCameraMovieOutput else {
            print("Movie output not configured")
            return
        }

        backCameraMovieOutput.stopRecording()
        frontCameraMovieOutput.stopRecording()
    }

    func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
        if let error = error {
            print("Video recording finished with error: \(error.localizedDescription)")
        } else {
            if output == backCameraMovieOutput {
                print("Back camera video recorded: \(outputFileURL)")
                if let firstFrame = self.firstFrame(from: outputFileURL) {
//                    self.saveImageToLibrary(image: firstFrame)
                    imgs.add(firstFrame)
                }
            } else if output == frontCameraMovieOutput {
                print("Front camera video recorded: \(outputFileURL)")
                if let firstFrame = self.firstFrame(from: outputFileURL) {
//                    self.saveImageToLibrary(image: firstFrame)
                    imgs.add(firstFrame)
                }
            }
            if(imgs.count == 2){
                bbb()
            }
        }
    }
    
    private func firstFrame(from videoURL: URL) -> UIImage? {
        let asset = AVURLAsset(url: videoURL)
        let generator = AVAssetImageGenerator(asset: asset)
        generator.appliesPreferredTrackTransform = true
        let time = CMTime(seconds: 0.0, preferredTimescale: 1)
        do {
            let cgImage = try generator.copyCGImage(at: time, actualTime: nil)
            return UIImage(cgImage: cgImage)
        } catch {
            print("Error generating first frame: \(error.localizedDescription)")
            return nil
        }
    }

    private func saveImageToLibrary(image: UIImage) {
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.creationRequestForAsset(from: image)
        }) { success, error in
            if success {
                print("Image saved to library")
            } else if let error = error {
                print("Error saving image to library: \(error.localizedDescription)")
            }
        }
    }
    
    
    func bbb(){
        
        let img1:UIImage = imgs[0] as! UIImage
        let img2:UIImage = imgs[1] as! UIImage
        
        let imageSize1 = CGRect(x: 0, y: 0, width: img1.cgImage!.width, height: img1.cgImage!.height)
        let imageSize2 = CGRect(x: 0, y: 0, width: img2.cgImage!.width, height: img2.cgImage!.height)
        
       let url =   URL.documentsDirectory.appending(path:"aaa12.HEIC")
      
        let destination = CGImageDestinationCreateWithURL(url as CFURL, UTType.heic.identifier as CFString, 2, nil)!

        let properties1 = [
            kCGImagePropertyGroups: [
                kCGImagePropertyGroupIndex: 0,
                kCGImagePropertyGroupType: kCGImagePropertyGroupTypeStereoPair,
                kCGImagePropertyGroupImageIndexLeft: 0,
                kCGImagePropertyGroupImageIndexRight: 1,
            ],
            kCGImagePropertyHEIFDictionary: [
                kIIOMetadata_CameraExtrinsicsKey: [
                    kIIOCameraExtrinsics_CoordinateSystemID: 0,
                    kIIOCameraExtrinsics_Position: [
                        0,
                        0,
                        0
                    ],
                    kIIOCameraExtrinsics_Rotation: [
                        1, 0, 0,
                        0, 1, 0,
                        0, 0, 1
                    ]
                ]
            ]
        ]
        
        let properties2 = [
            kCGImagePropertyGroups: [
                kCGImagePropertyGroupIndex: 0,
                kCGImagePropertyGroupType: kCGImagePropertyGroupTypeStereoPair,
                kCGImagePropertyGroupImageIndexLeft: 0,
                kCGImagePropertyGroupImageIndexRight: 1,
            ],
            kCGImagePropertyHEIFDictionary: [
                kIIOMetadata_CameraExtrinsicsKey: [
                    kIIOCameraExtrinsics_CoordinateSystemID: 0,
                    kIIOCameraExtrinsics_Position: [
                        -0.019238,
                        0,
                        0
                    ],
                    kIIOCameraExtrinsics_Rotation: [
                        1, 0, 0,
                        0, 1, 0,
                        0, 0, 1
                    ]
                ]
            ]
        ]
        
        let leftImg = fixOrientation(img1)
        let rightImg = fixOrientation(img2)
        
        CGImageDestinationAddImage(destination, leftImg.cgImage!, properties1 as CFDictionary)
        CGImageDestinationAddImage(destination, rightImg.cgImage!, properties2 as CFDictionary)
        CGImageDestinationFinalize(destination)
        
        let image = UIImage(contentsOfFile: url.path())
        let source = CGImageSourceCreateWithURL(url as CFURL, nil)!
        guard let properties22 = CGImageSourceCopyPropertiesAtIndex(source, 1, nil) as? [CFString: Any] else {
                return
        }
        print(properties22)
        
        savePhoto(url)
        
    }
    
    func savePhoto(_ fileURL: URL) {
        
        // 创建 PHAssetCreationRequest
        PHPhotoLibrary.shared().performChanges({
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .photoProxy, fileURL: fileURL, options: nil)
                
        }) { success, error in
            if let error = error {
                print("Error saving photo to library: \(error.localizedDescription)")
            } else {
                print("Photo saved to library successfully.")
            }
        }
    }

    //修正图片的方向
    func fixOrientation(_ image: UIImage) -> UIImage {
        // No-op if the orientation is already correct
        guard image.imageOrientation != .up else { return image }
        
        // We need to calculate the proper transformation to make the image upright.
        // We do it in 2 steps: Rotate if Left/Right/Down, and then flip if Mirrored.
        var transform = CGAffineTransform.identity
        
        switch image.imageOrientation {
        case .down, .downMirrored:
            transform = transform.translatedBy(x: image.size.width, y: image.size.height)
            transform = transform.rotated(by: .pi)
        case .left, .leftMirrored:
            transform = transform.translatedBy(x: image.size.width, y: 0)
            transform = transform.rotated(by: .pi / 2)
        case .right, .rightMirrored:
            transform = transform.translatedBy(x: 0, y: image.size.height)
            transform = transform.rotated(by: -.pi / 2)
        default:
            break
        }
        
        switch image.imageOrientation {
        case .upMirrored, .downMirrored:
            transform = transform.translatedBy(x: image.size.width, y: 0)
            transform = transform.scaledBy(x: -1, y: 1)
        case .leftMirrored, .rightMirrored:
            transform = transform.translatedBy(x: image.size.height, y: 0)
            transform = transform.scaledBy(x: -1, y: 1)
        default:
            break
        }
        
        // Now we draw the underlying CGImage into a new context, applying the transform
        // calculated above.
        guard let cgImage = image.cgImage,
              let colorSpace = cgImage.colorSpace,
              let context = CGContext(data: nil,
                                      width: Int(image.size.width),
                                      height: Int(image.size.height),
                                      bitsPerComponent: cgImage.bitsPerComponent,
                                      bytesPerRow: 0,
                                      space: colorSpace,
                                      bitmapInfo: cgImage.bitmapInfo.rawValue)
        else {
            return image
        }
        
        context.concatenate(transform)
        
        switch image.imageOrientation {
        case .left, .leftMirrored, .right, .rightMirrored:
            // Grr...
            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: image.size.height, height: image.size.width))
        default:
            context.draw(cgImage, in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height))
        }
        
        // And now we just create a new UIImage from the drawing context
        guard let cgImageFixed = context.makeImage() else { return image }
        let fixedImage = UIImage(cgImage: cgImageFixed)
        return fixedImage
    }
}
