//
//  UITableView+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 nullDataImageViewKey = "nullDataImageViewKey"
private var dataArrayKey = "dataArrayKey"

private let PAGESIZE = 10
private let PAGENUM = 1

extension UITableView {
    // 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 nullDataImageView: UIImageView? {
        get { objc_getAssociatedObject(self, &nullDataImageViewKey) as? UIImageView }
        set { objc_setAssociatedObject(self, &nullDataImageViewKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
    }

    var dataArray: [Any] {
        get { objc_getAssociatedObject(self, &dataArrayKey) as? [Any] ?? [] }
        set { objc_setAssociatedObject(self, &dataArrayKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
    }

    // MARK: - Methods
    
    func myReloadData() {
        reloadData()
        guard let dataSource = dataSource else { return }
        var isEmpty = true
        let sections = (dataSource.responds(to: #selector(UITableViewDataSource.numberOfSections(in:))) ? dataSource.numberOfSections?(in: self) : 1) ?? 1

        for section in 0..<sections {
            if dataSource.tableView(self, numberOfRowsInSection: section) > 0 {
                isEmpty = false
                break
            }
        }

        if isEmpty {
            if nullDataImageView == nil {
                let nullImage = UIImage(named: "nullDataImageView") ?? UIImage()
                let w = nullImage.size.width
                let h = nullImage.size.height
                nullDataImageView = UIImageView(frame: CGRect(x: (bounds.width - w) / 2, y: (bounds.height - h) / 2, width: w, height: h))
                nullDataImageView?.image = nullImage
                if let nullDataImageView = nullDataImageView {
                    addSubview(nullDataImageView)
                }
            }
        } else {
            nullDataImageView?.removeFromSuperview()
            nullDataImageView = nil
        }
    }

    func handleDataArray(_ networkArray: [Any]) {
        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 {
            handleMJRefresh(count: count)
        }
    }

    func addFooter(refreshingBlock: @escaping () -> Void) {
        isUseMJRefresh = true
        mj_footer = MJRefreshAutoNormalFooter(refreshingBlock: { [weak self] in
            self?.pageNum += 1
            refreshingBlock()
        })
    }

    func addHeader(refreshingBlock: @escaping () -> Void) {
        isUseMJRefresh = true
        mj_header = MJRefreshNormalHeader(refreshingBlock: { [weak self] in
            self?.pageNum = PAGENUM
            refreshingBlock()
        })
    }

    func handleMJRefresh(count: Int) {
        if count >= pageSize {
            mj_footer?.resetNoMoreData()
        } else {
            mj_footer?.endRefreshingWithNoMoreData()
        }

        if pageNum <= PAGENUM {
            mj_header?.endRefreshing()
        } else {
            mj_footer?.endRefreshing()
        }
    }

    func handleMJRefreshWithError(_ error: String?) {
        if pageNum <= PAGENUM {
            mj_header?.endRefreshing()
        } else {
            mj_footer?.endRefreshing()
        }
    }

    func initBaseTableView(reuseXib cellIds: [String], isUseMJRefresh: Bool, delegate: UITableViewDelegate & UITableViewDataSource) {
        setUpTableView()
        self.isUseMJRefresh = isUseMJRefresh
        self.delegate = delegate
        self.dataSource = delegate

        cellIds.forEach { cellId in
            register(UINib(nibName: cellId, bundle: nil), forCellReuseIdentifier: cellId)
        }
    }

    func initBaseTableView(reuseClass cellIds: [String], isUseMJRefresh: Bool, delegate: UITableViewDelegate & UITableViewDataSource) {
        setUpTableView()
        self.isUseMJRefresh = isUseMJRefresh
        self.delegate = delegate
        self.dataSource = delegate

        cellIds.forEach { cellId in
            if let cellClass = cellId.toClass() {
                self.register(cellClass, forCellReuseIdentifier: cellId)
            }
        }
    }

    private func setUpTableView() {
        if #available(iOS 11.0, *) {
            contentInsetAdjustmentBehavior = .never
        }

        if #available(iOS 15.0, *) {
            sectionHeaderTopPadding = 0
        }

        separatorStyle = .none
        backgroundColor = .clear

        pageNum = PAGENUM
        pageSize = PAGESIZE
        dataArray = []

        estimatedRowHeight = 0
        estimatedSectionHeaderHeight = 0
        estimatedSectionFooterHeight = 0

        showsVerticalScrollIndicator = false
        showsHorizontalScrollIndicator = false
        
        
        backgroundColor = .clear

        if tableFooterView == nil {
            tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: 0, height: CGFLOAT_MIN))
        }
    }
}
