//
//  PQEditMusicSearchController.swift
//  BFFramework
//
//  Created by ak on 2021/8/7.
//  功能：显示编辑界中搜索音乐界面

import BFAnalyzeKit
import BFCommonKit
import BFMediaKit
import BFUIKit
import Foundation

class PQEditMusicSearchController: BFBaseViewController {
    // 当前播放的音乐
    var currentPlayData: PQVoiceModel?
    // 当前播放的视频
    var playerItem: AVPlayerItem?
    // 左边距离
    let leftMargin: CGFloat = 47
    // 搜索拦高度
    let searchTFH: CGFloat = 37
    // 热搜数据
    var hotList: [Any] = Array<Any>.init()
    // 按钮点击的回调
    var btnClickHandle: ((_ sender: UIButton, _ bgmData: Any?) -> Void)?
    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: "BFStuckPointKit", 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_iPhoneStatusBarHei, width: cScreenWidth - leftMargin * 2, height: searchTFH))
        searchTF.font = UIFont.systemFont(ofSize: 17)
        searchTF.backgroundColor = BFConfig.shared.otherTintColor
        searchTF.attributedPlaceholder = NSAttributedString(string: "搜索歌曲名称/歌手", attributes: [.foregroundColor: UIColor.hexColor(hexadecimal: "#BDBDBD"), .font: UIFont.systemFont(ofSize: 14)])
        searchTF.textColor = BFConfig.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: "BFStuckPointKit", 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 searchController: PQStuckPointMusicSearchController = {
        let searchController = PQStuckPointMusicSearchController()
        searchController.cellHight = cDefaultMargin * 8

        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 BFEmptyModel) {
                    BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_musicSearchAudition, pageSource: .sp_shanyinApp_main, extParams: ["musicName": (itemData as? PQVoiceModel)?.musicName ?? "", "musicId": (itemData as? PQVoiceModel)?.musicId ?? ""], commonParams: commonParams())
                    self?.playStuckPointMusic(itemData: itemData as? PQVoiceModel)
                }
            }
        }
        searchController.btnClickHandle = { [weak self] btn, bgmData in
            BFEventTrackAdaptor.baseReportUpload(businessType: .bt_buttonClick, objectType: .ot_shanyinApp_musicVideoPreview_musicSearchSelect, pageSource: .sp_shanyinApp_main, extParams: ["musicName": (bgmData as? PQVoiceModel)?.musicName ?? "", "musicId": (bgmData as? PQVoiceModel)?.musicId ?? ""], commonParams: commonParams())
            // 使用音乐
            self?.backBtnClick()
            if self?.btnClickHandle != nil {
                self?.btnClickHandle!(btn, bgmData)
            }
        }
        searchController.scroDidScroHandle = { [weak self] in
            self?.view.endEditing(true)
        }
        searchController.contentType = .serach
        return searchController
    }()

    override func backBtnClick() {
        super.backBtnClick()
        avPlayer.pause()
    }

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

    override func viewWillAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        BFEventTrackAdaptor.baseReportUpload(businessType: .bt_windowView, objectType: .ot_shanyinApp_musicVideoPreview_musicSearch, pageSource: .sp_shanyinApp_main, commonParams: commonParams())
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(searchTF)
        searchTF.becomeFirstResponder()

        addChild(searchController)
        view.addSubview(searchController.view)

        leftButton(image: UIImage(named: "upload_delete"), tintColor: BFConfig.shared.styleTitleColor)

        // 请求一下热门数据在没有搜索数据时显示
        PQStuckPointViewModel.stuckPointMusicPageList(tagId: 425, parentTagId: 0, pageNum: 1, videoCount: 0, imageCount: 0, totalDuration: 0) { [weak self] musicInfo, _ in

            if musicInfo.count > 0 {
                self?.searchController.hotList = musicInfo
                self?.searchController.configMusicListData(isRefresh: true, musicListData: musicInfo)
            }
        }
    }

    /// 按钮点击事件
    /// - 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
        }
    }

    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)
                }
            }
            currentPlayData = itemData
        } else if itemData != nil, avPlayer.rate == 0.0 {
            avPlayer.play()
        } else {
            avPlayer.pause()
        }
        if isClearCurrentMusic {
            avPlayer.pause()
            currentPlayData = nil
        }
    }
}

/// 音乐搜索相关
extension PQEditMusicSearchController: 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
            }
        }

        searchController.hotList = hotList
        playStuckPointMusic(itemData: nil)
    }

    /// 键盘将要隐藏
    @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
        playStuckPointMusic(itemData: nil)
    }

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

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

extension PQEditMusicSearchController {
    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))")
        }
    }
}
