//
//  UICollectionView+Ex.swift
//  TSLiveWallpaper
//
//  Created by 100Years on 2024/12/20.
//

import UIKit
import MJRefresh

private var isMJRefreshKey = "isMJRefreshKey"
private var pageNumKey = "pageNumKey"
private var pageSizeKey = "pageSizeKey"
private var dataArrayKey = "dataArrayKey"

private let PAGESIZE = 10
private let PAGENUM = 1

extension UICollectionView {
    static func createCommon(delegate: UICollectionViewDelegate & UICollectionViewDataSource, cellReuseIds: [String]) -> UICollectionView {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .vertical
        
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        collectionView.delegate = delegate
        collectionView.dataSource = delegate
        collectionView.showsVerticalScrollIndicator = false
        collectionView.showsHorizontalScrollIndicator = false
        collectionView.backgroundColor = .clear
        
        if #available(iOS 11.0, *) {
            collectionView.contentInsetAdjustmentBehavior = .never
        }
        
        for cellReuseId in cellReuseIds {
            collectionView.register(cellReuseId.toClass(), forCellWithReuseIdentifier: cellReuseId)
        }
        
        collectionView.dataArray = []
        collectionView.pageNum = PAGENUM
        collectionView.pageSize = PAGESIZE
        
        return collectionView
    }
    
    func myReloadData() {
        reloadData()
    }
    
    func addFooterWithRefreshingBlock(_ block: @escaping () -> Void) {
        isUseMJRefresh = true
        mj_footer = MJRefreshAutoNormalFooter(refreshingBlock: { [weak self] in
            self?.pageNum += 1
            block()
        })
        (mj_footer as? MJRefreshAutoNormalFooter)?.stateLabel?.isHidden = true
    }
    
    func addHeaderWithRefreshingBlock(_ block: @escaping () -> Void) {
        isUseMJRefresh = true
        mj_header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in
            self?.pageNum = PAGENUM
            block()
        })
    }
    
    func handleDataArray(_ networkArray: [Any], noMore: Bool) {
        let count = networkArray.count
        
        if count > 0 {
            if pageNum <= PAGENUM {
                dataArray.removeAll()
            }
            dataArray.append(contentsOf: networkArray)
            myReloadData()
        } else if pageNum <= PAGENUM {
            dataArray.removeAll()
            myReloadData()
        }
        
        if isUseMJRefresh {
            if !noMore {
                mj_footer?.resetNoMoreData()
            } else {
                mj_footer?.endRefreshingWithNoMoreData()
            }
            
            if pageNum <= PAGENUM {
                mj_header?.endRefreshing()
            }
        }
    }
    
    func handleDataArray(_ networkArray: [Any]) {
        handleDataArray(networkArray, noMore: networkArray.count < pageSize)
    }
    
    func handleMJRefreshWithCount(_ count: Int) {
        if count >= pageSize {
            mj_footer?.resetNoMoreData()
        } else {
            mj_footer?.endRefreshingWithNoMoreData()
        }
        
        if pageNum <= PAGENUM {
            mj_header?.endRefreshing()
        }
    }
    
    func handleMJRefreshWithError(_ error: String) {
        if pageNum <= PAGENUM {
            mj_header?.endRefreshing()
        } else {
            mj_footer?.endRefreshing()
        }
    }
    
    // MARK: - Properties
    
    var isUseMJRefresh: Bool {
        get { (objc_getAssociatedObject(self, &isMJRefreshKey) as? Bool) ?? false }
        set { objc_setAssociatedObject(self, &isMJRefreshKey, newValue, .OBJC_ASSOCIATION_ASSIGN) }
    }
    
    var pageNum: Int {
        get { (objc_getAssociatedObject(self, &pageNumKey) as? Int) ?? PAGENUM }
        set { objc_setAssociatedObject(self, &pageNumKey, newValue, .OBJC_ASSOCIATION_ASSIGN) }
    }
    
    var pageSize: Int {
        get { (objc_getAssociatedObject(self, &pageSizeKey) as? Int) ?? PAGESIZE }
        set { objc_setAssociatedObject(self, &pageSizeKey, newValue, .OBJC_ASSOCIATION_ASSIGN) }
    }
    
    var dataArray: [Any] {
        get { (objc_getAssociatedObject(self, &dataArrayKey) as? [Any]) ?? [] }
        set { objc_setAssociatedObject(self, &dataArrayKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
    }
}
