//
//  PQUploadViewController.swift
//  PQSpeed
//
//  Created by SanW on 2020/8/1.
//  Copyright © 2020 BytesFlow. All rights reserved.
//

import MobileCoreServices
import Photos
import UIKit
import BFCommonKit

let playerHeaderH: CGFloat = cScreenWidth * (250 / 375)

class PQUploadController: PQBaseViewController {
    // 最大的宽度
    var maxWidth: CGFloat = cScreenWidth
    // 最大的高度
    var maxHeight: CGFloat = adapterWidth(width: 300)
    // 画面比例
    var aspectRatio: aspectRatio?
    var preViewSize: CGSize {
        if aspectRatio == nil, (isMember(of: PQUploadController.self) && selectedData == nil) || (!isMember(of: PQUploadController.self) && uploadData == nil) {
            return CGSize(width: maxHeight, height: maxHeight)
        }
        if selectedData != nil {
            aspectRatio = .origin(width: CGFloat(videoData[lastSeletedIndex?.item ?? 0].videoWidth), height: CGFloat(videoData[lastSeletedIndex?.item ?? 0].videoHeight))
        } else if aspectRatio == nil {
            aspectRatio = .origin(width: CGFloat(uploadData?.videoWidth ?? maxHeight), height: CGFloat(uploadData?.videoHeight ?? maxHeight))
        }
        switch aspectRatio {
        case let .origin(width, height):
            var tempHeight: CGFloat = 0
            var tempWidth: CGFloat = 0
            if width > height {
                tempHeight = (maxWidth * height / width)
                tempWidth = maxWidth
            } else {
                tempHeight = maxHeight
                tempWidth = (maxHeight * width / height)
            }
            if tempHeight.isNaN || tempWidth.isNaN {
                return CGSize.zero
            } else {
                return CGSize(width: tempWidth, height: tempHeight)
            }
        case .oneToOne:
            if maxWidth > maxHeight {
                return CGSize(width: maxHeight, height: maxHeight)
            } else {
                return CGSize(width: maxWidth, height: maxWidth)
            }
        case .sixteenToNine:
            return CGSize(width: maxWidth, height: maxWidth * 9.0 / 16.0)
        case .nineToSixteen:
            return CGSize(width: maxHeight * 9.0 / 16.0, height: maxHeight)
        default:
            break
        }
        return CGSize(width: maxHeight, height: maxHeight)
    }

    // 上传入口类型
    var sourceType: videoUploadSourceType = .videoUpload
    // 制作视频项目Id
    var makeVideoProjectId: String?
    // 再创作数据
    var reCreateData: PQReCreateModel?
    // 视频创作埋点数据
    var eventTrackData: PQVideoMakeEventTrackModel?
    // 制作视频草稿Id
    var makeVideoDraftboxId: String?
    // 制作视频草稿结构化数据
    var makeVideoSdata: String?
    var isAssetImage: Bool = false // 是否请求的是图片
    var videoWidth: CGFloat = 0 // 视频宽
    var videoHeight: CGFloat = 0 // 视频高
    var isLoop: Bool = true // 是否循环播放
    var playerItem: AVPlayerItem? // 当前播放item
    var videoOutput: AVPlayerItemVideoOutput?
    let itemSize = CGSize(width: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale, height: ((cScreenWidth - cDefaultMargin) / 3) * UIScreen.main.scale)
    var categoryH: CGFloat = cDefaultMargin * 40 // 相簿高度

    var videoData: [PQUploadModel] = Array<PQUploadModel>.init()

    var categoryData: [PQUploadModel] = Array<PQUploadModel>.init()

    // 当前选中的数据
    var selectedData: PQUploadModel?
    // 确定上传的数据
    var uploadData: PQUploadModel?
    var catagerySelectedIndex: IndexPath = IndexPath(item: 0, section: 0) // 更多图库选择

    var isJumpToAuthorization: Bool = false // 是否跳到授权
    var lastSeletedIndex: IndexPath? // 上次选中的index
    lazy var imageManager: PHCachingImageManager = {
        (PHCachingImageManager.default() as? PHCachingImageManager) ?? PHCachingImageManager()
    }()

    var allPhotos: PHFetchResult<PHAsset>!
    var previousPreheatRect = CGRect.zero

    var smartAlbums: PHFetchResult<PHAssetCollection>!
    var userCollections: PHFetchResult<PHCollection>!
    let sectionLocalizedTitles = ["", NSLocalizedString("Smart Albums", comment: ""), NSLocalizedString("Albums", comment: "")]
    lazy var fetchOptions: PHFetchOptions = {
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        fetchOptions.predicate = NSPredicate(format: "mediaType = %d", !isAssetImage ? PHAssetMediaType.video.rawValue : PHAssetMediaType.image.rawValue)
        return fetchOptions
    }()

    lazy var imagesOptions: PHImageRequestOptions = {
        let imagesOptions = PHImageRequestOptions()
        imagesOptions.isSynchronous = true
        imagesOptions.isNetworkAccessAllowed = false
        imagesOptions.deliveryMode = .opportunistic
        imagesOptions.resizeMode = .fast
        imagesOptions.progressHandler = { _, _, _, info in
            BFLog(message: "progressHandler = \(info)")
        }
        return imagesOptions
    }()

    lazy var singleImageOptions: PHImageRequestOptions = {
        let singleImageOptions = PHImageRequestOptions()
        singleImageOptions.isSynchronous = true
        singleImageOptions.isNetworkAccessAllowed = false
        singleImageOptions.deliveryMode = .highQualityFormat
        return singleImageOptions
    }()

    lazy var backBtn: UIButton = {
        let backBtn = UIButton(type: .custom)
        backBtn.frame = CGRect(x: 0, y: cDevice_iPhoneStatusBarHei, width: cDefaultMargin * 4, height: cDefaultMargin * 4)
        backBtn.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: -5, right: 0)
       
        backBtn.setImage(UIImage.moduleImage(named: "icon_blanc_back", moduleName: "BFFramework",isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .normal)
        backBtn.addTarget(self, action: #selector(backBtnClick), for: .touchUpInside)
        backBtn.imageView?.tintColor = PQBFConfig.shared.styleTitleColor
        return backBtn
    }()

    var anthorEmptyData: PQEmptyModel? = {
        let anthorEmptyData = PQEmptyModel()
        anthorEmptyData.title = "开始上传"
        anthorEmptyData.summary = "要开始上传视频，请先授予相册使用权限"
        anthorEmptyData.emptyImageName = "icon_authorError"
        return anthorEmptyData
    }()

    var emptyData: PQEmptyModel? = {
        let emptyData = PQEmptyModel()
        emptyData.title = "哦呜~ 你没有可上传的视频~"
        emptyData.emptyImageName = "video_empty"
        emptyData.netDisRefreshBgColor = UIColor.hexColor(hexadecimal: "#FA6400")
        emptyData.netDisTitle = "内容加载失败"
        emptyData.netDisTitleColor = UIColor.hexColor(hexadecimal: "#333333")
        emptyData.netemptyDisImage = UIImage.init(named: "empty_netDis_icon")
        emptyData.netDisRefreshTitle = NSMutableAttributedString(string: "重新加载", attributes: [.font: UIFont.systemFont(ofSize: 16, weight: .medium), .foregroundColor: UIColor.white])
        return emptyData
    }()

    lazy var emptyRemindView: PQEmptyRemindView = {
        let remindView = PQEmptyRemindView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei))
        remindView.isHidden = true
        remindView.emptyData = anthorEmptyData
        view.addSubview(remindView)
        remindView.fullRefreshBloc = { [weak self] _, _ in
            self?.isJumpToAuthorization = true
            if self?.emptyRemindView.refreshBtn.currentTitle == "授予权限" {
                openAppSetting()
            }
        }
        return remindView
    }()

    lazy var collectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets.zero
        let collectionView = UICollectionView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei), collectionViewLayout: layout)
        collectionView.showsVerticalScrollIndicator = false
        collectionView.register(PQSelecteVideoItemCell.self, forCellWithReuseIdentifier: "PQSelecteVideoItemCell")
        collectionView.delegate = self
        collectionView.dataSource = self
        if #available(iOS 11.0, *) {
            collectionView.contentInsetAdjustmentBehavior = .never
        } else {
            automaticallyAdjustsScrollViewInsets = false
        }
        collectionView.backgroundColor = .clear
        return collectionView
    }()

    lazy var categoryCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsets.zero
        let categoryCollectionView = UICollectionView(frame: CGRect(x: 0, y: -categoryH, width: cScreenWidth, height: categoryH), collectionViewLayout: layout)
        categoryCollectionView.showsVerticalScrollIndicator = false
        categoryCollectionView.register(PQAssetCategoryCell.self, forCellWithReuseIdentifier: "PQAssetCategoryCell")
        categoryCollectionView.delegate = self
        categoryCollectionView.dataSource = self
        if #available(iOS 11.0, *) {
            categoryCollectionView.contentInsetAdjustmentBehavior = .never
        } else {
            automaticallyAdjustsScrollViewInsets = false
        }
        categoryCollectionView.backgroundColor = PQBFConfig.shared.editCoverimageSelectedbackgroundColor
        return categoryCollectionView
    }()

    lazy var categoryView: UIView = {
        let categoryView = UIView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei))
        categoryView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
        let bgView = UIView(frame: CGRect(x: 0, y: categoryH, width: categoryView.frame.width, height: categoryView.frame.height - categoryH))
        let ges = UITapGestureRecognizer(target: self, action: #selector(cancelClick))
        bgView.addGestureRecognizer(ges)
        categoryView.addSubview(bgView)
        categoryView.isHidden = true
        return categoryView
    }()

 

    lazy var playBtn: UIButton = {
        let playBtn = UIButton(type: .custom)
        playBtn.frame = CGRect(x: (preViewSize.width - cDefaultMargin * 5) / 2, y: (preViewSize.height - cDefaultMargin * 5) / 2, width: cDefaultMargin * 5, height: cDefaultMargin * 5)
        playBtn.setImage(UIImage(named: "icon_video_play_big"), for: .normal)
        playBtn.tag = 4
        playBtn.isHidden = true
        playBtn.isUserInteractionEnabled = false
        // playBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
        return playBtn
    }()

    var playerHeaderView: UIImageView = {
        let playerHeaderView = UIImageView(frame: CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: 0))
        playerHeaderView.isUserInteractionEnabled = true
        playerHeaderView.contentMode = .scaleAspectFit
        playerHeaderView.clipsToBounds = true
        playerHeaderView.backgroundColor = UIColor.yellow
        return playerHeaderView
    }()

    lazy var selecteBtn: UIButton = {
        let selecteBtn = UIButton(frame: CGRect(x: deleteBtn.frame.maxX + cDefaultMargin, y: 0, width: cScreenWidth - nextBtn.frame.width - deleteBtn.frame.maxX - cDefaultMargin * 5, height: cDevice_iPhoneTabBarHei))
        selecteBtn.titleLabel?.lineBreakMode = .byTruncatingTail
        selecteBtn.setTitle("全部", for: .normal)
         
        selecteBtn.setImage(UIImage.moduleImage(named: "icon_uploadVideo_more", moduleName: "BFFramework",isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .normal)
        selecteBtn.setTitleColor( PQBFConfig.shared.styleTitleColor, for: .normal)
        selecteBtn.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        selecteBtn.tag = 2
        selecteBtn.imagePosition(at: PQButtonImageEdgeInsetsStyle.right, space: cDefaultMargin / 2)
        selecteBtn.imageView?.tintColor = PQBFConfig.shared.styleTitleColor
        selecteBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
        return selecteBtn
    }()

    lazy var deleteBtn: UIButton = {
        let deleteBtn = UIButton(frame: CGRect(x: cDefaultMargin, y: 0, width: cDefaultMargin * 4, height: cDevice_iPhoneTabBarHei))
        deleteBtn.setImage(UIImage.moduleImage(named: "icon_blanc_back", moduleName: "BFFramework",isAssets: false)?.withRenderingMode(.alwaysTemplate), for: .normal)
        deleteBtn.tag = 1
        deleteBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
        deleteBtn.imageView?.tintColor = PQBFConfig.shared.styleTitleColor
        return deleteBtn
    }()

    lazy var nextBtn: UIButton = {
        let nextBtn = UIButton(frame: CGRect(x: 0, y: (cDevice_iPhoneTabBarHei - cDefaultMargin * 3) / 2, width: cDefaultMargin * 6, height: cDefaultMargin * 3))
        nextBtn.addCorner(corner: 3)
        nextBtn.setTitle("下一步", for: .normal)
        nextBtn.titleLabel?.font = UIFont.systemFont(ofSize: 13, weight: .medium)
        nextBtn.tag = 3
        nextBtn.addTarget(self, action: #selector(btnClick(sender:)), for: .touchUpInside)
        nextBtn.backgroundColor = UIColor.hexColor(hexadecimal: PQBFConfig.shared.styleColor.rawValue)
        nextBtn.setTitleColor(.white, for: .normal)
        return nextBtn
    }()

    lazy var bottomView: UIView = {
        let bottomView = UIView(frame: CGRect(x: 0, y: cDefaultMargin * 2, width: cScreenWidth, height: cDevice_iPhoneNavBarHei))
        bottomView.addSubview(selecteBtn)
        bottomView.backgroundColor = PQBFConfig.shared.styleBackGroundColor
        selecteBtn.center.y = nextBtn.center.y
        bottomView.addSubview(deleteBtn)
        bottomView.addSubview(nextBtn)
        nextBtn.frame.origin.x = bottomView.frame.width - nextBtn.frame.width - cDefaultMargin * 2
        return bottomView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
     
        view.backgroundColor =  PQBFConfig.shared.editCoverimageSelectedbackgroundColor
        navHeadImageView?.backgroundColor =  PQBFConfig.shared.editCoverimageSelectedbackgroundColor
        lineView?.backgroundColor =  PQBFConfig.shared.editCoverimageSelectedbackgroundColor
        addSubViews()
        bottomView.backgroundColor = PQBFConfig.shared.editCoverimageSelectedbackgroundColor
        loadLocalData()
 
    }

    deinit {
        //        PHPhotoLibrary.shared().unregisterChangeObserver(self)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
  
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
   
        addPlayerItemObserver()
    }
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        removePlayerItemObserver()
    }
    func addSubViews() {
        view.addSubview(collectionView)
        navHeadImageView?.addSubview(bottomView)
    
        PQNotification.addObserver(self, selector: #selector(didBecomeActiveNotification), name: UIApplication.didBecomeActiveNotification, object: nil)
    }

    func loadLocalData() {
        let authStatus = PHPhotoLibrary.authorizationStatus()
        if authStatus == .notDetermined {
            // 第一次触发授权 alert
            PHPhotoLibrary.requestAuthorization { [weak self] (status: PHAuthorizationStatus) -> Void in
                if status == .authorized {
                    if (self?.allPhotos == nil) || (self?.allPhotos.count ?? 0) <= 0 {
                        self?.loadPhotoData()
                    }
                    if self?.backBtn != nil {
                        self?.backBtn.removeFromSuperview()
                    }
                } else {
                    DispatchQueue.main.async { [weak self] in
                        self?.emptyRemindView.isHidden = false
                        self?.emptyRemindView.refreshBtn.isHidden = false
                        self?.emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
                        if self?.backBtn.superview == nil {
                            self?.view.addSubview((self?.backBtn)!)
                        } else {
                            self?.backBtn.isHidden = false
                        }
                    }
                }
            }
        } else if authStatus == .authorized {
            if allPhotos == nil || allPhotos.count <= 0 {
                loadPhotoData()
            }
            if backBtn.superview != nil {
                backBtn.removeFromSuperview()
            }

        } else {
            emptyRemindView.isHidden = false
            emptyRemindView.refreshBtn.isHidden = false
            emptyRemindView.refreshBtn.setTitle("授予权限", for: .normal)
            if backBtn.superview == nil {
                view.addSubview(backBtn)
            } else {
                backBtn.isHidden = false
            }
        }
    }

    func loadPhotoData() {
        DispatchQueue.main.async { [weak self] in
            PQLoadingHUB.shared.showHUB(superView: self!.view, isVerticality: false)
        }
        DispatchQueue.global().async { [weak self] in
            self?.allPhotos = PHAsset.fetchAssets(with: self?.fetchOptions)
            DispatchQueue.main.async { [weak self] in
                if self?.view != nil {
                    PQLoadingHUB.shared.dismissHUB(superView: self!.view)
                }
                self?.collectionView.reloadData()
                if (self?.allPhotos.count ?? 0) <= 0 {
                    self?.emptyRemindView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - cDevice_iPhoneTabBarHei)
                    self?.emptyRemindView.emptyData = self?.emptyData
                    self?.emptyRemindView.isHidden = false
                } else {
                    self?.emptyRemindView.isHidden = true
                }
                if (self?.allPhotos.count ?? 0) > 0 {
                    let tempData = PQUploadModel()
                    tempData.title = "全部"
                    tempData.categoryList = self!.allPhotos
                    self?.categoryData.insert(tempData, at: 0)
                }
                self?.updateCachedAssets()
            }
        }
        PHPhotoLibrary.shared().register(self)

        DispatchQueue.global().async { [weak self] in
            self?.smartAlbums = PHAssetCollection.fetchAssetCollections(with: .smartAlbum, subtype: .albumRegular, options: nil)
            self?.smartAlbums?.enumerateObjects { [weak self] assCollection, _, _ in
                if assCollection.localizedTitle != "最近删除" {
                    self?.convertCollection(collection: assCollection)
                }
            }
            self?.userCollections = PHCollectionList.fetchTopLevelUserCollections(with: nil)
            self?.userCollections.enumerateObjects { assCollection, index, point in
                BFLog(message: "userCollections == \(assCollection),index = \(index),point = \(point)")
                if assCollection is PHAssetCollection {
                    if assCollection.localizedTitle != "最近删除" {
                        self?.convertCollection(collection: assCollection as? PHAssetCollection)
                    }
                }
            }
        }
  
    }

    // 转化处理获取到的相簿
    func convertCollection(collection: PHAssetCollection?) {
        if collection == nil {
            return
        }
        DispatchQueue.global().async { [weak self] in
            let assetsFetchResult = PHAsset.fetchAssets(in: collection!, options: self?.fetchOptions)
            if assetsFetchResult.count > 0 {
                let tempData = PQUploadModel()
                tempData.title = collection?.localizedTitle
                tempData.categoryList = assetsFetchResult
                if tempData.categoryList.count > 0 {
                    self?.categoryData.append(tempData)
                }
                BFLog(message: "assetsFetchResult = \(assetsFetchResult)")
            }
        }
    }

    @objc func btnClick(sender: UIButton) {
        switch sender.tag {
        case 1: // 返回
            navigationController?.popViewController(animated: true)
        
        case 2: // 筛选
            showCollects()
        case 3: // 下一步
            if selectedData == nil {
                cShowHUB(superView: nil, msg: isAssetImage ? "请选择图片" : "请选择视频")
                return
            }
 
            imageManager.requestImage(for: (selectedData?.asset)!, targetSize: itemSize, contentMode: .aspectFill, options: nil) { [weak self] image, _ in
                self?.selectedData?.image = image
                let vc = PQImageCropVC(image: (self?.selectedData?.image)!, aspectWidth: self?.videoWidth ?? 0.0, aspectHeight: self?.videoHeight ?? 0.0)
                vc.uploadData = self?.selectedData
                self?.navigationController?.pushViewController(vc, animated: true)
            }
        default:
            break
        }
    }

    @objc func showCollects() {
        if categoryData.count <= 0 {
            return
        }
        categoryCollectionView.reloadData()
        if categoryView.superview == nil {
            view.insertSubview(categoryView, belowSubview: navHeadImageView!)
            categoryView.addSubview(categoryCollectionView)
            showCategoryView()
            return
        }
        if categoryView.isHidden {
            showCategoryView()
        } else {
            cancelClick()
        }
    }

    @objc func showCategoryView() {
        categoryView.isHidden = false
        categoryView.alpha = 0
        view.bringSubviewToFront(categoryView)
        view.bringSubviewToFront(bottomView)
        UIView.animate(withDuration: 0.3, animations: {
            self.categoryCollectionView.frame = CGRect(x: 0, y: 0, width: cScreenWidth, height: self.categoryH)
            self.categoryView.alpha = 1
        }) { _ in
        }
    }

    @objc func cancelClick() {
        UIView.animate(withDuration: 0.3, animations: {
            self.categoryCollectionView.frame = CGRect(x: 0, y: -self.categoryH, width: cScreenWidth, height: self.categoryH)
            self.categoryView.alpha = 0
        }) { _ in
            self.categoryView.isHidden = true
        }
    }

 
 

    @objc func didBecomeActiveNotification() {
        if isJumpToAuthorization {
            loadLocalData()
            isJumpToAuthorization = false
        }
    }
 
}

extension PQUploadController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UIScrollViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection _: Int) -> Int {
        if collectionView == self.collectionView {
            return allPhotos == nil ? videoData.count : allPhotos.count
        }
        return categoryData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if collectionView == self.collectionView {
            let cell = PQSelecteVideoItemCell.selecteVideoItemCell(collectionView: collectionView, indexPath: indexPath)
            if videoData.count <= indexPath.item, allPhotos != nil {
                let itemData = PQUploadModel()
                // itemData.image = UIImage.init(named: "cut_place")
                let asset = allPhotos.object(at: indexPath.item)
                itemData.asset = asset
                itemData.duration = asset.duration
                videoData.append(itemData)
            }
            if videoData.count > indexPath.item {
                let itemData = videoData[indexPath.item]
                cell.uploadData = itemData
                if itemData.image == nil, itemData.asset != nil {
                    cell.representedAssetIdentifier = itemData.asset?.localIdentifier
                    imageManager.requestImage(for: itemData.asset!, targetSize: itemSize, contentMode: .aspectFill, options: nil) { image, info in
                        if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell.representedAssetIdentifier == itemData.asset?.localIdentifier {
                            if image != nil {
                                itemData.image = image
                                cell.videoImageView.image = image
                            } else if image == nil, info?.keys.contains("PHImageResultIsInCloudKey") ?? false {
                                let option = PHImageRequestOptions()
                                option.isNetworkAccessAllowed = true
                                option.resizeMode = .fast
                                self.imageManager.requestImageData(for: itemData.asset!, options: option) { data, _, _, _ in
                                    if data != nil {
                                        let image = UIImage(data: data!)
                                        itemData.image = image
                                        cell.videoImageView.image = image
                                    }
                                }
                            }
                        }
                    }
                }
            } else {
                cell.uploadData = PQUploadModel()
            }
            return cell
        } else {
            let cell = PQAssetCategoryCell.assetCategoryCell(collectionView: collectionView, indexPath: indexPath)
            let itemData = categoryData[indexPath.item]
            let asset = itemData.categoryList.object(at: 0)
            if itemData.image == nil {
                cell.representedAssetIdentifier = asset.localIdentifier
                imageManager.requestImage(for: asset, targetSize: itemSize, contentMode: .aspectFill, options: nil) { image, info in
                    if info?.keys.contains("PHImageResultIsDegradedKey") ?? false, "\(info?["PHImageResultIsDegradedKey"] ?? "0")" == "0", cell.representedAssetIdentifier == asset.localIdentifier {
                        itemData.image = image
                        cell.uploadData = itemData
                    }
                }
            } else {
                cell.uploadData = itemData
            }
            cell.isSelected = indexPath == catagerySelectedIndex
            return cell
        }
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if collectionView == self.collectionView {
            if videoData.count <= indexPath.item {
                return
            }
            let itemData = videoData[indexPath.item]
      
            let ratio = Float(itemData.asset?.pixelWidth ?? 0) / Float(itemData.asset?.pixelHeight ?? 1)
            if ratio < 0.4 || ratio > 4.2 {
                cShowHUB(superView: nil, msg: "暂不支持该比例的素材")
                return
            }
            if lastSeletedIndex != nil, lastSeletedIndex != indexPath {
                let lastData = videoData[lastSeletedIndex!.item]
                lastData.isSelected = false
                collectionView.reloadItems(at: [lastSeletedIndex!])
            }
            lastSeletedIndex = indexPath
            if itemData.isSelected {
                itemData.isSelected = false
                selectedData = nil
             
            } else {
                itemData.isSelected = true
                let itemData = videoData[indexPath.item]
              
                selectedData = itemData
                
            }
         
            collectionView.reloadItems(at: [indexPath])
        } else {
            videoData.removeAll()
            self.collectionView.setContentOffset(CGPoint.zero, animated: true)
            self.collectionView.reloadData()
            allPhotos = categoryData[indexPath.item].categoryList
            catagerySelectedIndex = indexPath
            selecteBtn.setTitle(categoryData[indexPath.item].title, for: .normal)
            selecteBtn.imagePosition(at: PQButtonImageEdgeInsetsStyle.right, space: cDefaultMargin / 2)
           
            lastSeletedIndex = nil
    
            if allPhotos.count <= 0 {
                emptyRemindView.frame = CGRect(x: 0, y: cDevice_iPhoneNavBarAndStatusBarHei, width: cScreenWidth, height: cScreenHeigth - cDevice_iPhoneNavBarAndStatusBarHei - cDevice_iPhoneTabBarHei)
                emptyRemindView.emptyData = emptyData
                emptyRemindView.isHidden = false
            } else {
                emptyRemindView.isHidden = true
            }
            self.collectionView.reloadData()
            cancelClick()
        }
    }

    func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, sizeForItemAt _: IndexPath) -> CGSize {
        if collectionView == self.collectionView {
            return CGSize(width: (cScreenWidth - cDefaultMargin) / 3, height: (cScreenWidth - cDefaultMargin) / 3)
        }
        return CGSize(width: collectionView.frame.width, height: cDefaultMargin * 8)
    }

    func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, minimumLineSpacingForSectionAt _: Int) -> CGFloat {
        if collectionView == self.collectionView {
            return cDefaultMargin / 2
        }
        return 0
    }

    func collectionView(_ collectionView: UICollectionView, layout _: UICollectionViewLayout, minimumInteritemSpacingForSectionAt _: Int) -> CGFloat {
        if collectionView == self.collectionView {
            return cDefaultMargin / 2
        }
        return 0
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        //这里是不是有用的？
//        if currentController() is PQUploadController || currentController() is PQImageSelectedController {
//            if scrollView == collectionView {
//                updateCachedAssets()
//            } else {
//                BFLog(message: "contentOffset = \(scrollView.contentOffset),contentSize = \(scrollView.contentSize)")
//                if scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.height) + cDefaultMargin * 10) {
//                    cancelClick()
//                }
//            }
//        }
    }
}

extension PQUploadController: PHPhotoLibraryChangeObserver {
    func photoLibraryDidChange(_ changeInstance: PHChange) {
        // Change notifications may be made on a background queue. Re-dispatch to the
        // main queue before acting on the change as we'll be updating the UI.
        DispatchQueue.main.sync { [weak self] in
            // Check each of the three top-level fetches for changes.
            if allPhotos != nil, changeInstance.changeDetails(for: allPhotos) != nil {
                self?.categoryData.removeAll()
                self?.loadPhotoData()
            }
        }
    }
}

extension PQUploadController {
    /// 添加监听
    /// - Parameter playerItem: <#playerItem description#>
    /// - Returns: <#description#>
    func addPlayerItemObserver() {
        playerItem?.addObserver(self, forKeyPath: "status", options: .new, context: nil)
    }

    /// 移除监听
    /// - Returns: <#description#>
    func removePlayerItemObserver() {
        playerItem?.removeObserver(self, forKeyPath: "status")
    }

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change _: [NSKeyValueChangeKey: Any]?, context _: UnsafeMutableRawPointer?) {
        if object is AVPlayerItem, keyPath == "status" {
            BFLog(message: "(object as! AVPlayerItem).status = \((object as! AVPlayerItem).status.rawValue)")
            PQLoadingHUB.shared.dismissHUB(superView: playerHeaderView)
            switch (object as! AVPlayerItem).status {
            case .unknown:
                break
            case .readyToPlay:
                break
            case .failed:
                break
            default:
                break
            }
        }
    }

    private func resetCachedAssets() {
        imageManager.stopCachingImagesForAllAssets()
        previousPreheatRect = .zero
    }

    private func updateCachedAssets() {
        if allPhotos != nil && allPhotos.count <= 0 {
            return
        }
        guard isViewLoaded, view.window != nil else { return }
        let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size)
        let preheatRect = visibleRect.insetBy(dx: 0, dy: -0.5 * visibleRect.height)
        let delta = abs(preheatRect.midY - previousPreheatRect.midY)
        guard delta > view.bounds.height / 3 else { return }
        let (addedRects, removedRects) = differencesBetweenRects(previousPreheatRect, preheatRect)
        let addedAssets = addedRects
            .flatMap { rect in collectionView.indexPathsForElements(in: rect) }
            .map { indexPath in allPhotos.object(at: indexPath.item) }
        let removedAssets = removedRects
            .flatMap { rect in collectionView.indexPathsForElements(in: rect) }
            .map { indexPath in allPhotos.object(at: indexPath.item) }
        imageManager.startCachingImages(for: addedAssets,
                                        targetSize: itemSize, contentMode: .aspectFill, options: nil)
        imageManager.stopCachingImages(for: removedAssets,
                                       targetSize: itemSize, contentMode: .aspectFill, options: nil)

        previousPreheatRect = preheatRect
    }

    private func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
        if old.intersects(new) {
            var added = [CGRect]()
            if new.maxY > old.maxY {
                added += [CGRect(x: new.origin.x, y: old.maxY,
                                 width: new.width, height: new.maxY - old.maxY)]
            }
            if old.minY > new.minY {
                added += [CGRect(x: new.origin.x, y: new.minY,
                                 width: new.width, height: old.minY - new.minY)]
            }
            var removed = [CGRect]()
            if new.maxY < old.maxY {
                removed += [CGRect(x: new.origin.x, y: new.maxY,
                                   width: new.width, height: old.maxY - new.maxY)]
            }
            if old.minY < new.minY {
                removed += [CGRect(x: new.origin.x, y: old.minY,
                                   width: new.width, height: new.minY - old.minY)]
            }
            return (added, removed)
        } else {
            return ([new], [old])
        }
    }
}
 
