//
//  ZZHCustomPlayer.swift
//  SwiftProject
//
//  Created by aaa on 2024/4/16.
//

import Foundation
import UIKit
import AVKit

typealias CustomMaskViewTapCallback = ()->Void

class ZZHCustomPlayer: UIView {
    
    //点击maskview 的回调,主要用于方向旋转
    var maskViewTapCallback:CustomMaskViewTapCallback?
    //标记是否为横屏
    var isLandscape:Bool = false
    //视频资源
    var sourceVideoURL:URL?
    var assetTrack:AVAssetTrack?
    lazy var videoOriginalAsset:AVAsset = {
        let asset = AVAsset(url: sourceVideoURL!)
        return asset
    }()
    
    var assetReader:AVAssetReader?
    var assetOutput:AVAssetReaderTrackOutput?  {
        didSet {
        }
    }
    
    let videoTranserConvertor = PlayByTransferConvertor()
    var selectedIndex:SpatialType = .parallelEyes//记录当前选择的菜单选项
    {
        didSet{
            //进行相应解码操作，边解边播
        }
    }
    
    var playerIsSeeking:Bool = false//标记播放器是否正在拖动
    
    //操作maskview的相关配套属性
    var timerForMaskView:Timer?//标记隐藏倒计时
    var temScale:CGFloat = 1.0
    var currentScale:CGFloat = 1.0//当前缩放值
    var currentED:Int = 0//当前的瞳距
    let userdefaultValueKey_scale = "userdefaultValueKey_scale"
    let userdefaultValueKey_ed = "userdefaultValueKey_ed"
    
    //ui
    var playerLayerBgView:UIView?
    var avPlayer:AVPlayer?
    var avPlayerLayer:AVPlayerLayer?
    var timeSlider:ZZHCustomSlider?
    var edBtn:UIButton? //瞳距调节按钮
    
    var prePlayingState:Bool = true {//标记 在滑块拖动前,player的播放状态,以便在拖动完毕之后回复播放状态
        didSet {
            if(prePlayingState){
                playBtn.setImage(UIImage(named: "custom_pauseBtn"), for: .normal)
            }
            else{
                playBtn.setImage(UIImage(named: "custom_playBtn"), for: .normal)
            }
        }
    }
    let playerPauseBgColor:UIColor = UIColor(r: 20, g: 20, b: 20, a: 0.2)//暂停时的背景颜色
    let playerHeight = 230 //播放器默认高度
    
    lazy var maskPlayerView:UIView? = {//播放按钮 背景
        let bgView = UIView()
        bgView.isHidden = true
        bgView.backgroundColor = playerPauseBgColor
        bgView.addSubview(self.playBtn)
        
        self.playBtn.snp.makeConstraints { make in
            make.centerX.centerY.equalToSuperview()
            make.width.height.equalTo(80)
        }
        return bgView
    }()
    
    lazy var playBtn:UIButton = {
        let btn = UIButton()
        btn.addTarget(self, action: #selector(playOrPause(sender: )), for: .touchUpInside)
        btn.setImage(UIImage(named: "custom_playBtn"), for: .normal)
        return btn
    }()
    
    deinit {
        print("zzhcustomplayer deinit......")
        
        saveParams()
        releaseVideoComposition()
        assetReader?.cancelReading()
        NotificationCenter.default.removeObserver(self)
    }
    
    func saveParams(){
        UserDefaults.standard.setValue(currentScale, forKey: self.userdefaultValueKey_scale )
        UserDefaults.standard.setValue(currentED, forKey: self.userdefaultValueKey_ed)
        UserDefaults.standard.synchronize()
    }
    
    func releaseVideoComposition()  {
        self.avPlayer?.currentItem?.videoComposition = nil
        self.avPlayer?.replaceCurrentItem(with: nil)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        //提前初始化配置参数
        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()
        }
        
        NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil)
        
        let playerWidth = KScreenWidth
        
        playerLayerBgView = UIView()
        self.addSubview(playerLayerBgView!)
        playerLayerBgView!.snp.makeConstraints { make in
            make.left.right.equalToSuperview()
            make.centerY.equalToSuperview()
            make.height.equalTo(playerHeight)
        }
        avPlayer = AVPlayer()
//        avPlayer?.allowsExternalPlayback = true
//        avPlayer?.usesExternalPlaybackWhileExternalScreenIsActive = true
//        avPlayer?.externalPlaybackVideoGravity = .resizeAspect
        
        avPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: self.avPlayer?.currentItem?.duration.timescale ?? 600), queue: DispatchQueue.main, using: {[weak self] ct in
            self?.updateSliderUI(ct: ct)
        })
        
        avPlayerLayer = AVPlayerLayer(player: avPlayer)
        avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: Int(playerWidth), height: playerHeight)
        avPlayerLayer?.videoGravity = .resizeAspect
        playerLayerBgView!.layer.addSublayer(avPlayerLayer!)
//        playerLayerBgView?.backgroundColor = UIColor.red
//        self.backgroundColor = .orange
        //添加遮罩视图
        let mpBgView = UIView(frame: .zero)
        playerLayerBgView?.addSubview(mpBgView)
        mpBgView.snp.makeConstraints { make in
            make.left.top.bottom.right.equalToSuperview()
        }
        
        self.maskPlayerView?.frame = mpBgView.bounds
        mpBgView.addSubview(maskPlayerView!)
        maskPlayerView?.snp.makeConstraints { make in
            make.left.top.bottom.right.equalToSuperview()
        }
        
        let tgr = UITapGestureRecognizer(target: self, action: #selector(tapPlayerMaskView(sender: )))
        mpBgView.addGestureRecognizer(tgr)
        
        let pgr = UIPinchGestureRecognizer(target: self, action: #selector(panPlayerMaskView(sender: )))
        mpBgView.addGestureRecognizer(pgr)
        
        
        timeSlider = ZZHCustomSlider(frame: .zero)
        timeSlider?.processChangeValueCallback = {[weak self] (value,isMoving) in
            self?.manualToSeekPlay(value:value,isMoving: isMoving)
        }
        self.addSubview(timeSlider!)
        timeSlider!.snp.makeConstraints { make in
            make.left.equalToSuperview().offset(24)
//            make.right.equalToSuperview().offset(-24)
            make.bottom.equalToSuperview().offset(-30)
            make.height.equalTo(84)
        }
        
        edBtn = UIButton()
        edBtn?.setImage(UIImage(named: "custom_TuningBtn"), for: .normal)
        edBtn?.addTarget(self, action: #selector(showEDView(sender:)), for: .touchUpInside)
        self.addSubview(edBtn!)
        edBtn!.snp.makeConstraints { make in
            make.centerY.equalTo(timeSlider!.snp.centerY)
            make.width.height.equalTo(40)
            make.right.equalToSuperview().offset(-10)
            make.left.equalTo(timeSlider!.snp.right).offset(24)
        }
        
        
    }
    
    //屏幕旋转时自动隐藏timeSlider、edBtn,同时将播放layer设置为全屏
    func layoutViewWhenScreenLandscape(value:Bool) {
        if value {
            timeSlider?.isHidden = true
            edBtn?.isHidden = true
            playerLayerBgView?.snp.updateConstraints { make in
                make.height.equalTo(KScreenWidth)
            }
            self.layoutIfNeeded()
            avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: KScreenHeight, height: KScreenWidth)
        }
        else {
            timeSlider?.isHidden = false
            edBtn?.isHidden = false
            playerLayerBgView?.snp.updateConstraints { make in
                make.height.equalTo(KScreenWidth)
            }
            self.layoutIfNeeded()
            avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: Int(KScreenWidth), height: playerHeight)
        }
    }
    
    //显示调节瞳距、缩放的界面
    @objc func showEDView(sender:UIButton){
        CustomParamBoardView.showBoard(scaleCallback: {[weak self] scale in
            self?.currentScale = scale
        }, edCallback: {[weak self] ed in
            self?.currentED = ed
        },resetCallback:{[weak self] in
            self?.currentScale = 1.0
            self?.currentED = 0
        }, dismissCallback:{[weak self] in
            self?.saveParams()
        },scale: currentScale, ed: currentED)
    }
    
    //通过slider进行seek播放时间点
    func manualToSeekPlay(value:Float,isMoving:Bool){
        if isMoving {
            self.avPlayer?.pause()
        }
       
        let totalSec = CMTimeGetSeconds((self.avPlayer?.currentItem?.duration)!)
        var atSec = Float(totalSec) * value
        var timeScale:CMTimeScale? =  self.avPlayer?.currentItem?.duration.timescale
        if let ts = timeScale {
            atSec = atSec * Float(ts)
        }
        else {
            timeScale = CMTimeScale(1)
        }
        let ct = CMTime(value:CMTimeValue(atSec) , timescale: timeScale!)

        playerIsSeeking = true
        self.avPlayer?.seek(to: ct,toleranceBefore:.zero,toleranceAfter: .zero)
        if(!isMoving) {//结束拖动时,再进行播放
            self.play(true)
            self.playerIsSeeking = false
        }
        
    }
    
    
    //初始化播放器信息
    func setUPPlayer() {
        Task {[weak self] in
             await self?.loadVideoAssetReader()
            self?.avPlayer?.replaceCurrentItem(with: self?.getPlayerItem())
            self?.play(true)
            
        }
    }
    
    //重新播放 状态
    private func reLoadPlay(){
        self.quickLoadAReaderWhenReplayBack()
        self.play(true)
    }
    
    
    //改变avplayer所在的avplayerLayer视图曾层:用户外接屏幕发声改变时
    func moveToOtherPlayerLayer(destLayer:AVPlayerLayer) {
        self.play(false)
        self.avPlayerLayer?.player = nil
        destLayer.player = self.avPlayer
        self.play(true)
    }
    
    //当外接屏幕断开时,恢复到原来的layer层上
    func recoveryPlayerLayer(otherLayer:AVPlayerLayer) {
        self.play(false)
        otherLayer.player = nil
        avPlayerLayer?.player = self.avPlayer
        self.play(true)
    }
    
    //暂停或者播放
    @objc func playOrPause(sender:UIButton) {
        if prePlayingState == false {//播放
            play(true)
            print("bofang...")
        }
        else {//暂停
            print("暂停...")
            play(false)
        }
        
        iniTimerForMaskView()
    }
    
    //内、外部共同使用该play接口
    func play(_ value:Bool)  {
        if value {
            self.avPlayer?.play()
            prePlayingState = true
        }
        else {
            prePlayingState = false
            self.avPlayer?.pause()
        }
        
    }
    

    
    //根据状态更新播放器遮罩视图显示与隐藏
    func updatePlayMaskView(_ value:Bool) {
        maskPlayerView?.isHidden = value
        if value == false {
            iniTimerForMaskView()
        }
        else {
            resetTimerForMaskView()
        }
    }
    
    func iniTimerForMaskView()  {
        resetTimerForMaskView()
        timerForMaskView = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(hidenMaskViewTimerAction(sender: )), userInfo: nil, repeats: false)
        RunLoop.main.add(timerForMaskView!, forMode: .common)

    }
    
    func resetTimerForMaskView() {
        if let td = timerForMaskView {
            td.invalidate()
            timerForMaskView = nil
        }
    }
    
    @objc func hidenMaskViewTimerAction(sender:CADisplayLink) {
        maskPlayerView?.isHidden = true
        resetTimerForMaskView()
    }
    
    //点击了player 的maskview
    @objc func tapPlayerMaskView(sender:UITapGestureRecognizer)  {
        updatePlayMaskView(!(maskPlayerView!.isHidden))
        if isLandscape {
            if let mcallback = maskViewTapCallback {
                mcallback()
            }
            self.timeSlider?.isHidden = !self.timeSlider!.isHidden
            self.edBtn?.isHidden = !self.edBtn!.isHidden
        }
        
    }
    
    //缩放手势 正在player的maskview进行缩放
    @objc func panPlayerMaskView(sender:UIPinchGestureRecognizer) {
        
        if sender.state == .began {
            temScale = 1.0
        }
        
        currentScale = currentScale - (temScale - sender.scale)
        currentScale = min(currentScale, 1.8)
        currentScale = max(currentScale, 0.3)
        temScale = sender.scale
        print("\(sender.scale)    currentScale....\(currentScale)")
    }
    
    //根据播放进度更新slider的 ui
    func updateSliderUI(ct:CMTime) {
        let sec = CMTimeGetSeconds(ct)
        let totalSec = CMTimeGetSeconds((self.avPlayer?.currentItem?.duration)!)
        if totalSec.isNaN {
           return
        }
        let s = sec / totalSec
        self.timeSlider?.exUpdateProcessValue(value: Float(s),currSec: Int(sec),totalSec: Int(totalSec))
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    
    
    //MARK: - 播放器控制
    
    //监听播放完毕
    @objc func notification_PlayerEndTime(notification:Notification){
        avPlayer?.seek(to: .zero,toleranceBefore: .zero,toleranceAfter: .zero,completionHandler: {[weak self] finish in
            self?.reLoadPlay()
        })
    }
}
