//
//  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 ListRequestResultBlock = (_ list:MPPositive_ListAlbumListViewModel) -> Void
///网络状况管理器
class MP_NetWorkManager: NSObject {
    //单例工具
    static let shared = MP_NetWorkManager()
    //MARK: - API接口
    ///域名链接
    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"
    //MARK: - 固定参数
    //访问数据（首次首页预览时获得）
    private var visitorData:String?

    //预览下一阶段参数（网络请求获取）
    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 {
                //移除异步线程
                browseQueque = nil
                return
            }
            //生成新参数
            let parameters:[String:Any] = [
                "ctoken":continuation,
                "continuation":continuation,
                "type":"next",
                "itct":itct,
                "prettyPrint":"false",
                "context":[
                    "client":[
                        //web端
                        "clientName": "WEB_REMIX",
                        "visitorData":visitorData,
                        //当前访问版本（日期值）
                        "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                        "platform":"DESKTOP",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":Location_First
                    ]
                ]
            ]
            //执行异步请求
            browseQueque?.async {
                [weak self] in
                guard let self = self else { return }
                requestPostHomeBrowse(url, parameters: parameters)
            }
        }
    }
    //MARK: - 异步队列
    //串行队列-预览
    private var browseQueque:DispatchQueue?
    //MARK: - 闭包
    ///预览闭包（传递一个预览模块数据和完成状态）
    var browseRequestStateBlock:BrowseRequestStateBlock?
    ///列表专辑闭包（传递一个请求完成的列表数据）
    var listRequestResultBlock:ListRequestResultBlock?
    //私有初始化
    private override init() {
        super.init()
    }
    
    //MARK: - 网络情况
    ///检查网络状况
    func requestNetworkPermission(oberve:UIViewController, completeHanlder:ActionBlock?) {
        let monitor = NWPathMonitor()
        monitor.pathUpdateHandler = { path in
            switch path.status {
            case .satisfied:
                DispatchQueue.main.async {
                    guard completeHanlder != nil else {
                        return
                    }
                    completeHanlder!()
                }
            default://网络权限出现问题
                DispatchQueue.main.async {
                    //次要处理
                    let alertController = UIAlertController(title: "Access network request", message: "”Musicoo“ 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)
                }
            }
        }
        let queue = DispatchQueue(label: "MPNetWorkManager")
        monitor.start(queue: queue)
    }
}
//MARK: - API请求
extension MP_NetWorkManager {
    //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?.async {
            [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",
                        //当前访问版本（日期值）
                        "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                        "platform":"DESKTOP",
                        //语言
                        "hl":Language_first_local,
                        //地址
                        "gl":Location_First
                    ]
                ]
            ]
            requestPostHomeBrowse(url, parameters: parameters)
        }
        
    }
    //请求首页预览内容（执行多次）
    private func requestPostHomeBrowse(_ url:URL, parameters:Parameters) {
        //发送post请求，并将结果转为RootBrowses
        AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonBrowses.self) { [weak self] (response) in
            guard let self = self else {return}
            if let task = response.request {
                print("URL: \(task.url!)")
            }
            switch response.result {
            case .success(let value):
                if value.responseContext?.visitorData != nil {
                    self.visitorData = value.responseContext?.visitorData
                }
                //解析结构体
                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")
                }
            case .failure(let error):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
    //MARK: - 请求列表专辑预览
    /// 向YouTubemusic请求列表/专辑数据，该接口调用的同样是browse预览接口
    /// - Parameters:
    ///   - item: 需要查看的模块
    func requestAlbumOrListDatas(_ item: MPPositive_BrowseItemViewModel) {
        //拼接出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":(item.browseItem.browseContent.browseId ?? ""),
            "params":(item.browseItem.browseContent.params ?? ""),
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        requestPostAlbumOrList(url, parameters: parameters)
    }
    //请求列表/专辑数据
    private func requestPostAlbumOrList(_ url:URL, parameters:Parameters) {
        //发送post请求，并将结果转为RootBrowses
        AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonListOrAlbum.self) { [weak self] (response) in
            guard let self = self else {return}
            if let task = response.request {
                print("URL: \(task.url!)")
            }
            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 = parsingListContents(content)
                }
                if let header = value.header {
                    list.header = .init(parsingListHeaders(header))
                }
                //传递列表值
                guard listRequestResultBlock != nil else {
                    return
                }
                listRequestResultBlock!(list)
            case .failure(let error):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
    
    //MARK: - 请求列表专辑下一部分
    ///请求Next列表（优先于Player）
    /// - Parameter item: 请求的预览实体
    func requestNextList(_ item: MPPositive_BrowseItemViewModel, 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":(item.browseItem.musicVideo.playListId ?? ""),
            "videoId":(item.browseItem.musicVideo.videoId ?? ""),
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        //发送next列表请求
        requestPostNextList(url, parameters: parameters) { listSongs in
            //成功拿到列表所有歌曲（内容尚不完善）
            completion(listSongs)
        }
    }
    //请求next列表
    private func requestPostNextList(_ url:URL, parameters:Parameters, completion:@escaping (([MPPositive_SongItemModel]) -> Void)) {
        //发送post请求
        AF.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):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
    ///请求Next歌词/相关内容
    /// - Parameter item: 请求的预览实体
    func requestNextLyricsAndRelated(_ item: MPPositive_SongItemModel, completion:@escaping(((String?,String?)) -> 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] = [
            "videoId":(item.videoId ?? ""),
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        //发送next列表歌词/相关内容请求
        requestPostNextLyricsAndRelated(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求请求Next歌词/相关内容
    private func requestPostNextLyricsAndRelated(_ url:URL, parameters:Parameters, completion:@escaping(((String?,String?)) -> Void)) {
        //发送post请求
        AF.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):
                let result = parsingNextLyricsAndRelated(value)
                //回掉数据
                completion(result)
            case .failure(let error):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
    
    //MARK: - 请求player播放资源
    /// 请求Player(单曲/视频)播放资源
    /// - Parameter item: 请求的预览实体
    func requestPlayer(_ item: MPPositive_SongItemModel, completion:@escaping (([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] = [
//            "playlistId":(item.browseItem.musicVideo.playListId ?? ""),
            "videoId":(item.videoId ?? ""),
            "prettyPrint":"false",
            "context":[
                "client":[
                    //当前访问版本（日期值）
                    "clientName": "WEB_REMIX",
                    "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00"
                ]
            ],
            "playbackContext": [
                "contentPlaybackContext": [
                    "signatureTimestamp": MP_WebWork.shared.signatureTimestamp ?? 0
                ]
            ]
        ]
        requestPostPlayer(url, parameters: parameters){ resourceUlrs, coverUrls in
            completion(resourceUlrs, coverUrls)
        }
    }
    //请求单曲/视频
    private func requestPostPlayer(_ url:URL, parameters:Parameters, completion:@escaping(([String]?, [String]?) -> Void)) {
        //发送post请求
        AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonPlayer.self) { [weak self] (response) in
            guard let self = self else {return}
            if let task = response.request {
                print("URL: \(task.url!)")
            }
            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": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        requestPostLyric(url, parameters: parameters) { lyrics in
            completion(lyrics)
        }
    }
    //请求歌词
    private func requestPostLyric(_ url:URL, parameters:Parameters, completion:@escaping((String) -> Void)) {
        //发送post请求
        AF.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):
                // 请求失败，处理错误
                print("Request failed: \(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": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        requestPostSearchSuggestions(url, parameters: parameters) { result in
            completion(result)
        }
    }
    //请求搜索建议
    private func requestPostSearchSuggestions(_ url:URL, parameters:Parameters, completion:@escaping(([[MPPositive_SearchSuggestionItemModel]]) -> Void)) {
        //发送post请求
        AF.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):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
    
    /// 请求搜索结果
    /// - Parameter text: 用户请求文本
    func requestSearchResults(_ text:String) {
        //拼接路径
        let path = header+point+search
        //设置url
        guard let url = URL(string: path) else {
            print("Url is Incorrect")
            return
        }
        //设置参数
        let parameters:[String:Any] = [
            "query":text,
            "prettyPrint":"false",
            "context":[
                "client":[
                    //web端
                    "clientName": "WEB_REMIX",
                    "visitorData":visitorData,
                    //当前访问版本（日期值）
                    "clientVersion": "1.\(Date().timeZone().toString(.custom("YYYYMMdd"))).01.00",
                    "platform":"DESKTOP",
                    //语言
                    "hl":Language_first_local,
                    //地址
                    "gl":Location_First
                ]
            ]
        ]
        //
    }
    //请求搜索结果
    private func requestPostSearchResults(_ url:URL, parameters:Parameters) {
        //发送post请求
        AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default).responseDecodable(of: JsonSearchResults.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 {
                    parsingSearchResults(contents)
                }
            case .failure(let error):
                // 请求失败，处理错误
                print("Request failed: \(error)")
            }
        }
    }
}
//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 {
                    browse.items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
                }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                    browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
                }
            })
            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, (continuation == nil))
        //重新赋值，直到没有下一阶段数据为止
        self.continuationAndItct = (continuation,itct)
    }
    ///解析预览内容_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 {
                    browse.items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
                }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                    browse.items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
                }
            })
            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, (continuation == nil))
        //重新赋值，直到没有下一阶段数据为止
        self.continuationAndItct = (continuation,itct)
    }
    ///解析列表_Contents
    private func parsingListContents(_ 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 {
                        items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                        items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
                    }
                })
            }else if let musicShelfRenderer = content.musicShelfRenderer{
                musicShelfRenderer.contents?.forEach({ content in
                    //设置标题、歌手、专辑/列表
                    if let musicResponsiveListItemRenderer = content.musicResponsiveListItemRenderer {
                        items.append(.init(parsingMusicResponsiveListItemRenderer(musicResponsiveListItemRenderer)))
                    }else if let musicTwoRowItemRenderer = content.musicTwoRowItemRenderer {
                        items.append(.init(parsingMusicTwoRowItemRenderer(musicTwoRowItemRenderer)))
                    }
                })
            }
        })
        return items
    }
    ///解析列表_Header
    private func parsingListHeaders(_ 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
    }
    ///解析相关内容_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
                        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)
        }
    }
    
    /// 解析播放器_Player
    /// - Parameters:
    ///   - player: player库
    ///   - completion: 传递两个字符串数组，第一个资源路径组，第二个是封面路径组
    private func parsingPlayer(_ player:JsonPlayer, completion:@escaping(([String]?, [String]?) -> Void)){
        var infos:[String]?
        //解析player，获取资源库和信息库
        if let videoDetails = player.videoDetails {
            infos = parsingPlayerVideoDetails(videoDetails)
        }
        if let streamingData = player.streamingData {
            parsingPlayerStreamingData(streamingData){ urls in
                completion(urls,infos)
            }
        }
    }
    
    /// 解析播放器_StreamingData
    /// - Parameter streamingData: 资源库
    private func parsingPlayerStreamingData(_ streamingData:JsonPlayer.StreamingData, completion:@escaping(([String]) -> Void)) {
        var group:DispatchGroup? = DispatchGroup()
        var array:[String] = []
        let allFormats = (streamingData.formats ?? []) + (streamingData.adaptiveFormats ?? [])
        for format in allFormats {
            if let signatureCipher = format.signatureCipher {
                // 进入DispatchGroup，表示开始一个异步任务
                group?.enter()
                //获得资源签名，开始解密签名内容
                parsingPlayerSignatureCipher(signatureCipher) { result in
                    array.append(result)
                    // 离开DispatchGroup，表示异步任务完成
                    group?.leave()
                }
            }
        }
        group?.notify(queue: .main) {
            completion(array)
            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
//            print("Resources-SignatureDecryption:\(abString)")
            completion(abString)
        }
    }
    /// 解析播放器_VideoDetails
    /// - Parameter videoDetails: 信息库
    /// - Returns: 返回一个元组，值分别为 videoId，title，author，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 ""
    }
    
    /// 解析搜索建议_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)
        }
    }
    ///解析搜索结果_SearchResults
    private func parsingSearchResults(_ contents:[JsonSearchResults.Contents.TabbedSearchResultsRenderer.Tab.TabRenderer.Content.SectionListRenderer.Content]) {
        contents.forEach { content in
            let resultList = MPPositive_SearchResultListViewModel()
            //判断当前模块是最佳结果还是其它模块
            if let musicCardShelfRenderer = content.musicCardShelfRenderer {
                //当前是最佳结果
                if let title = musicCardShelfRenderer.title {
                    //设置模块标题
                    resultList.title = title.runs?.reduce("", { $0 + ($1.text ?? "")})
                }
            }else {
                //当前是其他结果
            }
        }
    }
    
    //MARK: - 解析具体内容形式
    //解析musicResponsiveListItemRenderer（单曲/视频）
    private func parsingMusicResponsiveListItemRenderer(_ musicResponsiveListItemRenderer: RootMusicResponsiveListItemRenderer) -> MPPositive_BrowseItemModel {
        //生成一个音乐模型接收数据
        let item = MPPositive_BrowseItemModel()
        item.itemType = .single
        //封面路径
        item.coverUrl = musicResponsiveListItemRenderer.thumbnail?.musicThumbnailRenderer?.thumbnail?.thumbnails?.last?.url
        if let flexColumns = musicResponsiveListItemRenderer.flexColumns {
            for (index,flexColumn) in flexColumns.enumerated() {
                if index == 0 {
                    item.maintitle = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
                }else if index == 1 {
                    item.subtitle = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
                }else {
                    item.thirdtitle = flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.reduce("", { $0 + ($1.text ?? "")})
                }
                var browseContent = BrowseItemContent()
                flexColumn.musicResponsiveListItemFlexColumnRenderer?.text?.runs?.forEach({ run in
//                    if run.navigationEndpoint?.browseEndpoint?.browseId != nil {
//                        //获取到艺术家的ID
//                        item.artistsId = run.navigationEndpoint?.browseEndpoint?.browseId
//                    }
                    if run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != nil && run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_ARTIST" {
                        //专辑或则歌单
                        browseContent.pageType = run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                        browseContent.browseId = run.navigationEndpoint?.browseEndpoint?.browseId
                        browseContent.params = run.navigationEndpoint?.browseEndpoint?.params
                    }
                })
                item.browseContent = browseContent
            }
        }
        //设置音乐id和列表id
        if let watch  = musicResponsiveListItemRenderer.overlay?.musicItemThumbnailOverlayRenderer?.content?.musicPlayButtonRenderer?.playNavigationEndpoint?.watchEndpoint {
            var musicVideo = BrowseItemMusicVideo()
            musicVideo.videoId = watch.videoId
            musicVideo.playListId = watch.playlistId
            musicVideo.musicVideoType = watch.watchEndpointMusicSupportedConfigs?.watchEndpointMusicConfig?.musicVideoType
            item.musicVideo = musicVideo
        }
        return item
    }
    //解析musicResponsiveListItemRenderer（list）
    private func parsingMusicTwoRowItemRenderer(_ musicTwoRowItemRenderer: RootMusicTwoRowItemRenderer) -> MPPositive_BrowseItemModel {
        //生成一个音乐模型接收数据
        let item = MPPositive_BrowseItemModel()
        item.itemType = .list
        //封面路径
        item.coverUrl = musicTwoRowItemRenderer.thumbnailRenderer?.musicThumbnailRenderer?.thumbnail?.thumbnails?.last?.url
        //标题
        item.maintitle = musicTwoRowItemRenderer.title?.runs?.reduce("", { $0 + ($1.text ?? "")})
        //副标题
        item.subtitle = musicTwoRowItemRenderer.subtitle?.runs?.reduce("", { $0 + ($1.text ?? "")})
        var browseContent = BrowseItemContent()
        musicTwoRowItemRenderer.title?.runs?.forEach({ run in
//            if run.navigationEndpoint?.browseEndpoint?.browseId != nil {
//                //获取到艺术家的ID
//                item.artistsId = run.navigationEndpoint?.browseEndpoint?.browseId
//            }
            if run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != nil && run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_ARTIST" {
                //专辑或则歌单
                browseContent.pageType = run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                browseContent.browseId = run.navigationEndpoint?.browseEndpoint?.browseId
                browseContent.params = run.navigationEndpoint?.browseEndpoint?.params
            }
        })
        musicTwoRowItemRenderer.subtitle?.runs?.forEach({ run in
//            if run.navigationEndpoint?.browseEndpoint?.browseId != nil {
//                //获取到艺术家的ID
//                item.artistsId = run.navigationEndpoint?.browseEndpoint?.browseId
//            }
            if run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != nil && run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType != "MUSIC_PAGE_TYPE_ARTIST" {
                //专辑或则歌单
                browseContent.pageType = run.navigationEndpoint?.browseEndpoint?.browseEndpointContextSupportedConfigs?.browseEndpointContextMusicConfig?.pageType
                browseContent.browseId = run.navigationEndpoint?.browseEndpoint?.browseId
                browseContent.params = run.navigationEndpoint?.browseEndpoint?.params
            }
        })
        item.browseContent = browseContent
        if let playListId = musicTwoRowItemRenderer.thumbnailOverlay?.musicItemThumbnailOverlayRenderer?.content?.musicPlayButtonRenderer?.playNavigationEndpoint?.watchPlaylistEndpoint?.playlistId  {
            //设置列表ID
            var musicVideo = BrowseItemMusicVideo()
            musicVideo.playListId = playListId
            item.musicVideo = musicVideo
        }
        if let videoId = musicTwoRowItemRenderer.navigationEndpoint?.watchEndpoint?.videoId {
            //是视频
            var musicVideo = BrowseItemMusicVideo()
            musicVideo.videoId = videoId
            item.musicVideo = musicVideo
            item.itemType = .single
        }
        return item
    }
}
//MARK: - 解析资源加密
extension MP_NetWorkManager {
    ///百分比解码
    private func seperatorOff(_ encodedString: String) -> String {
        guard let decodedString = encodedString.removingPercentEncoding else {
            print("百分比解码失败")
            return ""
        }
        return decodedString
    }
}
