//
//  CCSpatialPhotoDisplayController.swift
//  SwiftProject
//
//  Created by Zhang, Joyce on 2024/3/2.
//

import UIKit
import AVFoundation
import VideoToolbox
import CoreVideo
import UIKit
import ImageIO
import CoreImage
import Photos
import SVProgressHUD
import Firebase
enum VideoReaderError : Error {
    case invalidVideo
    case notSpacialVideo
}

class CCSpatialPhotoDisplayController: BaseController {
    let kNowTimeToUserDefaultKey_PhotoDisplayController:String = "kNowTimeToUserDefaultKey_PhotoDisplayController"
    //标记是否为横屏
    var isLandscape:Bool = false
    var externalVC:ZZHExternalViewController?
    var externalDispalylink:CADisplayLink?
    var externalImageView:UIImageView?
    
    var outputVideoURL:URL?
    var dvc:UIDocumentViewController?
    
    //图片源数据
//    var photoOriginalURL:URL?
    var photoOriginalData:Data?
    var imageAsset:PHAsset?
    
    var imgData:Data?
    var imgOritentation:UIImage.Orientation = .left
    //空间视频 交叉眼 红蓝立体 高斯模糊
    var type = 0
    
    //增加一个瞳距、缩放的调节按钮
    var edBtn:UIButton?
    var temScale:CGFloat = 1.0
    var currentScale:CGFloat = 1.0 {//当前缩放值
        didSet {
            if imgData != nil {
                selectedSpatialType(selectedIndex: currentSpatialType)
            }
        }
    }
    var currentED:Int = 0{//当前的瞳距
        didSet {
            if imgData != nil {
                selectedSpatialType(selectedIndex: currentSpatialType)
            }
        }
    }
    var currentSpatialType = 0{//标记当前选中的浏览种类
        didSet{
            redBlueImage = nil
        }
    }
    
    //保留红蓝立体的uiimage
    var redBlueImage:UIImage?
    
    //标记是否正在串流中:目前就是用于控制是否显示瞳距调节的slider部分
    var isPlayingOnExternalScreen = false
    
    lazy var mTopImgView:UIImageView = {
        //393*236
        let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height:236))
        
        view.image = UIImage.init(named: "BG_Top")
        return view
    }()
    
    lazy var tipsButton: UIButton = {
        
        //76*56
        let button = UIButton.init(type: UIButton.ButtonType.custom)
        button.tag = 203
        button.backgroundColor = .clear
        button.addTarget(self, action: #selector(showTipsView(sender:)), for: UIControl.Event.touchUpInside)
        let img2:UIImage = UIImage.init(named:  NSLocalizedString("displayvc_desc", comment: ""))!
        button.setImage(img2, for: UIControl.State.normal)
        button.frame = CGRect(x: 0, y: 0, width: 173, height: 42)
        button.centerY = KScreenHeight - 120
        button.centerX = self.view.centerX
        
        return button
    }()
    
    
    lazy var transformButton: UIButton = {
        
        //76*56
        let transformButton = UIButton.init(type: UIButton.ButtonType.custom)
        
        transformButton.tag = 201
        transformButton.isSelected = false
        transformButton.backgroundColor = UIColor(hexString: "#5326D6")
        transformButton.addTarget(self, action: #selector(navgationButtonClick2(sender:)), for: UIControl.Event.touchUpInside)
        let img2:UIImage = UIImage.init(named: "transform_button" as String)!
        transformButton.setImage(img2, for: UIControl.State.normal)
        transformButton.frame = CGRect(x: 0, y: 0, width: 56, height: 36)
        transformButton.layer.cornerRadius = 18
        transformButton.layer.masksToBounds = true
        transformButton.centerY = StatuBar_Height + NavBar_Height * 0.5
        transformButton.right = SCREEN_Width - 24
        
        return transformButton
    }()
    
    lazy var mTopCenterTypeButton: UIButton = {
        //173*36
        let button = UIButton()
        button.backgroundColor = UIColor.hexStringToColor(hexString: "#1F1E20")
        button.tag = 202
        button.isSelected = false
        button.addTarget(self, action: #selector(navgationButtonClick2(sender:)), for: UIControl.Event.touchUpInside)
        button.frame = CGRect(x: 2, y: 10, width: SCREEN_Width * 0.4 + 20, height: 36)
        button.centerY = StatuBar_Height + NavBar_Height * 0.5
        button.centerX = SCREEN_Width * 0.5
        button.clipsToBounds = true
        button.layer.cornerRadius = 18
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.white.cgColor
        button.setTitle(NSLocalizedString("平行眼", comment: ""), for: UIControl.State.normal)
        button.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal)
        
        button.setTitleColor(UIColor.white, for: UIControl.State.normal)
        button.titleLabel?.font = KFont_Medium(14)
        button.updateBtnEdgeInsets(style: .Right, space: 10)
        return button
    }()
    
    let imgH = 340.0
    
    lazy var mImgView:UIImageView = {
        
        let imageView = UIImageView()
        imageView.frame = CGRect.init(x: 0, y: 250, width: self.view.frame.size.width, height: imgH)
        imageView.contentMode = .scaleAspectFit
        imageView.backgroundColor = UIColor.black
        
        imageView.isUserInteractionEnabled = true
        return imageView
    }()
    
    lazy var imgMaskView:UIView = {
       return UIView()
    }()
    
    var typeData:[(icon:String,title:String,isHiden:Bool)] = [(icon:"type_check",title:NSLocalizedString("平行眼", comment: ""),isHiden:false),
                                                              (icon:"type_check",title:NSLocalizedString("单眼2D", comment: ""),isHiden:false),
                                                              
                                                              (icon:"type_check",title:NSLocalizedString("红蓝立体", comment: ""),isHiden:false),
                                                              (icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
    
    lazy var menuView: CCSpatialDisplayTypeView = {
        //数据源（icon可不填）
        
        //设置参数
        let parameters:[CCSpatialDisplayTypeConfigure] = [
            .PopMenuTextColor(UIColor.white),
            .popMenuItemHeight(40),
            .PopMenuTextFont(KFont_Medium(12)),
            .PopMenuBackgroudColor(UIColor(hexString: "#1F1E20"))
        ]
        
        
        //init  (test随机生成点位置，注意：arrow点是基于屏幕的位置)
        let pointOnScreen = navtionImgView!.convert(CGPointMake(navtionImgView!.centerX, navtionImgView!.bottom), to: KWindow)
        let popMenu = CCSpatialDisplayTypeView(menuWidth: mTopCenterTypeButton.width, arrow: pointOnScreen, datas: typeData,configures: parameters){ [weak self] in
            //dissmiss回调
            self?.mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal)
        }
        return popMenu
    }()
    
    var isAirPlayActive:Bool = false {
        didSet{
            //更新串流UI
            setttinisScreenMirroring(isScreenMirroring: isAirPlayActive)
            isPlayingOnExternalScreen = isAirPlayActive
        }
    }
    
    
    deinit  {
        print("spatioal photo display deinit...\(self)")
        NotificationCenter.default.removeObserver(self)
        // 停止监听设备方向变化
        UIDevice.current.endGeneratingDeviceOrientationNotifications()
        externalDispalylink?.invalidate()
    }
    
    
    // 开始监听设备方向变化
    func listingScreenOrientatinChange()  {
            UIDevice.current.beginGeneratingDeviceOrientationNotifications()
            // 添加监听器
        NotificationCenter.default.addObserver(self, selector: #selector(screenOrientationRotate), name: UIDevice.orientationDidChangeNotification, object: nil)
    }
    
    @objc func screenOrientationRotate() {
        let orientation = UIDevice.current.orientation
        switch orientation {
        case .portrait , .portraitUpsideDown:
            isLandscape = false
            print("Portrait")
            navtionBar?.snp.updateConstraints { make in
                make.top.equalToSuperview().offset(0)
            }
            mImgView.snp.updateConstraints { make in
                make.height.equalTo(imgH)
            }
            edBtn!.snp.updateConstraints { make in
                make.centerY.equalTo((edBtn?.superview!.snp.bottom)!).offset( -120)
            }
            self.view.layoutIfNeeded()
            self.navtionBar?.isHidden = false
            mTopImgView.isHidden = false
            edBtn?.isHidden = false
            menuView.isLandspaceScreen = false
            menuView.dismiss()
            let pointOnScreen = navtionImgView!.convert(CGPointMake(KScreenWidth*0.5, navtionImgView!.bottom), to: KWindow)
            menuView.exUpdateArrowPointWithIsLandspace(pointOnScreen)
            break
        case .landscapeLeft , .landscapeRight:
            isLandscape = true
            menuView.isLandspaceScreen = true
            menuView.dismiss()
            let pointOnScreen = navtionImgView!.convert(CGPointMake(KScreenHeight*0.5, navtionImgView!.bottom), to: KWindow)
            menuView.exUpdateArrowPointWithIsLandspace(pointOnScreen)
            print("Landscape ...")
            navtionBar?.snp.updateConstraints { make in
                make.top.equalToSuperview().offset(-30)
            }
            
            edBtn!.snp.updateConstraints { make in
                make.centerY.equalTo((edBtn?.superview!.snp.bottom)!).offset( -50)
            }
            
            mImgView.snp.updateConstraints { make in
                make.height.equalTo(KScreenWidth)
            }
            self.view.layoutIfNeeded()
            self.navtionBar?.isHidden = true
            mTopImgView.isHidden = true
            edBtn?.isHidden = true
            break
        default:
            print("Other")
        }
        
        
    }
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //提前初始化配置参数
        if let defaultScale = UserDefaults.standard.value(forKey: userdefaultValueKey_scale) as? CGFloat {
            currentScale = defaultScale
        }
        else {
            UserDefaults.standard.setValue(currentScale, forKey: userdefaultValueKey_scale)
            UserDefaults.standard.synchronize()
        }
        
        if let defaultED = UserDefaults.standard.value(forKey: userdefaultValueKey_ed) as? Int {
            currentED = defaultED
        }
        else{
            UserDefaults.standard.setValue(currentED, forKey: userdefaultValueKey_ed)
            UserDefaults.standard.synchronize()
        }
        
        KAppDelegate?.allowRotation = true
        listingScreenOrientatinChange()
        updateNavgationBarColorImgMakeConstraint()
        
        ZZHHelper.setNowTimeToUserDefaultWithKey(kNowTimeToUserDefaultKey_PhotoDisplayController)
        print("spatioal photo viewdidload...\(self)")
//        return
        //添加外接屏幕链接通知
        NotificationCenter.default.addObserver(self, selector: #selector(exScreenWillConnectNotification(notification:)), name: UIScene.willConnectNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(exScreenDisConnectNotification(notification:)), name: UIScene.didDisconnectNotification, object: nil)
        
        
        // 监听 AirPlay 设备的连接状态
//        NotificationCenter.default.addObserver(self, selector: #selector(airPlayStatusDidChange(notification:)), name: AVAudioSession.routeChangeNotification, object: nil)
        
        self.view.backgroundColor = UIColor(hexString: "#060507")
        outputVideoURL = URL.documentsDirectory.appending(path:"output11114.jpg")
        
        //获取图片源数据
        var originalData:Data?
        originalData = photoOriginalData

        imgData = originalData
        //展示
        let image = UIImage(data: originalData!)
//        mImgView.image = image
        imgOritentation = image?.imageOrientation ?? .left
        selectedSpatialType(selectedIndex: currentSpatialType)
        let isSpatial = isSpatialImage(originalData: originalData!)
        if !isSpatial {
            print("这不是一张空间图片")
            return
        }
        
        //设置返回按钮图片
        self.setLeftOneBtnImg(imgStr: "spatial_back_button")
//        self.setLeftBtnImg(imgStr1: "", imgStr2: "spatial_back_button")
        self.setNavgationBarColorImg(color: .clear)
        self.setNavgationBarLine(color: .clear)
        
        self.view.addSubview(mTopImgView)
        mTopImgView.snp.makeConstraints { make in
            make.left.right.top.equalToSuperview()
            make.height.equalTo(236)
        }
        self.view.bringSubviewToFront(self.navtionBar!)
        //        navtionBar?.addSubview(backButton)
        navtionBar?.addSubview(transformButton)
        transformButton.snp.makeConstraints { make in
            make.width.equalTo(56)
            make.height.equalTo(36)
            make.right.equalToSuperview().offset(-14)
            make.centerY.equalToSuperview().offset(StatuBar_Height*0.5)
        }
        navtionBar?.addSubview(mTopCenterTypeButton)
        mTopCenterTypeButton.snp.makeConstraints { make in
            make.height.equalTo(36)
            make.width.equalTo(SCREEN_Width * 0.4 + 20)
            make.centerX.equalToSuperview()
            make.centerY.equalToSuperview().offset(StatuBar_Height*0.5)
        }
        self.view.addSubview(mImgView)
        mImgView.snp.makeConstraints { make in
            make.left.right.equalToSuperview()
            make.height.equalTo(imgH)
            make.centerY.equalToSuperview()
        }
        self.view.addSubview(imgMaskView)
        imgMaskView.snp.makeConstraints { make in
            make.left.top.right.bottom.equalTo(mImgView)
        }
        imgMaskView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tapPlayerMaskView(sender: ))))
        imgMaskView.addGestureRecognizer(UIPinchGestureRecognizer(target: self, action: #selector(pinchPlayerMaskView(sender: ))))
        self.view.addSubview(tipsButton)
        
        edBtn = UIButton()
        edBtn?.setImage(UIImage(named: "custom_TuningBtn"), for: .normal)
        edBtn?.addTarget(self, action: #selector(showEDView(sender:)), for: .touchUpInside)
        self.view.addSubview(edBtn!)
        edBtn!.snp.makeConstraints { make in
            make.centerY.equalTo((edBtn?.superview!.snp.bottom)!).offset( -120)
//            make.bottom.equalToSuperview().offset(-70)
            make.width.height.equalTo(40)
            make.right.equalToSuperview().offset(-20)
        }
        
        
        checkAirPlayStatus()
        
        
        
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        KAppDelegate?.allowRotation = false
        self.setNeedsUpdateOfSupportedInterfaceOrientations()
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey(kNowTimeToUserDefaultKey_PhotoDisplayController)
        Analytics.logEvent("preview_pv", parameters: ["refer_page":"图片预览页面","duration":sec])
    }
    
    @objc func showTipsView(sender:UIButton) {
        //tips
        let view = CCDeviceOperationListView.init(frame: CGRectMake(0, 0, KScreenWidth, KScreenHeight))
        KWindow?.addSubview(view)
    }
    //MARK: - 外接屏幕 链接 与 断开
    @objc func exScreenWillConnectNotification(notification:Notification){
        print("exScreenWillConnectNotification>>>>>")
        airPlayStatusDidChange(notification: notification)
    }
    
    @objc func exScreenDisConnectNotification(notification:Notification){
        print("exScreenDisConnectNotification>>>>>")
        airPlayStatusDidChange(notification: notification)
    }
    
    func airPlayStatusDidChange(notification:Notification) {
        checkAirPlayStatus()
        
        if(isAirPlayActive) {
            Analytics.logEvent("streaming_live", parameters: ["refer_page":"图片预览页面"])
            ZZHHelper.setNowTimeToUserDefaultWithKey("kNowTimeToUserDefaultKey_PhotoDisplayController_airplay")
        }
        else {
            let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey("kNowTimeToUserDefaultKey_PhotoDisplayController_airplay")
            Analytics.logEvent("streaming_live", parameters: ["refer_page":"图片预览页面","duration":sec])
        }
    }

    
    private func checkAirPlayStatus() {
        print("设备连接变化 photodisplaycontroller>>>>>")
        let currentRoute = AVAudioSession.sharedInstance().currentRoute
        self.isAirPlayActive = currentRoute.outputs.contains { output in
            return output.portType == AVAudioSession.Port.HDMI ||
            output.portType == AVAudioSession.Port.airPlay
        }
    }
    
    func setttinisScreenMirroring(isScreenMirroring:Bool){
        //已连接
        if(isScreenMirroring){
            print("变化为已连接。。。。")
            UIApplication.shared.connectedScenes.forEach { us in
                print("uisence:\(us)\n")
                let ws = us as! UIWindowScene
                if ws.session.role.rawValue == "UIWindowSceneSessionRoleExternalDisplayNonInteractive"{
                    externalVC = ws.windows.first?.rootViewController as? ZZHExternalViewController
                    externalDispalylink = ws.windows.first?.screen.displayLink(withTarget: DisplayLinkProxy.with(target: self), selector: #selector(displayUpdate(caDisplayLink:)))
                    externalDispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
                    externalVC?.imageView?.isHidden = false
                    externalVC?.playerLayer?.isHidden = true
                }
            }
        }
        else{
            print("变化为 断开。。。。")
            externalVC = nil
            externalDispalylink?.invalidate()
            externalDispalylink = nil
        }
    }
    

    
    @objc func displayUpdate(caDisplayLink:CADisplayLink) {
        if let has_exvc = externalVC {
            has_exvc.imageView?.image = mImgView.image
        }
        
    }
    
    
    //MARK: - action
    @objc public func navgationButtonClick2(sender:UIButton){
        
        if sender.tag == 200 {
            //左边按钮
        }else if sender.tag == 201 {
            //右边按钮
            let orientation = UIDevice.current.orientation
            if orientation == .landscapeLeft || orientation == .landscapeRight {
                KAppDelegate?.allowRotation = false
                self.setNeedsUpdateOfSupportedInterfaceOrientations()
                DispatchQueue.main.asyncAfter(deadline: .now()+0.25, execute: {[weak self] in
                    //右边按钮
                    let transVC = VRPhotoTransformController()
                    transVC.sourceImageData = self?.photoOriginalData
                    transVC.imageAsset = self?.imageAsset
                    self?.navigationController?.pushViewController(transVC, animated: true)
                })
            }
            else {
                let transVC = VRPhotoTransformController()
                transVC.sourceImageData = photoOriginalData
                transVC.imageAsset = imageAsset
                self.navigationController?.pushViewController(transVC, animated: true)
            }
            
            
            
            
            
            Analytics.logEvent("preview_trans_click", parameters: nil)
        }else if sender.tag == 202 {
            //中间按钮
            mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_up"), for: .normal)
            menuView.show()
            
            //click
            menuView.didSelectMenuBlock = { [weak self](index:Int)->Void in
                print("block select \(index)")
                self?.mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal)
                self?.selectedSpatialType(selectedIndex: index)
                let title = self?.typeData[index].title
                self?.mTopCenterTypeButton.setTitle(title, for: UIControl.State.normal)
            }
        }
    }
    
    func selectedSpatialType(selectedIndex:Int) {
        // 处理分段选择器值改变事件
        currentSpatialType = selectedIndex
//        print("选中了第 \(selectedIndex) 个选项")

        if(selectedIndex == 1){
            //空间照片 --- 单眼2D(展示原照片或者广角或者主摄其中一个)
            let image = UIImage(data: photoOriginalData!)
            monocular2DImgWith(drawImg: image!, scale: currentScale,callback: {[weak self] image in
                self?.mImgView.image = image
            })
            
        }else {
            guard let imageSource = CGImageSourceCreateWithData(imgData! as CFData, nil) else {
                return
            }

            let frameCount = CGImageSourceGetCount(imageSource)
            var frames: [CGImage] = []
            for index in 0..<frameCount {
                guard let frameImage = CGImageSourceCreateImageAtIndex(imageSource, index, nil) else {
                    continue
                }
                frames.append(frameImage)
            }
            
            if(frames.count < 2){return}
            let lciImage = CIImage(cgImage: frames.first!)
            let rciImage = CIImage(cgImage: frames[1])
            if(selectedIndex == 0){
                //平行眼
                
                let newpb = joinImages(leftImage: lciImage, rightImage: rciImage, scale: currentScale, ed: currentED)
                let lastImg = UIImage(ciImage: newpb)
                self.mImgView.image = lastImg
                
            }else if(selectedIndex == 2){//红蓝立体
               
                var ri = joinImages_red_blue(lciImage: lciImage, rciImage: rciImage, scale: currentScale,rbImage: redBlueImage)
//                ri = ri.getUpImg(imgOrigOritentation: self.imgOritentation )
                redBlueImage = ri
                self.mImgView.image = ri
                   
                
            }else if(selectedIndex == 3){
                //交叉眼
                let newpb = joinImages(leftImage: rciImage , rightImage:lciImage , scale: currentScale, ed: currentED)
                let lastImg = UIImage(ciImage: newpb)
                    self.mImgView.image = lastImg
            }
        }
    }
    
    //MARK: - 判断是不是空间照片
    //判断是不是空间照片 非空间照片只有一帧
    //空间照片包含 let makerAppleProperties = imageProperties["{HEIF}"]
    func isSpatialImage(originalData: Data) -> Bool {
        //通过data获取
        guard let imageSource = CGImageSourceCreateWithData(originalData as CFData, nil) else {
            return false
        }
        
        //通过url获取
        guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 1, nil) as? [CFString: Any] else {
            return false
        }
        print(properties)
        return true
    }
    
    //MARK: - 判断是不是空间照片
    func createCVPixelBuffer(from image: UIImage, with frame: CGRect) -> CVPixelBuffer? {
        let options: [String: Any] = [
            kCVPixelBufferCGImageCompatibilityKey as String: true,
            kCVPixelBufferCGBitmapContextCompatibilityKey as String: true
        ]
        
        var pixelBuffer: CVPixelBuffer?
        let status = CVPixelBufferCreate(kCFAllocatorDefault,
                                         Int(frame.width),
                                         Int(frame.height),
                                         kCVPixelFormatType_32BGRA,
                                         options as CFDictionary,
                                         &pixelBuffer)
        
        guard status == kCVReturnSuccess, let buffer = pixelBuffer else {
            return nil
        }
        
        CVPixelBufferLockBaseAddress(buffer, [])
        let pixelData = CVPixelBufferGetBaseAddress(buffer)
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        
        guard let context = CGContext(data: pixelData,
                                      width: Int(frame.width),
                                      height: Int(frame.height),
                                      bitsPerComponent: 8,
                                      bytesPerRow: CVPixelBufferGetBytesPerRow(buffer),
                                      space: colorSpace,
                                      bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue) else {
            return nil
        }
        
        context.translateBy(x: -frame.origin.x, y: -frame.origin.y)
        context.draw(image.cgImage!, in: CGRect(origin: .zero, size: image.size))
        
        CVPixelBufferUnlockBaseAddress(buffer, [])
        
        return buffer
    }
    

    
    
    
    
    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)) )
    }
    
    
    
}
