//
//  PQStuckPointMusicController.swift
//  PQSpeed
//
//  Created by SanW on 2021/4/28.
//  Copyright © 2021 BytesFlow. All rights reserved.
//

import AVFoundation
import UIKit
import Photos
import BFCommonKit

class PQStuckPointMusicController: PQBaseViewController {
    // 选中的总时长
    var selectedTotalDuration: Float64 = 0
    // 选择的总数
    var selectedDataCount: Int = 0
    // 选择的图片总数
    var selectedImageDataCount: Int = 0
    weak var stuckPointEditVC : PQStuckPointEditerController?
    var firstFrameImage:UIImage?
    // 选中的素材数据
    var selectedPhotoData: [PHAsset]?{
        didSet {
            if selectedPhotoData != nil && selectedPhotoData!.count > 0 {
                let photo = selectedPhotoData!.first!
                let option = PHImageRequestOptions()
                option.isNetworkAccessAllowed = true //允许下载iCloud的图片
                option.resizeMode = .none
                option.deliveryMode = .highQualityFormat
                let startTime = Date()
                PHImageManager.default().requestImage(for: photo,
                                                      targetSize: CGSize(width: 1920, height: 1920),
                                                      contentMode: .aspectFit,
                                                      options: option)
                { (image, nil) in
                     //image就是图片
                    if image != nil {
                        self.firstFrameImage = image
                        if self.stuckPointEditVC != nil {
                            self.stuckPointEditVC?.firstFrameImage = image
                        }
                        
//                        BFLog(1, message: "aaa: \(Date().timeIntervalSince(startTime)), \(String(describing: image?.size))")
                    }
                }
            }
        }
    }
    // 选中的音乐数据
    var selectedMusicData: PQVoiceModel?
    /// 缓存数据
    /// ["tagId":
    ///         [
    ///         "tagInfo":([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat)),
    ///         "pageList":[PQVoiceModel],
    ///         "currentTag": PQStuckPointMusicTagsModel
    ///         ]
    /// ]
    var cacheMusicData: [String: [String: Any]] = Dictionary<String, [String: Any]>.init()
    // 热搜数据
    var hotList: [Any] = Array<Any>.init()
    // 左边距离
    let leftMargin: CGFloat = 16
    // 搜索拦高度
    let searchTFH: CGFloat = 37
    // 当前页码
    var pageNum: Int = 0
    // 当前标签信息-如果是热门则为空
    var tagData: PQStuckPointMusicTagsModel?
    // 当前播放的音乐
    var currentPlayData: PQVoiceModel?
    // 当前播放的视频
    var playerItem: AVPlayerItem?

    public var reCreateVideoData: PQReCreateModel? // 再创作数据
    lazy var avPlayer: AVPlayer = {
        let avPlayer = AVPlayer()
        PQNotification.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: avPlayer.currentItem, queue: .main) { [weak self] notify in
            BFLog(message: "AVPlayerItemDidPlayToEndTime = \(notify)")
            avPlayer.seek(to: CMTime(value: CMTimeValue((self?.currentPlayData?.startTime ?? 0) * 1000), timescale: CMTimeScale(playerTimescale)))
//            avPlayer.play()
            self?.playStuckPointMusic(itemData: nil)
        }
        PQNotification.addObserver(forName: .AVPlayerItemNewErrorLogEntry, object: avPlayer.currentItem, queue: .main) { notify in
            BFLog(message: "AVPlayerItemNewErrorLogEntry = \(notify)")
        }
        PQNotification.addObserver(forName: .AVPlayerItemFailedToPlayToEndTime, object: avPlayer.currentItem, queue: .main) { notify in
            BFLog(message: "AVPlayerItemFailedToPlayToEndTime = \(notify)")
        }
        PQNotification.addObserver(forName: .AVPlayerItemPlaybackStalled, object: avPlayer.currentItem, queue: .main) { notify in
            BFLog(message: "AVPlayerItemPlaybackStalled = \(notify)")
        }
        avPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: CMTimeScale(playerTimescale)), queue: .main) { [weak self] cmTime in
            BFLog(message: "addPeriodicTimeObserver = \(cmTime)")
        }
        return avPlayer
    }()

    // 输入框清空按钮
    lazy var clearBtn: UIButton = {
        let clearBtn = UIButton(type: .custom)
        clearBtn.setImage(UIImage.moduleImage(named: "icon_search_delete", moduleName: "BFFramework",isAssets: false), for: .normal)
        clearBtn.frame = CGRect(x: 0, y: 0, width: 28, height: 32)
        clearBtn.tag = 1
        clearBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
        clearBtn.isHidden = true
        return clearBtn
    }()

    // 搜索框
    lazy var searchTF: UITextField = {
        let searchTF = UITextField(frame: CGRect(x: leftMargin, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth - leftMargin * 2, height: searchTFH))
        searchTF.font = UIFont.systemFont(ofSize: 17)
        searchTF.backgroundColor = PQBFConfig.shared.otherTintColor
        searchTF.attributedPlaceholder = NSAttributedString(string: "搜索歌曲名称/歌手", attributes: [.foregroundColor: UIColor.hexColor(hexadecimal: "#BDBDBD"), .font: UIFont.systemFont(ofSize: 14)])
        searchTF.textColor = PQBFConfig.shared.styleTitleColor
        searchTF.addCorner(corner: searchTFH / 2)

        searchTF.leftViewMode = .always
        let leftView = UIView(frame: CGRect(x: 0, y: 0, width: 35, height: 32))
        let imageView = UIImageView(image:UIImage.moduleImage(named: "icon_search_s", moduleName: "BFFramework",isAssets: false))
        imageView.frame = CGRect(x: 15, y: 8, width: 16, height: 16)
        leftView.addSubview(imageView)
        searchTF.leftView = leftView
        searchTF.delegate = self

        searchTF.rightViewMode = .always
        let rightView = UIView(frame: CGRect(x: 0, y: 0, width: 40, height: 32))
        rightView.addSubview(clearBtn)
        searchTF.rightView = rightView
        searchTF.delegate = self
        searchTF.returnKeyType = .search
        searchTF.addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        return searchTF
    }()

    /// 一级分类视图
    lazy var topCategoryController: PQStuckPointMusicContentController = {
        let topCategoryController = PQStuckPointMusicContentController()
        addChild(topCategoryController)
        view.insertSubview(topCategoryController.view, belowSubview: searchController.view)
        topCategoryController.updateViewFrame(newFrame: CGRect(x: 0, y: searchTF.frame.maxY + cDefaultMargin * 2, width: cDefaultMargin * 12, height: view.frame.height - (searchTF.frame.maxY + cDefaultMargin * 2)))
        // 一级分类点击
        topCategoryController.didSelectedHandle = { [weak self] _, _, _, itemData in
            if itemData is PQStuckPointMusicTagsModel {
                self?.musicPageController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: true)
                self?.searchController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: true)
                self?.tagData = itemData as? PQStuckPointMusicTagsModel
                self?.dealWithCategorySelectedData(itemData: itemData as? PQStuckPointMusicTagsModel)
                // 更新当前标签
                self?.updateMusicCacheData(tagId: (itemData as? PQStuckPointMusicTagsModel)?.tagId ?? 0, tagInfo: nil, pageList: nil, currentTag: self?.tagData)
            }
            self?.playStuckPointMusic(itemData: nil, isClearCurrentMusic: true)
        }
        return topCategoryController
    }()

    /// 音乐列表视图
    lazy var musicPageController: PQStuckPointMusicContentController = {
        let musicPageController = PQStuckPointMusicContentController()
        musicPageController.cellHight = cDefaultMargin * 8
        addChild(musicPageController)
        view.insertSubview(musicPageController.view, belowSubview: searchController.view)
        musicPageController.updateViewFrame(newFrame: CGRect(x: topCategoryController.view.frame.maxX, y: topCategoryController.view.frame.minY, width: view.frame.width - topCategoryController.view.frame.maxX, height: topCategoryController.view.frame.height))
        musicPageController.contentType = .page
        musicPageController.didSelectedHandle = { [weak self] isTagsClick, _, _, itemData in
            if isTagsClick { // 二级分类点击
                self?.tagData = (itemData as? PQStuckPointMusicTagsModel)
                let tagId: Int64 = (itemData as? PQStuckPointMusicTagsModel)?.tagId ?? 0
                let parentTagId: Int64 = (itemData as? PQStuckPointMusicTagsModel)?.parentTagId ?? 0
                // 请求列表数据
                self?.requestPageListData(tagId: tagId, parentTagId: parentTagId)
            } else {
                self?.playStuckPointMusic(itemData: itemData as? PQVoiceModel)
            }
        }
        musicPageController.refreshHandle = { [weak self] isRefresh, _ in
            let tagId: Int64 = self?.tagData?.tagId ?? 0
            let parentTagId: Int64 = self?.tagData?.parentTagId ?? 0
//            self?.musicPageController.tagsInfo = (tags, tagAttributes) as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))
            // 请求列表数据
            self?.requestPageListData(isRefresh: isRefresh, tagId: tagId, parentTagId: parentTagId)
            // 请求二级标签数据
//            self?.loadRequestSubTagsList()
            self?.playStuckPointMusic(itemData: nil, isClearCurrentMusic: true)
        }
        musicPageController.btnClickHandle = { [weak self] _, bgmData in
            // 使用音乐
            self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel)
        }
        return musicPageController
    }()

    /// 搜索控制器
    lazy var searchController: PQStuckPointMusicSearchController = {
        let searchController = PQStuckPointMusicSearchController()
        searchController.selectedDataCount = selectedDataCount
        searchController.selectedImageDataCount = selectedImageDataCount
        searchController.selectedTotalDuration = selectedTotalDuration
        searchController.cellHight = cDefaultMargin * 8
        addChild(searchController)
        view.addSubview(searchController.view)
        searchController.updateViewFrame(newFrame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei + cDefaultMargin * 2, width: view.frame.width, height: view.frame.height - (cDevice_iPhoneNavBarAndStatusBarHei + cDefaultMargin * 2)))
        searchController.didSelectedHandle = { [weak self] isTagsClick, _, _, itemData in
            if !isTagsClick {
                self?.view.endEditing(true)
                if !(itemData is PQEmptyModel) {
                    self?.playStuckPointMusic(itemData: itemData as? PQVoiceModel)
                }
            }
        }
        searchController.btnClickHandle = { [weak self] _, bgmData in
            // 使用音乐
            self?.userstuckPointMusic(musicData: bgmData as? PQVoiceModel)
        }
        searchController.scroDidScroHandle = { [weak self] in
            self?.view.endEditing(true)
        }
        searchController.view.isHidden = true
        searchController.contentType = .serach
        return searchController
    }()

    lazy var emptyRemindView: PQEmptyRemindView = {
        let emptyRemindView = PQEmptyRemindView(frame: CGRect(x: 0, y: searchTF.frame.maxY + cDefaultMargin * 2, width: view.frame.width, height: view.frame.height - (searchTF.frame.maxY + cDefaultMargin * 2)))
        emptyRemindView.remindLab.font = UIFont.systemFont(ofSize: 20)
        emptyRemindView.remindLab.textColor = UIColor.hexColor(hexadecimal: "#575757")
        emptyRemindView.isHidden = true
        let emptyData = PQEmptyModel()
        emptyData.title = "暂无音乐"
        emptyRemindView.emptyData = emptyData
        emptyRemindView.fullRefreshBloc = { [weak self] _, _ in
            /// 请求标签数据
            self?.loadRequestTagsList()
        }
        view.addSubview(emptyRemindView)
        return emptyRemindView
    }()

//    /// 已选择音乐view
//    lazy var selectedMusciView: PQStuckPointMusicContentCell = {
//        let selectedMusciView = PQStuckPointMusicContentCell(frame: CGRect(x: 0, y: view.frame.height - cDefaultMargin * 6, width: cScreenWidth, height: cDefaultMargin * 6))
//        selectedMusciView.confirmContentView.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
//        selectedMusciView.playImageView.isHidden = true
//        selectedMusciView.confirmBtn.setTitle("  继续使用  ", for: .normal)
//        selectedMusciView.backgroundColor = UIColor.hexColor(hexadecimal: "#333333")
//        view.addSubview(selectedMusciView)
//        return selectedMusciView
//    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        // 拦截侧滑返回
        disablePopGesture().popGestureHandle = { [weak self] in
            self?.backBtnClick()
        }
        leftButton(image: nil, tintColor: PQBFConfig.shared.styleTitleColor)
        setTitle(title: "选择音乐主题", color: PQBFConfig.shared.styleTitleColor)
        view.addSubview(searchTF)
      
        /// 请求标签数据
        loadRequestTagsList()
        PQNotification.addObserver(self, selector: #selector(enterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil)
        if selectedMusicData != nil {
            let editerVC: PQStuckPointEditerController = PQStuckPointEditerController()
            editerVC.stuckPointMusicData = selectedMusicData
            editerVC.selectedDataCount = selectedDataCount
            editerVC.selectedImageDataCount = selectedImageDataCount
            //mdf by ak 进入编辑界面的时候去掉图片的时长
            editerVC.selectedTotalDuration = selectedTotalDuration - (Double(selectedImageDataCount) * 1.5)
            editerVC.selectedPhotoData = selectedPhotoData
            editerVC.reCreateVideoData = reCreateVideoData
            editerVC.isReCreate = true
            navigationController?.pushViewController(editerVC, animated: true)
            stuckPointEditVC = editerVC
            if firstFrameImage != nil {
                editerVC.firstFrameImage = firstFrameImage
            }
        }
        // 卡点视频音乐选择曝光上报
        PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_selectSyncedUpMusic, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-（曝光上报：卡点视频音乐选择页）")
    }

    override func viewWillAppear(_ animated: Bool) {
        // mdf by ak 修复其它界面的键盘会影响这个界面问题
        addKeyboardObserver()
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        playStuckPointMusic(itemData: nil)
        
        PQNotification.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        PQNotification.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
 
 
    }

    /// 按钮点击事件
    /// - Parameter sender: <#sender description#>
    /// - Returns: <#description#>
    @objc func btnClick(sender: UIButton) {
        switch sender.tag {
        case 1: // 清除
            searchTF.text = nil
//            emptyRemindView.isHidden = true
            clearBtn.isHidden = true
        default:
            break
        }
    }

    /// 请求标签数据
    /// - Returns: <#description#>
    func loadRequestTagsList() {
        PQLoadingHUB.shared.showHUB()
        PQStuckPointViewModel.stuckPointMusicCategoryList { [weak self] tags, _, _ in
            PQLoadingHUB.shared.dismissHUB()
            if tags.count > 0 {
                self?.tagData = tags.first
            }
            self?.emptyRemindView.isHidden = tags.count > 0
            if tags.count > 0 {
                self?.topCategoryController.configMusicListData(isRefresh: true, musicListData: tags)
                // 请求列表数据
                self?.requestPageListData(isHotPage: true, tagId: tags.first?.tagId ?? 0, parentTagId: 0)
            }
        }
    }

    /// 请求二级标签数据
    /// - Returns: <#description#>
    func loadRequestSubTagsList() {
        PQLoadingHUB.shared.showHUB()
        PQStuckPointViewModel.stuckPointMusicCategoryList(parentTagId: tagData?.tagId ?? 0) { [weak self] tags, _, tagAttributes in
            PQLoadingHUB.shared.dismissHUB()
            if tagAttributes != nil {
                let tagId: Int64 = tags.count > 0 ? (tags.first?.tagId ?? 0) : (self?.tagData?.tagId ?? 0)
                let parentTagId: Int64 = tags.count > 0 ? (self?.tagData?.tagId ?? 0) : 0
                self?.musicPageController.tagsInfo = (tags, tagAttributes) as? ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))
                if tags.count > 0 {
                    self?.tagData = tags.first
                }
                // 添加缓存
                self?.updateMusicCacheData(tagId: parentTagId > 0 ? parentTagId : tagId, isClearOld: false, tagInfo: self?.musicPageController.tagsInfo, pageList: nil, currentTag: self?.tagData)
                // 请求列表数据
                self?.requestPageListData(tagId: tagId, parentTagId: parentTagId)
            } else {
                // 重置数据
                self?.resetPageData(isResetData: false)
            }
        }
    }

    /// 处理cell点击回调
    /// - Parameter itemData: <#itemData description#>
    /// - Returns: <#description#>
    func dealWithCategorySelectedData(itemData: PQStuckPointMusicTagsModel?) {
        tagData = itemData
        // 重置数据
        resetPageData(isResetData: true)
        let cacheData = getMusicCacheData(itemData: itemData)
        if cacheData != nil, (cacheData?.0 != nil && (cacheData?.0?.0.count ?? 0) > 0) || (cacheData?.1 != nil && (cacheData?.1?.count ?? 0) > 0) {
            musicPageController.tagsInfo = cacheData?.0
            musicPageController.configMusicListData(isRefresh: true, musicListData: cacheData?.1 ?? [])
            pageNum = ((cacheData?.1?.count ?? 0) / 20) + 1
            tagData = cacheData?.2
        } else {
            pageNum = 1
            // 请求二级标签数据
            loadRequestSubTagsList()
        }
    }

    /// 请求列表数据
    /// - Parameters:
    ///   - tagId: <#tagId description#>
    ///   - parentTagId: <#parentTagId description#>
    ///   - tagsInfo: <#tagsInfo description#>
    /// - Returns: <#description#>
    func requestPageListData(isRefresh: Bool = true, isHotPage: Bool = false, tagId: Int64, parentTagId: Int64) {
        PQLoadingHUB.shared.showHUB()
        if isRefresh {
            pageNum = 1
        }
        PQStuckPointViewModel.stuckPointMusicPageList(tagId: tagId, parentTagId: parentTagId, pageNum: pageNum, videoCount: selectedDataCount - selectedImageDataCount, imageCount: selectedImageDataCount, totalDuration: selectedTotalDuration) { [weak self] musicInfo, _ in
            PQLoadingHUB.shared.dismissHUB()
            if musicInfo.count > 0 {
                self?.pageNum = (self?.pageNum ?? 0) + 1
            }
            self?.musicPageController.configMusicListData(isRefresh: isRefresh, musicListData: musicInfo)
            // 添加缓存
            self?.updateMusicCacheData(tagId: parentTagId > 0 ? parentTagId : tagId, isClearOld: isRefresh, tagInfo: nil, pageList: musicInfo, currentTag: nil)
            if musicInfo.count > 0, isHotPage, isRefresh {
                self?.hotList = musicInfo
                self?.searchController.hotList = self?.hotList ?? []
                self?.searchController.configMusicListData(isResetData: false, isRefresh: true, musicListData: musicInfo)
            }
        }
    }

    /// 重置页面数据
    /// - Parameter isResetData: <#isResetData description#>
    /// - Returns: <#description#>
    func resetPageData(isResetData: Bool) {
        musicPageController.tagsInfo = nil
        musicPageController.configMusicListData(isResetData: isResetData, isRefresh: true, musicListData: [])
        pageNum = 1
    }

    var avPlayerTimeObserver:Any?
    /// 播放音乐
    /// - Parameter itemData: <#itemData description#>
    func playStuckPointMusic(itemData: PQVoiceModel?, isClearCurrentMusic: Bool = false) {
        if itemData != nil, currentPlayData != itemData {
            if !isValidURL(url: itemData?.musicPath ?? "") {
                cShowHUB(superView: nil, msg: "本歌曲暂无伴奏版本哦~")
                return
            }
            avPlayer.pause()
            playerItem?.removeObserver(self, forKeyPath: "status")
            playerItem?.removeObserver(self, forKeyPath: "error")
            if avPlayerTimeObserver != nil {
                avPlayer.removeTimeObserver(avPlayerTimeObserver as Any)
            }
            
            playerItem = AVPlayerItem(url: URL(string: itemData?.musicPath ?? "")!)
            if (itemData?.endTime ?? 0) > 0, (itemData?.endTime ?? 0) > (itemData?.startTime ?? 0) {
                playerItem?.forwardPlaybackEndTime = CMTime(value: CMTimeValue((itemData?.endTime ?? 0) * playerTimescale), timescale: CMTimeScale(playerTimescale))
            }
            avPlayer.replaceCurrentItem(with: playerItem)
            playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
            playerItem?.addObserver(self, forKeyPath: "error", options: .new, context: nil)
            avPlayer.seek(to: CMTime(value: CMTimeValue((itemData?.startTime ?? 0) * playerTimescale), timescale: CMTimeScale(playerTimescale)))
            avPlayer.play()
            
            avPlayerTimeObserver = avPlayer.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 10), queue: DispatchQueue.global()) {[weak self] time in
                if fabs(CMTimeGetSeconds(time) - (itemData?.startTime ?? 0)) > 0.1 {
                    self?.avPlayer.removeTimeObserver(self?.avPlayerTimeObserver as Any)
                    self?.avPlayerTimeObserver = nil
                    // 停止cell loading动画
                    PQNotification.post(name: NSNotification.Name(rawValue: "MusicContentCellIconLoadingAnimationStop"), object: nil)
                }
             //    进度监控
//                BFLog(1, message: "\(Int(CMTimeGetSeconds((self?.playerItem?.asset.duration)!))),curr:\(CMTimeGetSeconds(time))")
            }
//            let player = TXVodPlayer()
//            let config = TXVodPlayConfig()
//            config.cacheFolderPath = videoCacheDirectory
//            config.maxCacheItems = 0
//            player.config = config
            ////            player.vodDelegate = self
//            player.setRenderMode(.RENDER_MODE_FILL_EDGE)
//            player.startPlay("https://clipres.yishihui.com/longvideo/material/voice/prod/20210512/MUSIC_QQ_000T1Ws32MWrUj")
            currentPlayData = itemData
        } else if itemData != nil, avPlayer.rate == 0.0 {
            avPlayer.play()
        } else {
            avPlayer.pause()
            musicPageController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: isClearCurrentMusic)
            searchController.updateCurrentPlayMusic(isPlaying: false, isClearCurrentMusic: isClearCurrentMusic)
        }
        if isClearCurrentMusic {
            avPlayer.pause()
            currentPlayData = nil
        }
    }

    /// 使用卡点音乐
    /// - Parameter musicData: <#musicData description#>
    /// - Returns: <#description#>
    func userstuckPointMusic(musicData: PQVoiceModel?) {
        if musicData != nil {
            let editerVC: PQStuckPointEditerController = PQStuckPointEditerController()
            editerVC.selectedDataCount = selectedDataCount
            editerVC.selectedImageDataCount = selectedImageDataCount
            editerVC.selectedTotalDuration = selectedTotalDuration - (Double(selectedImageDataCount) * 1.5)
            editerVC.stuckPointMusicData = musicData
            editerVC.selectedPhotoData = selectedPhotoData
            navigationController?.pushViewController(editerVC, animated: true)
            stuckPointEditVC = editerVC
            if firstFrameImage != nil {
                editerVC.firstFrameImage = firstFrameImage
            }
        }
    }

    /// 返回按钮操作
    override func backBtnClick() {
        if searchController.view.isHidden {
            navigationController?.popViewController(animated: true)
            // 点击上报：选择音乐分类
            PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_back, pageSource: .sp_stuck_selectSynceedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-（点击上报：返回按钮）")
        } else {
            hiddenSearchController()
            // 点击上报：返回按钮
            PQEventTrackViewModel.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_click_back, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-（点击上报：返回按钮）")
        }
    }

    /// 进入后台暂停播放
    @objc func enterBackground() {
        playStuckPointMusic(itemData: nil)
    }

    deinit {
        PQNotification.removeObserver(self)
        PQNotification.removeObserver(self.avPlayer.currentItem as Any)
        avPlayer.currentItem?.removeObserver(self, forKeyPath: "status")
        avPlayer.currentItem?.removeObserver(self, forKeyPath: "error")
        avPlayer.pause()
        avPlayer.replaceCurrentItem(with: nil)
        playerItem = nil
    }
}

// MARK: - 音乐搜索相关

/// 音乐搜索相关
extension PQStuckPointMusicController: UITextFieldDelegate {
    /// 点击输入框
    @objc func editingChanged() {
        if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0, searchTF.markedTextRange == nil {
            if searchTF.text?.isSpace ?? false {
                return
            }
//            loadSearchData()
            clearBtn.isHidden = false
        }
    }

    /// 搜索
    @objc func loadSearchData() {
        if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0, searchTF.text?.isSpace ?? false {
            cShowHUB(superView: nil, msg: "搜索内容不能为空")
            return
        }
        if searchTF.text != nil, (searchTF.text?.count ?? 0) > 0 {
            BFLog(message: "背景音乐--开始搜索背景音乐-1")
            searchController.loadSearchData(keyword: searchTF.text)
        }
    }

    /// 添加键盘监听
    /// - Returns: <#description#>
    func addKeyboardObserver() {
        // 监听键盘的显示和隐藏
        PQNotification.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        PQNotification.addObserver(self, selector: #selector(keyboardWillHidden), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    /// 键盘显示
    /// - Parameter notification: <#notification description#>
    @objc func keyboardWillShow(notification: Notification) {
        let duration: TimeInterval = TimeInterval("\(notification.userInfo?["UIKeyboardAnimationDurationUserInfoKey"] ?? "1")") ?? 1
        UIView.animate(withDuration: duration) { [weak self] in
            self?.navTitleLabel?.alpha = 0
            self?.searchTF.frame = CGRect(x: cDefaultMargin * 5, y: (cDevice_iPhoneNavBarHei - (self?.searchTFH ?? 37.0)) / 2 + cDevice_iPhoneStatusBarHei, width: cScreenWidth - cDefaultMargin * 7, height: self?.searchTFH ?? 37.0)
        } completion: { _ in
        }
        searchController.view.isHidden = false
        hotList.forEach { item in
            if item is PQVoiceModel {
                (item as? PQVoiceModel)?.isSelected = false
                (item as? PQVoiceModel)?.isPlaying = false
            }
        }
        musicPageController.collectionView.reloadData()
        searchController.hotList = hotList
        playStuckPointMusic(itemData: nil)
        // 曝光上报：音乐素材搜索页
        PQEventTrackViewModel.baseReportUpload(businessType: .bt_windowView, objectType: .ot_view_searchSyncedUpMusic, pageSource: .sp_stuck_searchSyncedUpMusic, extParams: nil, remindmsg: "卡点视频数据上报-（曝光上报：音乐素材搜索页）")
    }

    /// 键盘将要隐藏
    @objc func keyboardWillHidden() {}

    /// 隐藏搜索界面
    /// - Returns: <#description#>
    func hiddenSearchController() {
        view.endEditing(true)
        UIView.animate(withDuration: 0.3) { [weak self] in
            self?.navTitleLabel?.alpha = 1
            self?.searchTF.frame = CGRect(x: self?.leftMargin ?? 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth - (self?.leftMargin ?? 0) * 2, height: self?.searchTFH ?? 0)
        } completion: { _ in
        }
        clearBtn.isHidden = true
        searchController.view.isHidden = true
//        searchTF.text = nil
//        searchController.clearData()
//        currentPlayData?.isSelected = false
//        currentPlayData?.isPlaying = false
        playStuckPointMusic(itemData: nil)
    }

    override func touchesBegan(_: Set<UITouch>, with _: UIEvent?) {
        view.endEditing(true)
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        loadSearchData()
        view.endEditing(true)
        if textField.text == nil || (textField.text?.count ?? 0) <= 0 {
            cShowHUB(superView: nil, msg: "请先输入搜索内容")
        }
        return true
    }
}

// MARK: - 缓存相关
//缓存歌曲列表 KEY
let kSaveMusicListDatas = "kSaveMusicListDatas"
/// 缓存相关
extension PQStuckPointMusicController {
    /// 获取缓存数据
    /// - Parameter itemData: <#itemData description#>
    /// - Returns: <#description#>
    func getMusicCacheData(itemData: PQStuckPointMusicTagsModel?) -> (([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))?, [PQVoiceModel]?, PQStuckPointMusicTagsModel?)? {
        let saveMusicListStr =  getUserDefaults(key: kSaveMusicListDatas)
    
        if(((saveMusicListStr as? String)?.count ?? 0 ) > 0){
            let cacheMusicDataTemp = jsonStringToDictionary(saveMusicListStr as! String)
            
            if itemData != nil, cacheMusicData.keys.contains("\(itemData?.tagId ?? 0)") {
                let tempData = cacheMusicDataTemp?["\(itemData?.tagId ?? 0)"] as? Dictionary<String, Any>
                
                return (tempData?["tagInfo"] as? ([PQStuckPointMusicTagsModel],([UICollectionViewLayoutAttributes], CGFloat)),tempData?["pageList"] as? [PQVoiceModel],tempData?["currentTag"] as? PQStuckPointMusicTagsModel)

            } else {
                return nil
            }
        }else{ return nil}
     
    }

    /// 更新缓存
    /// - Parameters:
    ///   - tagId: 一级分类id
    ///   - isClearOld: 是否清空老数据
    ///   - tagInfo: 二级标签信息
    ///   - pageList: 音乐数据
    ///   - currentTag: 当前页当前标签
    /// - Returns: <#description#>
    func updateMusicCacheData(tagId: Int64, isClearOld: Bool = false, tagInfo: ([PQStuckPointMusicTagsModel], ([UICollectionViewLayoutAttributes], CGFloat))?, pageList: [PQVoiceModel]?, currentTag: PQStuckPointMusicTagsModel?) {
        if (tagInfo != nil && (tagInfo?.0.count ?? 0) > 0) || (pageList != nil && (pageList?.count ?? 0) > 0) || currentTag != nil {
            if cacheMusicData.keys.contains("\(tagId)") {
                var tempDic = cacheMusicData["\(tagId)"]
                if tagInfo != nil, (tagInfo?.0.count ?? 0) > 0 {
                    tempDic?["tagInfo"] = tagInfo!
                }
                if pageList != nil, (pageList?.count ?? 0) > 0 {
                    var oldPageList: [PQVoiceModel] = (tempDic?["pageList"] as? [PQVoiceModel]) ?? Array<PQVoiceModel>.init()
                    if isClearOld {
                        oldPageList.removeAll()
                    }
                    if oldPageList.count > 0 {
                        tempDic?["pageList"] = oldPageList + pageList!
                    } else {
                        tempDic?["pageList"] = pageList!
                    }
                }
                if currentTag != nil {
                    tempDic?["currentTag"] = currentTag!
                }
                cacheMusicData["\(tagId)"] = tempDic ?? Dictionary<String, Any>.init()
            } else {
                var tempDic: [String: Any] = Dictionary<String, Any>.init()
                if tagInfo != nil, (tagInfo?.0.count ?? 0) > 0 {
                    tempDic["tagInfo"] = tagInfo!
                }
                if pageList != nil, (pageList?.count ?? 0) > 0 {
                    tempDic["pageList"] = pageList!
                }
                if currentTag != nil {
                    tempDic["currentTag"] = currentTag!
                }
                cacheMusicData["\(tagId)"] = tempDic
            }
            
            saveUserDefaults(key: kSaveMusicListDatas, value: dictionaryToJsonString(cacheMusicData) as Any)
        
        }
    }
}

extension PQStuckPointMusicController {
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
        if object is AVPlayerItem, keyPath == "status" {
            BFLog(message: "AVPlayerItem - status = \((object as! AVPlayerItem).status.rawValue)")
            switch (object as! AVPlayerItem).status {
            case .unknown:
                break
            case .readyToPlay:
                break
            case .failed:
                break
            default:
                break
            }
        } else if object is AVPlayerItem, keyPath == "error" {
            BFLog(message: "AVPlayerItem - error = \(String(describing: (object as! AVPlayerItem).error))")
        }
    }
}
