//
//  MPNetWorkManager.swift
//  MusicPlayer
//
//  Created by Mr.Zhou on 2024/4/11.
//

import UIKit
import Network
import Alamofire
import AVFoundation
///预览闭包（传递一个预览模块数据组和完成状态）
typealias BrowseRequestStateBlock = (_ browse:[MPPositive_BrowseModuleListViewModel], _ isCompeleted:Bool) -> Void
///预览数据失败闭包
typealias BrowseRequestErrorBlock = () -> Void

///列表/专辑闭包（传递一个列表数据）
typealias ListRequestResultBlock = (_ list:MPPositive_ListAlbumListViewModel) -> Void
///网络状况管理器
class MP_NetWorkManager: NSObject {
    //单例工具
    static let shared = MP_NetWorkManager()
    //MARK: - 网络请求会话
    ///会话实例
    private lazy var MPSession:Session = {
        let configuration = URLSessionConfiguration.af.default
        //最多同时执行4条
        configuration.timeoutIntervalForRequest = 20
        configuration.timeoutIntervalForResource = 20
        // 可调整网络服务类型
        configuration.networkServiceType = .default
        // 可调整缓存策略
        configuration.requestCachePolicy = .reloadIgnoringLocalCacheData
        let seesion = Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
        return seesion
    }()
    ///播放资源会话实例
    private lazy var PlayerSeesion:Session = {
        let configuration = URLSessionConfiguration.af.default
        configuration.timeoutIntervalForRequest = 20
        configuration.timeoutIntervalForResource = 20
        //最多同时执行4条
        configuration.httpMaximumConnectionsPerHost = 4
        return Alamofire.Session(configuration: configuration, interceptor: MP_CustomRetrier())
    }()
    ///播放相关内容ID和歌词ID记录组
    private var relatedRequests: [String:DataRequest] = [:]
    ///播放资源请求记录组
    private var playerRequests: [String:DataRequest] = [:]

    //MARK: - API接口
    ///IP获取
    private let iPInfo:String = "https://api.tikustok.com/app/common/getIPInfo"
    ///域名链接
    private let header:String = "https://music.youtube.com"
    ///端点
    private let point:String = "/youtubei/v1"
    ///预览接口
    private let browse:String = "/browse"
    ///相关接口
    private let next:String = "/next"
    ///播放器接口
    private let player:String = "/player"
    ///搜索建议接口
    private let suggestions:String = "/music/get_search_suggestions"
    ///搜索接口
    private let search = "/search"
    ///YouTuBe资源键值
    private let youTubeKeys:[String] = ["MUSIC_VIDEO_TYPE_ATV","MUSIC_VIDEO_TYPE_OMV","MUSIC_PAGE_TYPE_ALBUM","MUSIC_PAGE_TYPE_ARTIST","MUSIC_PAGE_TYPE_PLAYLIST","MUSIC_PAGE_TYPE_TRACK_LYRICS","MUSIC_PAGE_TYPE_TRACK_RELATED"]
    ///接口版本默认值
    private var clientVersion:String!
    ///播放接口版本默认值
    private var playerVersion:String!
    ///禁止接入IP信息组
    private let banIPs:[String] = [
//                                    "CN",
//                                   "HK",
//                                   "TW",
//                                   "JP",
//                                   "KR"
    ]
    ///允许访问的区域Code（对部分内容进行塞选）
    private let codes:[String] = [
        "CL","GB","ID","IN","IT","IL","HU","NZ","ES","UY","UA","UG","GT","TR","TZ","SA","RS","SV","CH","SE","JP","PT","NO","NG","NI","ZA","MX","PE","US","RO","LU","KE","ZW","CZ","CA","HN","NL","KR","CR","CO","FI","FR","EC","RU","DO","DK","BO","PL","IS","BE","BR","PA","PY","AU","AT","EE","IE","EG","AE","AR","ZZ"
    ]
    ///禁止关键词
    private var trashKeyWords:[String] = []
    ///设置禁止关键词
    func setTrashKeyWords(_ words:[String]){
        trashKeyWords = words
    }
    ///禁止歌手（id组）
    private var trashSingerIds:[String] = []
    ///设置禁用歌手
    func setTrashSingerIds(_ ids:[String]) {
        trashSingerIds = ids
    }
    ///禁止歌曲（id组）
    private var trashVideoIds:[String] = []
    ///设置禁用歌曲
    func setTrashVideoIds(_ ids:[String]) {
        trashVideoIds = ids
    }
    ///禁止下载
    private var isAllowedDownload:Bool = true
    //网络状态
    enum NetWorkStatus: String {
        case notReachable = "网络不可用"
        case unknown = "网络未知"
        case reachable = "网络可用"
    }
    ///网络监听器
    private var monitor:NWPathMonitor
    ///对监听器的判断
    private var isReach:Bool = false
    ///当前网络状态
    var netWorkStatu:NetWorkStatus!{
        willSet{
            guard newValue != netWorkStatu else {
                //重复情况
                return
            }
            switch newValue {
            case .reachable://网络可用
                print("网络可用")
                NotificationCenter.notificationKey.post(notificationName: .net_switch_reachable)
            case .notReachable://不可用
                print("网络不可用")
                NotificationCenter.notificationKey.post(notificationName: .net_switch_notReachable)
            case .unknown://位置情况
                print("网络状况未知")
            case .none:
                break
            }
        }
    }
    //MARK: - 固定参数
    //访问数据（首次首页预览时获得）
    private var visitorData:String?
    //固定时间点（同一天的上一周）
    private lazy var currTimeDate:String = (Date().timeZone() - 7.days).toString(.custom("YYYYMMdd"))
    ///地址
    private var locaton:String? = "HK"
    //预览下一阶段参数（网络请求获取）
    private var continuationAndItct:(String?,String?){
        willSet{
            //当获取新值后，判断新值是否存在，存在则继续串行异步请求
            guard let continuation = newValue.0, let itct = newValue.1, browseQueque != nil, let url = URL(string: header+point+browse) else {
                //首页基础数据已经获取完毕
                //调用艺术家排行榜
                requestArtistsRank()
                return
            }
            //生成新参数
            let parameters:[String:Any] = [
                "ctoken":continuation,
                "continuation":continuation,
                "type":"next",
                "itct":itct,
                "prettyPrint":"false",
                "context":[
                    "client":[
                        //web端
                        "clientName": "WEB_REMIX",
                        "visitorData":visitorData,
                        //当前访问版本（日期值）
                        "clientVersion": clientVersion,
                        "platform":"MOBILE",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":locaton ?? "HK"
                    ]
                ]
            ]
            //执行异步请求
            browseQueque?.sync {
                [weak self] in
                guard let self = self else { return }
                requestPostHomeBrowse(url, parameters: parameters)
            }
        }
    }
    //MARK: - GCD队列任务
    ///网络检测队列
    private let MPNetWorkqueue = DispatchQueue(label: "MPNetWorkManager")
    ///A/B任务处理队伍
    private var executionQueue: [() -> Void] = []
    ///串行队列-预览
    private var browseQueque:DispatchQueue?
    ///并发队列-单曲资源预加载
    var playerItemLoadingGroup:DispatchGroup = DispatchGroup()
    //MARK: - 闭包
    ///预览闭包（传递一个预览模块数据和完成状态）
    var browseRequestStateBlock:BrowseRequestStateBlock?
    ///预览失败闭包
    var browseRequestErrorBlock:BrowseRequestErrorBlock?
    //私有初始化
    private override init() {
        self.monitor = NWPathMonitor()
        super.init()
        reloadVersion()
        if let string = UserDefaults.standard.string(forKey: "Visitor_Data") {
            self.visitorData = string
        }
    }
    //更新版本默认值
    func reloadVersion() {
        if let cv = UserDefaults.standard.string(forKey: "ClientVersion") {
            print("成功更新数据版本")
            clientVersion = cv
        }
        if let pv = UserDefaults.standard.string(forKey: "PlayerVersion") {
            playerVersion = pv
        }
    }
    
    //MARK: - 网络情况
    ///检查网络状况
    func requestNetworkPermission(oberve:UIViewController, completeHanlder:ActionBlock?) {
        switch netWorkStatu {
        case .reachable:
            DispatchQueue.main.async {
                guard completeHanlder != nil else {
                    return
                }
                completeHanlder!()
            }
        default:
            DispatchQueue.main.async {
                //次要处理
                let alertController = UIAlertController(title: "Access network request", message: "”Musiclax“ needs to be loaded via a network request. Please click “Settings” to allow this application to gain access to the network.", preferredStyle: .alert)
                let CancelAction = UIAlertAction(title:"Cancel", style: .cancel) { (Cancel) in

                }
                let OKAction = UIAlertAction(title: "Settings", style: .default) { (action) in
                    let url = URL(string: UIApplication.openSettingsURLString)
                    if let url = url,UIApplication.shared.canOpenURL(url){
                        if #available(iOS 10, *) {
                            UIApplication.shared.open(url, options: [:]) { (success) in
                            }
                        }else{
                            UIApplication.shared.canOpenURL(url)
                        }
                    }
                }
                alertController.addAction(CancelAction)
                alertController.addAction(OKAction)
                oberve.present(alertController, animated: true, completion: nil)
            }
        }
    }
    ///网络请求检测
    func requestStatusToYouTube() {
        guard isReach == false else {
            return
        }
        isReach = true
        monitor.start(queue: MPNetWorkqueue)
        monitor.pathUpdateHandler = { [weak self] path in
            self?.updateNetworkStatus(path)
        }
    }
    private func updateNetworkStatus(_ path: NWPath) {
        if path.status == .satisfied {
            netWorkStatu = .reachable
            executePendingTasks()
        } else {
            netWorkStatu = .notReachable
        }
    }
    //AB面检测队列任务
    func performTaskNetWrokAvailable(_ task: @escaping() -> Void) {
        //根据当前网络情况决定是执行任务，还是将任务放置到队列
        if netWorkStatu == .reachable {
            //网络可以执行任务
            task()
        }else {
            //网络不可执行任务，放入队列
            executionQueue.append(task)
        }
    }
    //当网络恢复可用后立刻处理队列任务
    private func executePendingTasks() {
        while !executionQueue.isEmpty {
            let task = executionQueue.removeFirst()
            task()
        }
    }
}
//MARK: - API请求
extension MP_NetWorkManager {
    //MARK: - 请求iP信息
    ///请求IP信息
    func requestIPInfo(_ completion:@escaping((Bool) -> Void)) {
        //拼接出browse路径
        let path = iPInfo
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        requestPostIPInfo(url) { open in
            completion(open)
        }
    }
    private func requestPostIPInfo(_ url:URL, completion:@escaping((Bool) -> Void)) {
        MPSession.request(url, method: .get, encoding: JSONEncoding.default).responseDecodable(of: JsonIPInfo.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                guard let data = value.data, let code = data.isoCode else {
                    return
                }
                locaton = code
                if banIPs.contains(code) == true {
                    //包含，是禁止区域
                    completion(false)
                }else {
                    //不包含，是通行区域
                    completion(true)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
                completion(true)
            }
        }
    }
    
    //MARK: - 请求首页预览
    ///向YouTubemusic请求预览/首页数据
    func requestBrowseDatas() {
        //实行串行异步队列，进行多次请求。由于第一次之后的请求都必须携带对应的continuation编码，所以串行队列。直到最后一次请求的continuation值为空,销毁队列
        // 实例化串行队列
        browseQueque = DispatchQueue(label: "com.request.browseQueque")
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //异步执行任务
        browseQueque?.sync {
            [weak self] in
            //进行第一次请求，有预览ID，无continuation编码
            guard let self = self else { return }
            let parameters:[String:Any] = [
                "browseId": "FEmusic_home",
                "prettyPrint":"false",
                "context":[
                    "client":[
                        //web端
                        "clientName": "WEB_REMIX",
                        "visitorData":visitorData ?? "",
                        //当前访问版本（日期值）
                        "clientVersion": clientVersion,
                        "platform":"MOBILE",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":locaton ?? ""
                    ]
                ]
            ]
            //guard netWorkStatu != .notReachable else {return}
            requestPostHomeBrowse(url, parameters: parameters)
        }
    }
    //请求首页预览内容（执行多次）
    private func requestPostHomeBrowse(_ url:URL, parameters:Parameters) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonBrowses.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let data = value.responseContext?.visitorData {
                    if data != self.visitorData {
                        print("Visitor_Data更改了")
                        self.visitorData = data
                        UserDefaults.standard.setValue(data, forKey: "Visitor_Data")
                    }
                }
                //解析结构体
                let tab = value.contents?.singleColumnBrowseResultsRenderer?.tabs?[0]
                if let content = tab?.tabRenderer?.content {
                    parsingBrowseContents(content)
                }else if let continuationContents = value.continuationContents {
                    parsingBrowseContinuationContents(continuationContents)
                }else {
                    //不在服务范围内
                    print("Failed to parse browses content")
                    // 请求失败，处理错误
                    homeError(error: nil)
                    browseQueque = nil
                }
            case .failure(let error):
                print("Failed to parse browses content")
                // 请求失败，处理错误
                homeError(error: error)
                browseQueque = nil
            }
        }
    }
    //下拉刷新首页预览内容（回调）
    func requestPullDownHomeBrowse(){
        // 实例化串行队列
        browseQueque = DispatchQueue(label: "com.request.browseQueque")
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //异步执行任务
        browseQueque?.sync {
            [weak self] in
            //进行第一次请求，有预览ID，无continuation编码
            guard let self = self else { return }
            let parameters:[String:Any] = [
                "browseId": "FEmusic_home",
                "prettyPrint":"false",
                "context":[
//                    "activePlayers": [
//                        ["playerContextParams":"Q0FFU0FnZ0I="]
//                      ],
                    "client":[
                        //web端
                        "clientName": "WEB_REMIX",
                        "visitorData":visitorData,
                        //当前访问版本（日期值）
                        "clientVersion": clientVersion,
                        "platform":"MOBILE",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":locaton ?? ""
                    ]
                ]
            ]
            requestPostPullDownHomeBrowse(url, parameters: parameters)
        }
    }
    private func requestPostPullDownHomeBrowse(_ url:URL, parameters:Parameters) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonBrowses.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                //解析结构体
                let tab = value.contents?.singleColumnBrowseResultsRenderer?.tabs?[0]
                if let content = tab?.tabRenderer?.content {
                    parsingBrowseContents(content)
                }else if let continuationContents = value.continuationContents {
                    parsingBrowseContinuationContents(continuationContents)
                }else {
                    //不在服务范围内
                    print("Failed to pull down refresh browses content")
                    // 请求失败，处理错误
                    browseQueque = nil
                }
            case .failure(let error):
                print("Failed to pull down refresh browses content")
                browseQueque = nil
            }
        }
    }
    
    
    ///执行艺术家排行请求
    private func requestArtistsRank() {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //异步执行任务
        browseQueque?.sync {
            [weak self] in
            guard let self = self else { return }
            var code = locaton ?? ""
            if codes.contains(code) == false {
                //没有包含在内，默认替换为US美国国家码
                code = "US"
            }
            let parameters:[String:Any] = [
                "browseId": "FEmusic_charts",
                "prettyPrint":"false",
                "context":[
                    "client":[
                        //web端
                        "clientName": "WEB_REMIX",
                        //当前访问版本（日期值）
                        "clientVersion": clientVersion,
                        "platform":"MOBILE",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":locaton ?? ""
                    ]
                ],
                "formData":[
                    "selectedValues":[code]
                ]
            ]
            requestPostArtistsRank(url, parameters: parameters)
        }
    }
    ///请求艺术家排行
    private func requestPostArtistsRank(_ url:URL, parameters:Parameters) {
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonCharts.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let charts):
                if let content = charts.contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents {
                    parsingCharts(content)
                }
            case .failure(let error):
                print("Failed to parse browses content")
                // 请求失败，处理错误
                homeError(error: error)
                browseQueque = nil
            }
        }
    }
    //MARK: - 请求列表专辑预览
    /// 向YouTubemusic请求列表/专辑数据，该接口调用的同样是browse预览接口
    /// - Parameters:
    ///   - browseId: 专辑列表的Id
    ///   - params: 专辑列表的访问编码
    func requestAlbumOrListDatas(_ browseId: String, params: String, clickTrackingParams: String?, comletion:@escaping (MPPositive_ListAlbumListViewModel) -> Void) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "browseId":browseId,
            "params":params,
            "prettyPrint":"false",
            "clickTracking":[
                "clickTrackingParams": clickTrackingParams ?? ""
            ],
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
//        //guard netWorkStatu != .notReachable else {return}
        requestPostAlbumOrList(url, parameters: parameters) { results in
            comletion(results)
        }
    }
    //请求列表/专辑数据
    private func requestPostAlbumOrList(_ url:URL, parameters:Parameters, comletion:@escaping (MPPositive_ListAlbumListViewModel) -> Void) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonListOrAlbum.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                let contents = value.contents
                //创建一个列表ViewModel
                let list = MPPositive_ListAlbumListViewModel()
                if let content = contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content {//使用一号版本
                    list.items = parsingListSingleContents(content)
                    if let header = value.header {
                        list.header = .init(parsingListSingleHeaders(header))
                    }
                    //列表数据完善，回调
                    comletion(list)
                }else if let content = contents?.twoColumnBrowseResultsRenderer?.secondaryContents {//使用二号版本
                    list.items = parsingListTwoContents(content)
                    if let musicResponsiveHeaderRenderer = contents?.twoColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents?.first?.musicResponsiveHeaderRenderer {
                        list.header = .init(parsingListTwoHeaders(musicResponsiveHeaderRenderer))
                    }
                    //列表数据完善，回调
                    comletion(list)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求艺术家
    func requestArtist(_ browseId:String, clickTrackingParams: String?, comletion:@escaping (MPPositive_ArtistViewModel) -> Void) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "browseId":browseId,
            "prettyPrint":"false",
            "clickTracking":[
                "clickTrackingParams": clickTrackingParams ?? ""
            ],
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostArtist(url, parameters: parameters) { result in
            comletion(result)
        }
    }
    //请求艺术家信息
    private func requestPostArtist(_ url:URL, parameters:Parameters, comletion:@escaping (MPPositive_ArtistViewModel) -> Void) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonArtist.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                //解析value
                let artist = MPPositive_ArtistViewModel()
                if let header = value.header {
                    artist.header = parsingArtistHeaders(header)
                }
                if let contents = value.contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents {
                    artist.lists = parsingArtistContents(contents)
                }
                comletion(artist)
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求艺术家更多数据
    func requestArtistMore(_ browseId:String, params: String, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "browseId":browseId,
            "params":params,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostArtistMore(url, parameters: parameters) { result in
            comletion(result)
        }
    }
    ///请求艺术家更多数据
    private func requestPostArtistMore(_ url:URL, parameters:Parameters, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonArtistMore.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let content = value.contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents?.first {
                    let result = parsingArtistMore(content)
                    comletion(result)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求艺术家更多数据继续
    func requestArtistMoreContinuation(_ continuation:String, itct:String, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "continuation":continuation,
            "ctoken":continuation,
            "type":"next",
            "itct":itct,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostArtistMoreContinuation(url, parameters: parameters) { result in
            comletion(result)
        }
    }
    ///请求艺术家更多数据继续
    private func requestPostArtistMoreContinuation(_ url:URL, parameters:Parameters, comletion:@escaping (([MPPositive_BrowseItemViewModel], String?, String?)) -> Void) {
        //发送post请求，并将结果转为RootBrowses
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonArtistMore.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let musicPlaylistShelfContinuation = value.continuationContents?.musicPlaylistShelfContinuation {
                    let result = parsingArtistMoreContinuation(musicPlaylistShelfContinuation)
                    comletion(result)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求模块数据
    func requestGenres(_ completion:@escaping (([MPPositive_GridViewModel]) -> Void)) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "browseId": "FEmusic_moods_and_genres",
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        requestPostGenres(url, parameters: parameters) { array in
            completion(array)
        }
    }
    ///请求模块数据
    private func requestPostGenres(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_GridViewModel]) -> Void)) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonGenres.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let contents = value.contents?.singleColumnBrowseResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents {
                    let array = parsingGenres(contents)
                    completion(array)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求模块详情数据
    func requestMoodDetails(_ browseId:String, params:String, completion:@escaping (([MPPositive_BrowseModuleListViewModel]) -> Void)) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "browseId": browseId,
            "params":params,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        requestPostMoodDetails(url, parameters: parameters) { array in
            completion(array)
        }
    }
    ///请求模块详情数据
    private func requestPostMoodDetails(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_BrowseModuleListViewModel]) -> Void)) {
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonBrowses.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                //解析结构体
                let tab = value.contents?.singleColumnBrowseResultsRenderer?.tabs?[0]
                if let content = tab?.tabRenderer?.content {
                    let array = parsingMoodDetails(content)
                    completion(array)
                }
            case .failure(let error):
                print("Failed to parse browses content")
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    
    //MARK: - 请求列表专辑下一部分
    ///请求Next列表（优先于Player）
    /// - Parameter item: 请求的预览实体
    func requestNextList(_ browseId:String, videoId:String, clickTrackingParams: String?,completion:@escaping(([MPPositive_SongItemModel]) -> Void)) {
        //拼接出next路径
        let path = header+point+next
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，videoId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "playlistId":browseId,
            "videoId":videoId,
            "prettyPrint":"false",
            "clickTracking":[
                "clickTrackingParams": clickTrackingParams ?? ""
            ],
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostNextList(url, parameters: parameters) { listSongs in
            //成功拿到列表所有歌曲（内容尚不完善）
            completion(listSongs)
        }
    }
    //请求next列表
    private func requestPostNextList(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SongItemModel]) -> Void)) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonNext.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                //转化为list值
                let listSongs:[MPPositive_SongItemModel] = parsingNextList(value)
                completion(listSongs)
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求Next歌词/相关内容
    /// - Parameter item: 请求的预览实体
    func requestNextLyricsAndRelated(_ item: MPPositive_SongItemModel, completion:@escaping(((String?,String?)) -> Void)) {
        guard netWorkStatu != .notReachable else {
            completion((nil,nil))
            return
        }
        //拼接出next路径
        let path = header+point+next
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，videoId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "videoId":(item.videoId ?? ""),
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //"visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostNextLyricsAndRelated(url, videoId: item.videoId, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求请求Next歌词/相关内容
    private func requestPostNextLyricsAndRelated(_ url:URL, videoId:String, parameters:Parameters, completion:@escaping(((String?,String?)) -> Void)) {
        //发送post请求
        let request = MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonNext.self) { [weak self] (response) in
            guard let self = self else {return}
            relatedRequests[videoId] = nil
            switch response.result {
            case .success(let value):
                let result = parsingNextLyricsAndRelated(value)
                //回掉数据
                completion(result)
            case .failure(let error):
                //当前无数据
                completion((nil,nil))
                // 请求失败，处理错误
                handleError(url, error: error, status: false)
            }
        }
        relatedRequests[videoId] = request
    }
    
    //MARK: - 请求player播放资源
    /// 请求Player(单曲/视频)播放资源
    /// - Parameter item: 请求的预览实体
    func requestAndroidPlayer(_ videoId: String, playlistId: String, clickTrackingParams: String?, completion:@escaping ((([String],[Int],[String])?, [String]?) -> Void)){
        guard netWorkStatu != .notReachable else {
            completion(nil,nil)
            return
        }
        //拼接出player路径
        let path = header+point+player
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，videoId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "videoId":videoId,
            "prettyPrint":"false",
            "clickTracking":[
                "clickTrackingParams": clickTrackingParams ?? ""
            ],
            "context":[
                "client":[
                    "clientName": "ANDROID_MUSIC",
                    "visitorData":visitorData,
                    "clientVersion": playerVersion,
                    "platform":"MOBILE",
                    "browserVersion":"125.0.0.0",

                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestAndroidPostPlayer(url, videoId: videoId, parameters: parameters){ resourceUlrs, coverUrls in
            completion(resourceUlrs, coverUrls)
        }
    }
    private func requestAndroidPostPlayer(_ url:URL, videoId:String, parameters:Parameters, completion:@escaping((([String],[Int],[String])?, [String]?) -> Void)) {
        //发送post请求
        let request = PlayerSeesion.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonAndroidPlayer.self) { [weak self] (response) in
            guard let self = self else {return}
            self.playerRequests[videoId] = nil // 清除请求
            switch response.result {
            case .success(let value):
                parsingAndroidPlayer(value) { resourceUlrs, coverUrls in
                    completion(resourceUlrs, coverUrls)
                }
            case .failure(let error):
                //当前无数据
                completion(nil,nil)
                // 请求失败，处理错误
                handleError(url, error: error, status: false)
            }
        }
        //根据当前videoId添加request
        playerRequests[videoId] = request
    }
    ///移除补全任务请求任务
    func removeVideoResource(_ videoId: String) {
//        playerRequests[videoId]?.cancel()
        playerRequests.removeValue(forKey: videoId)
//        relatedRequests[videoId]?.cancel()
        relatedRequests.removeValue(forKey: videoId)
    }
//    func requestPlayer(_ videoId: String, playlistId: String, completion:@escaping ((([String],[Float],[String]), [String]?) -> Void)){
//        //拼接出player路径
//        let path = header+point+player
//        //设置url
//        guard let url = URL(string: path) else {
//            print("Url is Incorrect")
//            return
//        }
//        //设置参数，videoId与params参数是必定携带内容
//        let parameters:[String:Any] = [
//            "videoId":videoId,
//            "prettyPrint":"false",
//            "context":[
//                "client":[
//                    "clientName": "WEB_REMIX",
////                    //"visitorData":visitorData,
////                    "originalUrl":"https://music.youtube.com/watch?v=\(videoId)",
//                    //当前访问版本（日期值）
//                    "clientVersion": clientVersion,
//                    "platform":"MOBILE",
//                    //语言
//                    "hl":Language_first_local,
//                    //地址
//                    "gl":locaton ?? ""
//                ]
//            ],
//            "playbackContext": [
//                "contentPlaybackContext": [
//                    "signatureTimestamp": MP_WebWork.shared.signatureTimestamp ?? 0
//                ]
//            ]
//        ]
//        //guard netWorkStatu != .notReachable else {return}
//        requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
//            completion(resourceUlrs, coverUrls)
//        }
//    }
    //请求单曲/视频
//    private func requestPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)) {
//        //发送post请求
//        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonPlayer.self) { [weak self] (response) in
//            guard let self = self else {return}
//
//            switch response.result {
//            case .success(let value):
//                parsingPlayer(value) { resourceUlrs, coverUrls in
//                    completion(resourceUlrs, coverUrls)
//                }
//            case .failure(let error):
//                // 请求失败，处理错误
//                print("Request failed: \(error)")
//            }
//        }
//    }
    //MARK: - 请求歌词
    /// 请求歌词
    /// - Parameter lyricId: 歌词id
    func requestLyric(_ lyricId:String, completion:@escaping((String) -> Void)) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "browseId":lyricId,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //"visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostLyric(url, parameters: parameters) { lyrics in
            completion(lyrics)
        }
    }
    //请求歌词
    private func requestPostLyric(_ url:URL, parameters:Parameters, completion:@escaping((String) -> Void)) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonLyrics.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                completion(parsingLyrics(value) ?? "")
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///请求相关内容
    func requestRecommend(_ browseId:String, completion: @escaping ([MPPositive_RecommendListViewModel]) -> Void) {
        //拼接出browse路径
        let path = header+point+browse
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数，browseId与params参数是必定携带内容
        let parameters:[String:Any] = [
            "browseId":browseId,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //"visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostRecommend(url, parameters: parameters) { results in
            completion(results)
        }
    }
    ///请求相关内容
    private func requestPostRecommend(_ url:URL, parameters:Parameters, completion: @escaping ([MPPositive_RecommendListViewModel]) -> Void) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonRecommend.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let contents = value.contents?.sectionListRenderer?.contents {
                    let section = parsingRecommend(contents)
                    completion(section)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    
    //MARK: - 请求搜索建议
    /// 请求搜索建议
    /// - Parameter content: 用户输入的文本
    func requestSearchSuggestions(_ content:String, completion:@escaping(([[MPPositive_SearchSuggestionItemModel]]) -> Void)) {
        //拼接路径
        let path = header+point+suggestions
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "input":content,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    //"visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostSearchSuggestions(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求搜索建议
    private func requestPostSearchSuggestions(_ url:URL, parameters:Parameters, completion:@escaping(([[MPPositive_SearchSuggestionItemModel]]) -> Void)) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonSearchSuggestions.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                parsingSearchSuggestions(value) { results in
                    completion(results)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    
    /// 请求搜索预览结果
    /// - Parameter text: 用户请求文本
    func requestSearchPreviewResults(_ text:String, completion:@escaping (([MPPositive_SearchResultListViewModel]) -> Void)) {
        //拼接路径
        let path = header+point+search
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //检索关键词
        guard trashKeyWords.contains(text) == false else {
            //是禁用关键词
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.4) {
                print("是禁用关键词")
                completion([])
            }
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "query":text,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostSearchPreviewResults(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求搜索预览结果
    private func requestPostSearchPreviewResults(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultListViewModel]) -> Void)) {
        guard netWorkStatu != .notReachable else {
            completion([])
            handleError(url, error: nil)
            return
        }
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonSearchPreviewResults.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let contents = value.contents?.tabbedSearchResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents {
                    let result = parsingSearchPreviewResults(contents)
                    print("一共搜索到\(result.count)相关内容模块")
                    completion(result)
                }
            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    
    
    /// 请求搜索分类结果
    /// - Parameters:
    ///   - query: 搜索文本
    ///   - params: 事件参数码
    func requestSearchTypeResults(_ query:String, params:String, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
        //拼接路径
        let path = header+point+search
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "query":query,
            "prettyPrint":"false",
            "params":params,
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostSearchTypeResults(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求搜索分类结果
    private func requestPostSearchTypeResults(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonSearchTypeResults.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let musicShelfRenderer = value.contents?.tabbedSearchResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents?.first?.musicShelfRenderer {
                    completion(parsingSearchTypeResults(musicShelfRenderer))
                }else {
                    value.contents?.tabbedSearchResultsRenderer?.tabs?.first?.tabRenderer?.content?.sectionListRenderer?.contents?.forEach({ item in
                        if let musicShelfRenderer = item.musicShelfRenderer{
                            completion(self.parsingSearchTypeResults(musicShelfRenderer))
                        }
                    })
                }

            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    
    /// 请求搜索分类继续结果
    /// - Parameters:
    ///   - continuation: 继续编码
    ///   - itct: 继续事件码
    func requestSearchTypeContinuation(_ continuation:String, itct:String, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
        //拼接路径
        let path = header+point+search
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "ctoken":continuation,
            "continuation":continuation,
            "type":"next",
            "itct":itct,
            "prettyPrint":false,
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": clientVersion,
                    "platform":"MOBILE",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":locaton ?? ""
                ]
            ]
        ]
        //guard netWorkStatu != .notReachable else {return}
        requestPostSearchTypeContinuation(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求搜索分类继续结果
    private func requestPostSearchTypeContinuation(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SearchResultItemViewModel], String?, String?))->Void) {
        //发送post请求
        MPSession.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonSearchTypeContinuation.self) { [weak self] (response) in
            guard let self = self else {return}
            switch response.result {
            case .success(let value):
                if let musicShelfContinuation = value.continuationContents?.musicShelfContinuation {
                    completion(parsingSearchTypeContinuation(musicShelfContinuation))
                }

            case .failure(let error):
                // 请求失败，处理错误
                handleError(url, error: error)
            }
        }
    }
    ///首页错误处理
    private func homeError(error:AFError?) {
        // 根据错误类型处理
        if let statusCode = error?.responseCode {
            switch statusCode {
            case 400...499:
                print("请求错误，错误码: \(statusCode)。")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Request Error, Code:\(statusCode)")
                MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
                return
            case 500...599:
                print("服务器错误，错误码: \(statusCode)。")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Server Error, Code:\(statusCode)")
            default:
                print("其他 HTTP 错误，错误码: \(statusCode)。")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("HTTP Error, Code:\(statusCode)")
            }
        } else if let underlyingError = error?.underlyingError as? URLError {
            switch underlyingError.code {
            case .notConnectedToInternet:
                print("网络连接不可用，请检查你的网络设置")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Network Unavailable, Error:\(underlyingError.localizedDescription)")
            case .timedOut:
                print("请求超时，即将重启请求")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Timed Out, Error:\(underlyingError.localizedDescription)")
                MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
                return
            case .networkConnectionLost:
                print("网络权限开启，但网络本身不可用，请检查你的网络设置")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("International comics not yet launched, Error:\(underlyingError.localizedDescription)")
            case .cannotLoadFromNetwork:
                print("请求证书失效，即将重启请求")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("SSL Error, Error:\(underlyingError.localizedDescription)")
                MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
                return
            case .cannotConnectToHost:
                print("服务器响应失败，请待会儿调用")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Server not present, Error:\(underlyingError.localizedDescription)")
            case .badURL:
                print("链接失败，即将重启请求")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Bad URL, Error:\(underlyingError.localizedDescription)")
                MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
                return
            case .cannotDecodeContentData:
                print("解析响应体失败，即将重启请求")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Can't Decode Content Data, Error:\(underlyingError.localizedDescription)")
                MPPositive_BrowseLoadViewModel.shared.reloadBrowseLists()
                return
            default:
                print("NSURL 错误，错误码: \(underlyingError.code.rawValue)。")
                MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Request Error, Error:\(underlyingError.localizedDescription)")
            }
        } else {
            print("未知错误: \(error?.localizedDescription ?? "")")
            pingYoutube { status in
                if status {
                    //ping成功了，说明当前地区可以访问油管本体，但是不能属于油管音乐服务区
                    MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("Can access YouTube, but not in the service area")
                }else {
                    MP_AnalyticsManager.shared.home_b_module_showfailure_errorAction("No Area")
                }
            }
        }
        if browseRequestErrorBlock != nil {
            browseRequestErrorBlock!()
        }
    }
    ///二次检索网络是否拉通了
    private func pingYoutube(completion: @escaping (Bool) -> Void) {
        guard let url = URL(string: "https://www.youtube.com/") else {return}
        AF.request(url).response { response in
            if let error = response.error {
                print("Ping failed with error: \(error)")
                completion(false)
            } else {
                print("Ping successful, response code: \(response.response?.statusCode ?? -1)")
                completion(true)
            }
        }
    }
    
    ///通用错误处理方法
    private func handleError(_ url: URL, error:AFError?, status:Bool = true) {
        // 根据错误类型处理
        if let statusCode = error?.responseCode {
            switch statusCode {
            case 400...499:
                print("\(url)请求错误，错误码: \(statusCode)。")
            case 500...599:
                print("\(url)服务器错误，错误码: \(statusCode)。")
            default:
                print("\(url)其他 HTTP 错误，错误码: \(statusCode)。")
            }
        } else if let underlyingError = error?.underlyingError as? URLError {
            switch underlyingError.code {
            case .notConnectedToInternet:
                print("\(url)网络连接不可用，请检查你的网络设置。")
            case .timedOut:
                print("\(url)请求超时，请稍后重试。")
            default:
                print("\(url)NSURL 错误，错误码: \(underlyingError.code.rawValue)。")
            }
        } else {
            print("\(url)未知错误: \(error?.localizedDescription ?? "")")
        }
        if status {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
                //统一发一个报错通知
                NotificationCenter.notificationKey.post(notificationName: .netWork_error_deal)
            }
        }
    }
}
//MARK: - 数据解析
extension MP_NetWorkManager {
    //MARK: - 浅层解析
    ///解析预览内容_Contents
    private func parsingBrowseContents(_ content:JsonBrowses.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content) {
        //获取预览结构体中需要的数据（模块标题；歌曲信息:封面路径，音乐标题，歌手姓名，列表id和视频id）
        var browses:[MPPositive_BrowseModuleListViewModel] = []
        var continuation:String?
        var itct:String?
        //循环获取音乐内容
        content.sectionListRenderer?.contents?.forEach({ content in
            //该循环获取预览模块内容，生成一个预览模型接收数据
            let browse = MPPositive_BrowseModuleListViewModel()
            browse.title = content.musicCarouselShelfRenderer?.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.text
            //循环音乐内容组
            content.musicCarouselShelfRenderer?.contents?.forEach({ content in
                //设置标题、歌手、专辑/列表
                if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                    if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        browse.items.append(.init(item))
                    }
                }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                    browse.items.append(.init(d))
                }
            })
            browses.append(browse)
        })
        if let nextContinuationData = content.sectionListRenderer?.continuations?.first {
            continuation = nextContinuationData.nextContinuationData?.continuation
            itct = nextContinuationData.nextContinuationData?.clickTrackingParams
        }
        guard browseRequestStateBlock != nil else {
            return
        }
        //传递解析数据
        self.browseRequestStateBlock!(browses, false)
        //重新赋值，直到没有下一阶段数据为止
        self.continuationAndItct = (continuation,itct)
    }
    ///排行榜艺术家数据解析
    private func parsingCharts(_ contents:[JsonCharts.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) {
        var browses:[MPPositive_BrowseModuleListViewModel] = []
        contents.forEach { content in
            //检索content是否存在二阶段数据
            if let musicCarouselShelfRenderer = content.musicCarouselShelfRenderer {
                //存在，继续操作
                let browse = MPPositive_BrowseModuleListViewModel()
                browse.title = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.text
                //获取数据
                musicCarouselShelfRenderer.contents?.forEach({ content in
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        let item = MPPositive_BrowseItemModel()
                        //设置封面
                        item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
                        //设置标题
                        for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() {
                            if index == 0 {
                                //添加主标题
                                item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
                            }else {
                                item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
                            }
                        }
                        //设置ID
                        item.itemType = .artist
                        item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
                        item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
                        item.pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                        browse.items.append(.init(item))
                    }
                })
                browses.append(browse)
            }
        }
        //清理为空的数据
        browses = browses.filter({$0.items.contains(where: {$0.browseItem.pageType == "MUSIC_PAGE_TYPE_ARTIST"})})
        guard browseRequestStateBlock != nil else {
            return
        }
        //传递解析数据
        self.browseRequestStateBlock!(browses, true)
        //移除队列
        browseQueque = nil
    }
    ///解析预览内容_ContinuationContents
    private func parsingBrowseContinuationContents(_ continuationContents:JsonBrowses.ContinuationContents) {
        //获取预览结构体中需要的数据（模块标题；歌曲信息:封面路径，音乐标题，歌手姓名，列表id和视频id）
        var browses:[MPPositive_BrowseModuleListViewModel] = []
        var continuation:String?
        var itct:String?
        //循环获取音乐内容
        continuationContents.sectionListContinuation?.contents?.forEach({ content in
            //该循环获取预览模块内容，生成一个预览模型接收数据
            let browse = MPPositive_BrowseModuleListViewModel()
            browse.title = content.musicCarouselShelfRenderer?.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.text
            //循环音乐内容组
            content.musicCarouselShelfRenderer?.contents?.forEach({ content in
                //设置标题、歌手、专辑/列表
                if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                    if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        browse.items.append(.init(item))
                    }
                }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                    browse.items.append(.init(d))
                }
            })
            browses.append(browse)
        })
        if let nextContinuationData = continuationContents.sectionListContinuation?.continuations?.first {
            continuation = nextContinuationData.nextContinuationData?.continuation
            itct = nextContinuationData.nextContinuationData?.clickTrackingParams
        }
        guard browseRequestStateBlock != nil else {
            return
        }
        //传递解析数据
        self.browseRequestStateBlock!(browses, false)
        //重新赋值，直到没有下一阶段数据为止
        self.continuationAndItct = (continuation,itct)
    }
    ///解析列表_Contents_一号版本
    private func parsingListSingleContents(_ content:JsonListOrAlbum.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content) -> [MPPositive_BrowseItemViewModel] {
        var items:[MPPositive_BrowseItemViewModel] = []
        //循环获取音乐内容
        content.sectionListRenderer?.contents?.forEach({ content in
            //循环音乐内容组
            if let musicPlaylistShelfRenderer = content.musicPlaylistShelfRenderer {
                musicPlaylistShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                        items.append(.init(d))
                    }
                })
            }else if let musicShelfRenderer = content.musicShelfRenderer{
                musicShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                        items.append(.init(d))
                    }
                })
            }
        })
        return items
    }
    ///解析列表_Contents_二号版本
    private func parsingListTwoContents(_ content:JsonListOrAlbum.Contents.TwoColumnBrowseResultsRenderer.SecondaryContents) -> [MPPositive_BrowseItemViewModel] {
        var items:[MPPositive_BrowseItemViewModel] = []
        //循环获取音乐内容
        content.sectionListRenderer?.contents?.forEach({ content in
            //循环音乐内容组
            if let musicPlaylistShelfRenderer = content.musicPlaylistShelfRenderer {
                musicPlaylistShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                        items.append(.init(d))
                    }
                })
            }else if let musicShelfRenderer = content.musicShelfRenderer{
                musicShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                        items.append(.init(d))
                    }
                })
            }
        })
        return items
    }
    ///解析列表_Header_一号版本
    private func parsingListSingleHeaders(_ header:JsonListOrAlbum.Header) -> MPPositive_ListHeaderModel {
        let listHeader = MPPositive_ListHeaderModel()
        if let musicDetailHeaderRenderer = header.musicDetailHeaderRenderer {
            //主标题
            listHeader.maintitle = musicDetailHeaderRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
            //次标题
            listHeader.subtitle = musicDetailHeaderRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
            //三级标题
            listHeader.thirdtitle = musicDetailHeaderRenderer.secondSubtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
            //说明/介绍
            listHeader.forDescription = musicDetailHeaderRenderer.description?.runs?.reduce("", { $0 + ($1.text ?? "")})
            //图片（默认获取最后/最大的）
            listHeader.coverUrl = musicDetailHeaderRenderer.thumbnail?.croppedSquareThumbnailRenderer?.thumbnail?.thumbnails?.last?.url
        }else if let musicImmersiveHeaderRenderer = header.musicImmersiveHeaderRenderer {
            listHeader.maintitle = musicImmersiveHeaderRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
            listHeader.forDescription = musicImmersiveHeaderRenderer.description?.runs?.reduce("", { $0 + ($1.text ?? "")})
            listHeader.coverUrl = musicImmersiveHeaderRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.last?.url
        }
        return listHeader
    }
    ///解析列表_Header_二号版本
    private func parsingListTwoHeaders(_ header:JsonListOrAlbum.Contents.TwoColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content.MusicResponsiveHeaderRenderer) -> MPPositive_ListHeaderModel {
        let listHeader = MPPositive_ListHeaderModel()
        //封面
        if let thumbnail = header.thumbnail {
            listHeader.coverUrl = thumbnail.musicThumbnailRenderer?.thumbnail?.thumbnails?.last?.url
        }
        //标题
        if let title = header.title {
            listHeader.maintitle = title.runs?.reduce("", { $0 + ($1.text ?? "")})
        }
        //副标题
        if let subtitle = header.subtitle {
            listHeader.subtitle = subtitle.runs?.reduce("", { $0 + ($1.text ?? "")})
        }
        //说明
        if let description = header.description?.musicDescriptionShelfRenderer?.description?.runs?.first?.text {
            //对说明文本裁剪
            let _d = truncateTextAfterTwoNewlines(from: description)
            listHeader.forDescription = _d
        }
        return listHeader
    }
    
    ///解析艺术家_Header
    private func parsingArtistHeaders(_ header:JsonArtist.Header) -> MPPositive_ArtistHeaderModel {
        let model = MPPositive_ArtistHeaderModel()
        model.title = header.musicImmersiveHeaderRenderer?.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
        model.subscriptions = header.musicImmersiveHeaderRenderer?.subscriptionButton?.subscribeButtonRenderer?.subscriberCountText?.runs?.reduce("", { $0 + ($1.text ?? "")})
        model.subscriptionedText = header.musicImmersiveHeaderRenderer?.subscriptionButton?.subscribeButtonRenderer?.subscribedButtonText?.runs?.reduce("", { $0 + ($1.text ?? "")})
        model.fordescription = header.musicImmersiveHeaderRenderer?.description?.runs?.reduce("", { $0 + ($1.text ?? "")})
        model.fordescription = truncateTextAfterTwoNewlines(from:  model.fordescription ?? "")
        model.thumbnails =  header.musicImmersiveHeaderRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
        return model
    }
    ///解析艺术家_Contents
    private func parsingArtistContents(_ contents:[JsonArtist.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) -> [MPPositive_ArtistContentListViewModel] {
        var listArray:[MPPositive_ArtistContentListViewModel] = []
        ///遍历解析模块内容
        contents.forEach { content in
            var title:String?
            var itemViews:[MPPositive_BrowseItemViewModel] = []
            var id:String?
            var params:String?
            if let musicShelfRenderer = content.musicShelfRenderer {
                //这是首选模块
                title = musicShelfRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
                //获取模块的事件值
                id = musicShelfRenderer.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.browseId
                params = musicShelfRenderer.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params
                //解析模块内容
                musicShelfRenderer.contents?.forEach({ item in
                    if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer, let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)  {
                        itemViews.append(.init(asd))
                    }
                })
            }
            if let musicCarouselShelfRenderer = content.musicCarouselShelfRenderer {
                //这是次选模块
                title = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
                id = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.browseId
                params = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.navigationEndpoint?.browseEndpoint?.params
                //解析模块内容
                musicCarouselShelfRenderer.contents?.forEach({ item in
                    if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                        itemViews.append(.init(d))
                    }
                })
            }
            let list = MPPositive_ArtistContentListViewModel(title, itemViews: itemViews, browseId: id, params: params)
            listArray.append(list)
        }
        return listArray
    }
    ///解析艺术家更多_More
    private func parsingArtistMore(_ content:JsonArtistMore.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content) -> ([MPPositive_BrowseItemViewModel], String?, String?) {
        //返回一组预览实体和一对继续编码
        var continuation:String?
        var clickTrackingParams:String?
        var array:[MPPositive_BrowseItemViewModel] = []
        //判断返回内容是音视频还是专辑列表
        if let musicPlaylistShelfRenderer = content.musicPlaylistShelfRenderer {
            //是音视频
            musicPlaylistShelfRenderer.contents?.forEach({ item in
                if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer {
                    if let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        array.append(.init(asd))
                    }
                }
            })
            continuation = musicPlaylistShelfRenderer.continuations?.first?.nextContinuationData?.continuation
            clickTrackingParams = musicPlaylistShelfRenderer.continuations?.first?.nextContinuationData?.clickTrackingParams
        }
        if let gridRenderer = content.gridRenderer {
            //是专辑列表
            gridRenderer.items?.forEach({ item in
                if let musicTwoRowItemRenderer = item.musicTwoRowItemRenderer, let d = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                    array.append(.init(d))
                }
                continuation = gridRenderer.continuations?.first?.nextContinuationData?.continuation
                clickTrackingParams = gridRenderer.continuations?.first?.nextContinuationData?.clickTrackingParams
            })
        }
        return (array, continuation, clickTrackingParams)
    }
    ///解析艺术家更多继续_Continuation
    private func parsingArtistMoreContinuation(_ musicPlaylistShelfContinuation: JsonArtistMore.ContinuationContents.MusicPlaylistShelfContinuation) -> ([MPPositive_BrowseItemViewModel], String?, String?) {
        //返回一组预览实体和一对继续编码
        var continuation:String?
        var clickTrackingParams:String?
        var array:[MPPositive_BrowseItemViewModel] = []
        //判断返回内容是音视频还是专辑列表
        if let contents = musicPlaylistShelfContinuation.contents {
            contents.forEach { item in
                if let musicResponsiveListItemRenderer = item.musicResponsiveListItemRenderer {
                    if let asd = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        array.append(.init(asd))
                    }
                }
            }
        }
        continuation = musicPlaylistShelfContinuation.continuations?.first?.nextContinuationData?.continuation
        clickTrackingParams = musicPlaylistShelfContinuation.continuations?.first?.nextContinuationData?.clickTrackingParams
        return (array,continuation,clickTrackingParams)
    }
    
    ///解析相关内容_Next_中的接下来播放列表
    private func parsingNextList(_ next:JsonNext) -> [MPPositive_SongItemModel] {
        var array:[MPPositive_SongItemModel] = []
        if let tabs = next.contents?.singleColumnMusicWatchNextResultsRenderer?.tabbedRenderer?.watchNextTabbedResultsRenderer?.tabs {
            if let tab = tabs.first {
                //获取一张播放列表
                for (index, content) in (tab.tabRenderer?.content?.musicQueueRenderer?.content?.playlistPanelRenderer?.contents ?? []).enumerated() {
                    if let playlistPanelVideoRenderer = content.playlistPanelVideoRenderer {
                        //生成一个音乐实体，用来装填部分数据
                        let song = MPPositive_SongItemModel()
                        song.index = index
                        song.title = playlistPanelVideoRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
                        song.longBylineText = playlistPanelVideoRenderer.longBylineText?.runs?.reduce("", { $0 + ($1.text ?? "")})
                        song.lengthText = playlistPanelVideoRenderer.lengthText?.runs?.reduce("", { $0 + ($1.text ?? "")})
                        song.shortBylineText = playlistPanelVideoRenderer.shortBylineText?.runs?.reduce("", { $0 + ($1.text ?? "")})
                        song.reviewUrls = playlistPanelVideoRenderer.thumbnail?.thumbnails?.map({$0.url ?? ""})
                        song.videoId = playlistPanelVideoRenderer.videoId
                        song.clickTrackingParams = playlistPanelVideoRenderer.trackingParams
                        array.append(song)
                    }
                }
            }
        }
        return array
    }
    
    /// 解析相关内容_Next_中的歌词ID和相关内容ID（两个ID都适用于用brwose接口）
    /// - Parameter next: 需要解析的next组
    /// - Returns: 0位是歌词ID，1位相关内容ID
    private func parsingNextLyricsAndRelated(_ next:JsonNext) -> (String?,String?){
        if let tabs = next.contents?.singleColumnMusicWatchNextResultsRenderer?.tabbedRenderer?.watchNextTabbedResultsRenderer?.tabs {
            if tabs.count == 3 {
                //歌词ID
                let lyrcisId = tabs[1].tabRenderer?.endpoint?.browseEndpoint?.browseId
                //相关内容ID
                let relatedID = tabs[2].tabRenderer?.endpoint?.browseEndpoint?.browseId
                return (lyrcisId, relatedID)
            }else if tabs.count == 2 {
                //歌词ID
                let lyrcisId = tabs[1].tabRenderer?.endpoint?.browseEndpoint?.browseId
                return (lyrcisId, nil)
            }else {
                return (nil,nil)
            }
        }else {
            return (nil,nil)
        }
    }
    ///解析模块数据_Genres
    private func parsingGenres(_ contents:[JsonGenres.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) -> [MPPositive_GridViewModel] {
        var array:[MPPositive_GridViewModel] = []
        contents.forEach { content in
            if let items = content.gridRenderer?.items {
                items.forEach { item in
                    if let text = item.musicNavigationButtonRenderer?.buttonText?.runs?.first?.text, let leftStripeColor = item.musicNavigationButtonRenderer?.solid?.leftStripeColor, let browseId = item.musicNavigationButtonRenderer?.clickCommand?.browseEndpoint?.browseId, let params = item.musicNavigationButtonRenderer?.clickCommand?.browseEndpoint?.params {
                        let gride = MPPositive_GridModel(title: text, stringColor: leftStripeColor, browseId: browseId, params: params)
                        array.append(.init(gride))
                    }
                }
            }
        }
        return array
    }
    ///解析模块详情数据_Mood
    private func parsingMoodDetails(_ content:JsonBrowses.Contents.SingleColumnBrowseResultsRenderer.Tab.TabRenderer.Content) -> [MPPositive_BrowseModuleListViewModel] {
        //获取预览结构体中需要的数据（模块标题；歌曲信息:封面路径，音乐标题，歌手姓名，列表id和视频id）
        var browses:[MPPositive_BrowseModuleListViewModel] = []
        //循环获取音乐内容
        content.sectionListRenderer?.contents?.forEach({ content in
            //该循环获取预览模块内容，生成一个预览模型接收数据
            let browse = MPPositive_BrowseModuleListViewModel()
            if let musicCarouselShelfRenderer = content.musicCarouselShelfRenderer {
                browse.title = musicCarouselShelfRenderer.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.first?.text
                //循环音乐内容组
                musicCarouselShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            browse.items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                        if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                            browse.items.append(.init(item))
                        }
                    }
                })
                if browse.items.isEmpty != true {
                    browses.append(browse)
                }
            }else if let gridRenderer = content.gridRenderer {
                browse.title = gridRenderer.header?.gridHeaderRenderer?.title?.runs?.first?.text
                gridRenderer.items?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            browse.items.append(.init(item))
                        }
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                        if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer) {
                            browse.items.append(.init(item))
                        }
                    }
                })
                if browse.items.isEmpty != true {
                    browses.append(browse)
                }
            }
        })
        return browses
    }
    /// 解析播放器_Player
    /// - Parameters:
    ///   - player: player库
    ///   - completion: 传递两个字符串数组，第一个资源路径组，第二个是封面路径组
//    private func parsingPlayer(_ player:JsonPlayer, completion:@escaping((([String],[Float],[String]), [String]?) -> Void)){
//        var infos:[String]?
//        //解析player，获取资源库和信息库
//        if let videoDetails = player.videoDetails {
//            infos = parsingPlayerVideoDetails(videoDetails)
//        }
//        if let streamingData = player.streamingData {
//            parsingPlayerStreamingData(streamingData){ videos,floats,approxDurationMs in
//                completion((videos,floats,approxDurationMs),infos)
//            }
//        }
//    }
    private func parsingAndroidPlayer(_ player:JsonAndroidPlayer,completion:@escaping((([String],[Int],[String]), [String]?) -> Void)){
        var infos:[String]?
        //解析player，获取资源库和信息库
        if let videoDetails = player.videoDetails {
            infos = parsingAndroidPlayerVideoDetails(videoDetails)
        }
        if let streamingData = player.streamingData {
            parsingAndroidPlayerStreamingData(streamingData){ videos,itags,mimeType in
                completion((videos,itags,mimeType),infos)
            }
        }
    }
    
    /// 解析播放器_StreamingData
    /// - Parameters:
    ///   - streamingData: 资源库
    ///   - completion: 第一位是音频资源，第二位是视频资源
    private func parsingAndroidPlayerStreamingData(_ streamingData:JsonAndroidPlayer.StreamingData, completion:@escaping(([String],[Int],[String]) -> Void)) {
        var videos:[String] = []
        var itags:[Int] = []
        var mimeType:[String] = []
        var allFormats = (streamingData.formats ?? []) + (streamingData.adaptiveFormats ?? [])
        //判断第一个itag值是否大于100，当第一条itag大于100，那么第一条资源将不可用，将itag140移动到首位
        if let first = allFormats.first, (first.itag ?? 0) >= 100 {
            //第一条资源不可用，将音轨itag140资源移动到第一条
            if let index = allFormats.firstIndex(where: {$0.itag == 140 || $0.itag == 251}) {
                let itag = allFormats.remove(at: index)
                allFormats.insert(itag, at: 0)
            }
        }
        for format in allFormats {
            videos.append(format.url ?? "")
            itags.append(format.itag ?? 0)
            mimeType.append(format.mimeType ?? "")
        }
        completion(videos,itags,mimeType)
    }
//    private func parsingPlayerStreamingData(_ streamingData:JsonPlayer.StreamingData, completion:@escaping(([String],[Float],[String]) -> Void)) {
//        var group:DispatchGroup? = DispatchGroup()
//        var videos:[String] = []
//        var floats:[Float] = []
//        var approxDurationMs:[String] = []
//        let allFormats = (streamingData.formats ?? []) + (streamingData.adaptiveFormats ?? [])
//        for format in allFormats {
//            if let signatureCipher = format.signatureCipher {
//                // 进入DispatchGroup，表示开始一个异步任务
//                group?.enter()
//                //获得资源签名，开始解密签名内容
//                parsingPlayerSignatureCipher(signatureCipher) { result in
//                    //这是条视频资源
//                    videos.append(result)
//                    floats.append(format.bitrate ?? 0)
//                    approxDurationMs.append(format.approxDurationMs ?? "")
//                    // 离开DispatchGroup，表示异步任务完成
//                    group?.leave()
//                }
//            }
//        }
//        group?.notify(queue: .main) {
//            completion(videos, floats, approxDurationMs)
//            group = nil
//        }
//    }
    ///解析加密签名_SignatureCipher
    private func parsingPlayerSignatureCipher(_ signatureCipher:String, completion:@escaping((String) -> Void)) {
//        print("Resources-SignatureCipher:\(signatureCipher)")
        //该加密资源有两段式加密，先进行百分比加密解码
        let originalURLString = seperatorOff(String(signatureCipher))
        //第一段加密资源为权限资源
        guard let sRange = originalURLString.range(of: "s=") else {
            return
        }
        guard let spSigRange = originalURLString.range(of: "&sp=sig", range: sRange.upperBound..<originalURLString.endIndex) else {
            return
        }
        //第二段是url
        guard let urlRange = originalURLString.range(of: "&url=")?.lowerBound else {
            return
        }
        let urlStartIndex = originalURLString.index(urlRange, offsetBy: 5) // "&url=" 的长度为 5
        //提取URl路径
        let urlSubstring = originalURLString[urlStartIndex...] // 从 &url= 之后开始提取
        let signString = String(originalURLString[sRange.upperBound..<spSigRange.lowerBound])
        
//        //加密的权限请求解码
//        MP_WebWork.shared.excuteJavaScript(signString) { result in
//            //与权限拼接
//            let abString = urlSubstring  + "&sig=" + result
//            completion(abString)
//        }
    }
    /// 解析播放器_VideoDetails
    /// - Parameter videoDetails: 信息库
    /// - Returns: 返回一个元组，值分别为 videoId，title，author，urls
    private func parsingAndroidPlayerVideoDetails(_ videoDetails:JsonAndroidPlayer.VideoDetails) -> [String]? {
        var urls:[String]?
        videoDetails.thumbnail?.thumbnails?.forEach({ item in
            if item.url != nil {
                if urls != nil {
                    urls!.append(item.url!)
                }else {
                    urls = []
                    urls!.append(item.url!)
                }
            }
        })
        return urls
    }
//    private func parsingPlayerVideoDetails(_ videoDetails:JsonPlayer.VideoDetails) -> [String]? {
//        var urls:[String]?
//        videoDetails.thumbnail?.thumbnails?.forEach({ item in
//            if item.url != nil {
//                if urls != nil {
//                    urls!.append(item.url!)
//                }else {
//                    urls = []
//                    urls!.append(item.url!)
//                }
//            }
//        })
//        return urls
//    }
    ///解析歌词_Lyrics
    private func parsingLyrics(_ lyrics:JsonLyrics) -> String? {
        if let first = lyrics.contents?.sectionListRenderer?.contents?.first {
            return first.musicDescriptionShelfRenderer?.description?.runs?.first?.text
        }
        return ""
    }
    ///解析相关内容
    private func parsingRecommend(_ contents:[JsonRecommend.Contents.SectionListRenderer.Content]) -> [MPPositive_RecommendListViewModel] {
        var sectionLists:[MPPositive_RecommendListViewModel] = []
        contents.forEach { section in
            let list = MPPositive_RecommendListViewModel()
            list.title = section.musicCarouselShelfRenderer?.header?.musicCarouselShelfBasicHeaderRenderer?.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
            section.musicCarouselShelfRenderer?.contents?.forEach({ content in
                if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer{
                    if let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        list.items.append(.init(item))
                    }
                }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer{
                    if let item = parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)  {
                        list.items.append(.init(item))
                    }
                }
            })
            sectionLists.append(list)
        }
        return sectionLists
    }
    /// 解析搜索建议_SearchSuggestions
    /// - Parameters:
    ///   - searchSuggestions: 需要解析搜索建议
    ///   - completion: 回掉两组搜索建议组
    private func parsingSearchSuggestions(_ searchSuggestions:JsonSearchSuggestions, completion:@escaping([[MPPositive_SearchSuggestionItemModel]]) -> Void) {
        if let contents = searchSuggestions.contents {
            var sections:[[MPPositive_SearchSuggestionItemModel]] = []
            contents.forEach { section in
                var suggestions:[MPPositive_SearchSuggestionItemModel] = []
                section.searchSuggestionsSectionRenderer?.contents?.forEach({ content in
                    //生成搜索建议模型
                    let item = MPPositive_SearchSuggestionItemModel()
                    if let searchSuggestionRenderer = content.searchSuggestionRenderer {
                        //这里是搜索词条建议
                        item.title = searchSuggestionRenderer.suggestion?.runs?.reduce("", { $0 + ($1.text ?? "")})
                    }else if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        var reviewUrls:[String] = []
                        //这里是搜索音乐建议
                        musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.forEach({ thumbnail in
                            reviewUrls.append(thumbnail.url ?? "")
                        })
                        item.reviewUrls = reviewUrls
                        if let flexColumns = musicResponsiveListItemRenderer.flexColumns {
                            for (index,flexColumn) in flexColumns.enumerated() {
                                if index == 0 {
                                    //主标题
                                    item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
                                }else {
                                    //副标题
                                    item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
                                }
                            }
                        }
                    }
                    suggestions.append(item)
                })
                sections.append(suggestions)
            }
            completion(sections)
        }
    }
    ///解析搜索预览结果_SearchPreviewResults
    private func parsingSearchPreviewResults(_ contents:[JsonSearchPreviewResults.Contents.TabbedSearchResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) -> [MPPositive_SearchResultListViewModel]{
        var resultListSections:[MPPositive_SearchResultListViewModel] = []
        contents.forEach { content in
            let resultList = MPPositive_SearchResultListViewModel()
            //判断当前模块是最佳结果还是其它模块
            if let musicCardShelfRenderer = content.musicCardShelfRenderer {
                //当前是最佳结果
                //设置模块标题
                resultList.title = musicCardShelfRenderer.header?.musicCardShelfHeaderBasicRenderer?.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
                //生成第一个内容块（根据内容不同，可能是单曲/歌手/专辑）
                let item = MPPositive_BrowseItemModel()
                //设置第一个内容块的预览图
                item.coverUrls =  musicCardShelfRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
                item.playListId = musicCardShelfRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
                item.clickTrackingParams = musicCardShelfRenderer.trackingParams
                //设置第一个内容块的一级标题和类型和ID
                if let title = musicCardShelfRenderer.title {
                    title.runs?.forEach({ run in
                        item.title = run.text
                        if run.navigationEndpoint?.watchEndpoint != nil {
                            //这个内容块是单曲/视频
                            item.videoId =  run.navigationEndpoint?.watchEndpoint?.videoId
                            item.itemType = .single
                        }else {
                            //这个内容块是艺术家/列表/专辑
                            item.browseId = run.navigationEndpoint?.browseEndpoint?.browseId
                            let pageType = run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                            if youTubeKeys.contains(pageType ?? "") == true {
                                //判断细分
                                if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
                                    item.artistId = run.navigationEndpoint?.browseEndpoint?.browseId
                                    //是艺术家
                                    item.itemType = .artist
                                }else {
                                    //是列表/专辑
                                    item.itemType = .list
                                }
                            }
                        }
                    })
                }
                //设置第一个内容块的二级标题
                if let subtitle = musicCardShelfRenderer.subtitle {
                    item.subtitle = subtitle.runs?.reduce("", { $0 + ($1.text ?? "")})
                }
                //第一个内容块填充完毕
                if item.itemType != nil {
                    resultList.previewItemViews.append(.init(item))
                }
                //设置最佳结果的其他内容块
                if let contents = musicCardShelfRenderer.contents {
                    contents.forEach { content in
                        //生成更多内容块
                        if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                            if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
                                resultList.previewItemViews.append(.init(item))
                            }
                        }
//                        let item = MPPositive_BrowseItemModel()
//                        if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, (musicResponsiveListItemRenderer.playlistItemData != nil || musicResponsiveListItemRenderer.navigationEndpoint != nil) && (musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"){
//                            if let trackingParams = musicResponsiveListItemRenderer.trackingParams {
//                                item.clickTrackingParams = trackingParams
//                            }
//                            //设置预览图
//                            item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
//                            //设置一级标题与二级标题
//                            for (index, flexColumn) in (musicResponsiveListItemRenderer.flexColumns ?? []).enumerated() {
//                                if index == 0 {
//                                    //一级标题
//                                    item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
//                                }else {
//                                    //二级标题
//                                    item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
//                                }
//                            }
//                            item.playListId = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
//                            //设置id和类型
//                            if musicResponsiveListItemRenderer.playlistItemData != nil {
//                                //是单曲
//                                item.itemType = .single
//                                item.videoId = musicResponsiveListItemRenderer.playlistItemData?.videoId
//                            }else {
//                                //是专辑列表/艺术家
//                                item.browseId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
//                                let pageType = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
//                                if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
//                                    //判断细分
//                                    if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
//                                        item.artistId = musicResponsiveListItemRenderer.navigationEndpoint?.browseEndpoint?.browseId
//                                        //是艺术家
//                                        item.itemType = .artist
//                                    }else {
//                                        //是列表/专辑
//                                        item.itemType = .list
//                                    }
//                                }
//                            }
//                        }
//                        if item.title != nil && item.itemType != nil, item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
//                            resultList.previewItemViews.append(.init(item))
//                        }
                    }
                }
                //由于是最佳结果模块,所以没有query和params值
                resultList.query = nil
                resultList.params = nil
            }else if let musicShelfRenderer = content.musicShelfRenderer {
                //当前是其他结果,不存在首选内容块
                //设置模块标题
                resultList.title = musicShelfRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
                //设置内容块
                musicShelfRenderer.contents?.forEach({ content in
                    //专辑/列表/单曲视频/艺术家
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                        resultList.previewItemViews.append(.init(item))
                    }
                })
                //设置query和params值
                if let searchEndpoint = musicShelfRenderer.bottomEndpoint?.searchEndpoint {
                    resultList.query = searchEndpoint.query
                    resultList.params = searchEndpoint.params
                }
            }
            resultListSections.append(resultList)
        }
        resultListSections.forEach { list in
            list.previewItemViews = list.previewItemViews.filter({ item in
                return item.item.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE"
            })
        }
        //移除每一个被禁止的内容
        resultListSections.forEach { list in
            list.previewItemViews = list.previewItemViews.filter({ item in
                return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
            })
        }
        
        resultListSections = resultListSections.filter({$0.previewItemViews.count != 0})
        return resultListSections
    }
    ///解析搜索分页结果
    private func parsingSearchTypeResults(_ musicShelfRenderer:JsonSearchTypeResults.Contents.TabbedSearchResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content.MusicShelfRenderer) -> ([MPPositive_SearchResultItemViewModel], String?, String?) {
        var array:[MPPositive_SearchResultItemViewModel] = []
        if let contents = musicShelfRenderer.contents {
            ///解析内容块
            contents.forEach({ content in
                //专辑/列表/单曲视频/艺术家
                let item = MPPositive_BrowseItemModel()
                if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                    //添加内容块
                    if item.itemType != nil {
                        array.append(.init(item))
                    }
                }
//                if (content.musicResponsiveListItemRenderer?.playlistItemData != nil || content.musicResponsiveListItemRenderer?.navigationEndpoint != nil) &&  (content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE") {
//                    //设置内容块的封面
//                    item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
//                    //设置一级标题与二级标题
//                    for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
//                        if index == 0 {
//                            //一级标题
//                            item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
//                        }else {
//                            //二级标题
//                            item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
//                        }
//                    }
//                    item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
//                    //设置id和类型
//                    if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
//                        //是单曲
//                        item.itemType = .single
//                        item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
//                    }else {
//                        //是专辑列表/艺术家
//                        item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
//                        let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
//                        if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
//                            //判断细分
//                            if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
//                                item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
//                                //是艺术家
//                                item.itemType = .artist
//                            }else {
//                                //是列表/专辑
//                                item.itemType = .list
//                            }
//                        }
//                    }
//                    //添加内容块
//                    if item.itemType != nil {
//                        array.append(.init(item))
//                    }
//                }
            })
        }
        var continuation:String?
        var clickTrackingParams:String?
        if let continuations = musicShelfRenderer.continuations?.first {
            ///解析继续编码
            continuation = continuations.nextContinuationData?.continuation
            clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
        }
        array = array.filter({ item in
            return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
        })
        array = array.filter({$0.item.itemType != nil})
        return (array, continuation, clickTrackingParams)
    }
    ///解析搜索分页继续
    private func parsingSearchTypeContinuation(_ musicShelfContinuation:JsonSearchTypeContinuation.ContinuationContents.MusicShelfContinuation) -> ([MPPositive_SearchResultItemViewModel], String?, String?) {
        var array:[MPPositive_SearchResultItemViewModel] = []
        if let contents = musicShelfContinuation.contents {
            ///解析内容块
            contents.forEach({ content in
                if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer, let item = parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer) {
                    //添加内容块
                    if item.itemType != nil {
                        array.append(.init(item))
                    }
                }
//                //专辑/列表/单曲视频/艺术家
//                let item = MPPositive_BrowseItemModel()
//                //设置内容块的封面
//                item.coverUrls = content.musicResponsiveListItemRenderer?.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.map({$0.url ?? ""})
//                //设置一级标题与二级标题
//                for (index, flexColumn) in (content.musicResponsiveListItemRenderer?.flexColumns ?? []).enumerated() {
//                    if index == 0 {
//                        //一级标题
//                        item.title = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
//                    }else {
//                        //二级标题
//                        item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
//                    }
//                }
//                item.playListId = content.musicResponsiveListItemRenderer?.menu?.menuRenderer?.items?.first?.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
//                //设置id和类型
//                if content.musicResponsiveListItemRenderer?.playlistItemData != nil {
//                    //是单曲
//                    item.itemType = .single
//                    item.videoId = content.musicResponsiveListItemRenderer?.playlistItemData?.videoId
//                }else {
//                    //是专辑列表/艺术家
//                    item.browseId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
//                    let pageType = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
//                    if youTubeKeys.contains(pageType ?? "") == true && pageType != "MUSIC_PAGE_TYPE_NON_MUSIC_AUDIO_TRACK_PAGE" {
//                        //判断细分
//                        if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
//                            item.artistId = content.musicResponsiveListItemRenderer?.navigationEndpoint?.browseEndpoint?.browseId
//                            //是艺术家
//                            item.itemType = .artist
//                        }else {
//                            //是列表/专辑
//                            item.itemType = .list
//                        }
//                    }
//                }
//                //添加内容块
//                if item.itemType != nil {
//                    array.append(.init(item))
//                }
            })
        }
        var continuation:String?
        var clickTrackingParams:String?
        if let continuations = musicShelfContinuation.continuations?.first {
            ///解析继续编码
            continuation = continuations.nextContinuationData?.continuation
            clickTrackingParams = continuations.nextContinuationData?.clickTrackingParams
        }
        array = array.filter({ item in
            return (trashSingerIds.contains(item.item.artistId ?? "") == false) && (trashVideoIds.contains(item.item.videoId ?? "") == false)
        })
        array = array.filter({$0.item.itemType != nil})
        return (array, continuation, clickTrackingParams)
    }
    //MARK: - 解析具体内容形式
    //解析musicResponsiveListItemRenderer（四组件内容）
    private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel? {
        //生成一个音乐模型接收数据
        let item = MPPositive_BrowseItemModel()
        //预览图片路径
        item.coverUrls = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
        if let clickTrackingParams = musicResponsiveListItemRenderer.trackingParams {
            item.clickTrackingParams = clickTrackingParams
        }
        //判断预览项性质，并继续补完数据
        if let playlistItemData = musicResponsiveListItemRenderer.playlistItemData {
            //当前预览项是视频/单曲
            item.itemType = .single
            item.videoId = playlistItemData.videoId
            //设置主副标题
            guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty == false else {
                return nil
            }
            //主标题为第一位,同时VideoId,PlayListId,pageType都以第一个flexColumn为主
            let first = flexColumns.removeFirst()
            item.title = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
            if let clickTrackingParams = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.clickTrackingParams {
                item.clickTrackingParams = clickTrackingParams
            }
            //判断watchEndpoint（资源导向）是否存在
            guard let watchEndpoint = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.watchEndpoint else {return nil}
            //watchEndpoint内容赋值给item
            item.playListId = watchEndpoint.playlistId
            item.pageType = watchEndpoint.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType
            //设置副标题，通常为作者/专辑
            flexColumns.forEach { flexColumn in
                item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
                if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint != nil}) {
                    if ari.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST", let id = ari.navigationEndpoint?.browseEndpoint?.browseId {
                        //这个文本指向作者，获取作者ID
                        item.artistId = id
                    }
                }
            }
            //继续补完videoId,检索是否具备playListId,当playListId为空时，说明并没有成功补完，需要使用菜单结构补全内容
            guard (item.playListId ?? "").isEmpty == true else {
                //判断是否禁止的作者或者禁止的音乐
                if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false {
                    return item
                }else {
                    //禁止内容
                    return nil
                }
            }
            //未补完，继续
            if let watchItem = musicResponsiveListItemRenderer.menu?.menuRenderer?.items?.first(where: {$0.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint != nil}) {
                item.playListId = watchItem.menuNavigationItemRenderer?.navigationEndpoint?.watchEndpoint?.playlistId
                //判断是否禁止的作者或者禁止的音乐
                if (trashSingerIds.contains(item.artistId ?? "")) == false && (trashVideoIds.contains(item.videoId ?? "")) == false {
                    return item
                }else {
                    //禁止内容
                    return nil
                }
            }else {
                //补完失败
                return nil
            }
        }else if let navigationEndpoint = musicResponsiveListItemRenderer.navigationEndpoint {
            //是专辑/艺术家/歌单
            //设置主副标题
            guard var flexColumns = musicResponsiveListItemRenderer.flexColumns, flexColumns.isEmpty != true else {
                return nil
            }
            //主标题为第一位,其余内容都是副标题
            let first = flexColumns.removeFirst()
            item.title = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
            if let clickTrackingParams = first.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first?.navigationEndpoint?.clickTrackingParams {
                item.clickTrackingParams = clickTrackingParams
            }
            //设置副标题，通常为作者/专辑
            flexColumns.forEach { flexColumn in
                item.subtitle = (item.subtitle ?? "") + (flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")}) ?? "")
                if let ari = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
                    //这个文本指向作者，获取作者ID
                    if let id = ari.navigationEndpoint?.browseEndpoint?.browseId {
                        item.artistId = id
                    }
                }
            }
            //设置预览Id
            guard let browseEndpoint = navigationEndpoint.browseEndpoint else {
                return nil
            }
            item.browseId = browseEndpoint.browseId
            //根据pageType确定导航至何处
            guard let pageType = browseEndpoint.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType else {return nil}
            item.pageType = pageType
            if pageType == "MUSIC_PAGE_TYPE_ALBUM" {
                //专辑
                item.itemType = .list
                return item
            }else if pageType == "MUSIC_PAGE_TYPE_PLAYLIST" {
                //列表
                item.itemType = .list
                return item
            }else if pageType == "MUSIC_PAGE_TYPE_ARTIST" {
                //艺术家
                item.itemType = .artist
                item.artistId = item.browseId
                if (trashSingerIds.contains(item.artistId ?? "")) == false {
                    return item
                }else {
                    return nil
                }
            }else {
                return nil
            }
        }else {
            return nil
        }
    }
    //解析musicResponsiveListItemRenderer（三组件结构）
    private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel? {
        //生成一个音乐模型接收数据
        let item = MPPositive_BrowseItemModel()
        //封面路径
        item.coverUrls = musicTwoRowItemRenderer.thumbnailRenderer?.musicThumbnailRenderer?.thumbnail?.thumbnails?.compactMap({$0.url})
        //标题
        item.title = musicTwoRowItemRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
        //副标题
        item.subtitle = musicTwoRowItemRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
        //获取这个预览项的作者（有的话）
        if let art = musicTwoRowItemRenderer.subtitle?.runs?.first(where: {$0.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST"}) {
            item.artistId = art.navigationEndpoint?.browseEndpoint?.browseId
        }
        if let clickTrackingParams = musicTwoRowItemRenderer.navigationEndpoint?.clickTrackingParams {
            item.clickTrackingParams = clickTrackingParams
        }
        //判断这个内容是音视频还是专辑列表艺术家
        if let watchEndpoint = musicTwoRowItemRenderer.navigationEndpoint?.watchEndpoint {
            //是音视频
            item.itemType = .single
            item.videoId = watchEndpoint.videoId
            item.playListId = watchEndpoint.playlistId
            item.pageType = watchEndpoint.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType
        }
        if let browseEndpoint = musicTwoRowItemRenderer.navigationEndpoint?.browseEndpoint {
            //是列表专辑艺术家
            if browseEndpoint.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType == "MUSIC_PAGE_TYPE_ARTIST" {
                //是艺术家
                item.itemType = .artist
                item.artistId = browseEndpoint.browseId
                item.pageType = "MUSIC_PAGE_TYPE_ARTIST"
            }else {
                //是专辑列表
                item.itemType = .list
                item.pageType = browseEndpoint.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                item.browseId = browseEndpoint.browseId
            }
        }
        if (trashSingerIds.contains(item.artistId ?? "")) == false {
            return item
        }else {
            return nil
        }
    }
}
//MARK: - 解析资源加密
extension MP_NetWorkManager {
    ///百分比解码
    private func seperatorOff(_ encodedString: String) -> String {
        guard let decodedString = encodedString.removingPercentEncoding else {
            print("百分比解码失败")
            return ""
        }
        return decodedString
    }
}
//MARK: - 自动重试
///重试策略类
class MP_CustomRetrier: RequestInterceptor {
    // 追踪重试次数的字典
    private var retryCounts: [String: Int] = [:]
    // 最大重试次数
    private let maxRetryCount: Int = 2
    // 重试间隔时间
    private let retryInterval: TimeInterval = 1.0
    //重试策略
    func retry(_ request: Request, for session: Session, dueTo error: any Error, completion: @escaping (RetryResult) -> Void) {
        // 检查请求是否具有URL以便于在字典中进行追踪
        guard let url = request.request?.url?.absoluteString else {
            completion(.doNotRetry)
            return
        }
        // 获取这个 URL 当前的重试次数
        let currentRetryCount = retryCounts[url] ?? 0
            
        // 如果未超过最大重试次数，那么决定重试
        if currentRetryCount < maxRetryCount {
            // 更新重试次数
            retryCounts[url] = currentRetryCount + 1
            print("进行对\(url)访问的第\(currentRetryCount)次重试")
            // 告诉 Alamofire 重试并包含间隔时间
            completion(.retryWithDelay(retryInterval))
        } else {
            // 如果达到最大重试次数，则不再重试
            completion(.doNotRetry)
            print("访问\(url)失败，不在进行重试")
//            // 移除追踪记录
//            retryCounts[url] = nil
        }
    }
}
