//
//  CLWaterfallLayout.swift
//  Visual_Novel_iOS
//
//  Created by mh on 2025/10/15.
//

import UIKit

final class CLWaterfallLayout: UICollectionViewLayout {
    // MARK: 可外部配置
    var columnCount: Int = 2
    var columnSpacing: CGFloat = 15
    var interItemSpacing: CGFloat = 10
    var sectionInset: UIEdgeInsets = .init(top: 0, left: 10, bottom: 10, right: 10)
    var delegate: WaterfallLayoutDelegate? = nil
    
    // MARK: 私有缓存
    private var cache: [UICollectionViewLayoutAttributes] = []
    private var contentHeight: CGFloat = 0
    private var colHeight: [CGFloat] = []
    
    override var collectionViewContentSize: CGSize {
        CGSize(width: collectionView!.bounds.width, height: contentHeight)
    }
    
    override func prepare() {
        super.prepare()
        guard cache.isEmpty, let cv = collectionView else { return }
        
        contentHeight = sectionInset.top
        colHeight = .init(repeating: sectionInset.top, count: columnCount)
        
        let itemCount = cv.numberOfItems(inSection: 0)
        let totalWidth = cv.bounds.width - sectionInset.left - sectionInset.right
        let cellWidth = (totalWidth - CGFloat(columnCount - 1) * columnSpacing) / CGFloat(columnCount)
        
        for idx in 0..<itemCount {
            let indexPath = IndexPath(item: idx, section: 0)
            // 找最短列
            let minCol = colHeight.firstIndex(of: colHeight.min()!)!
            let x = sectionInset.left + CGFloat(minCol) * (cellWidth + columnSpacing)
            let y = colHeight[minCol]
            
            // 高度由外部代理返回（动态） ((UIScreen.width - 30.0) / 2.0) / (4.0 * 3.0)
            let h = delegate?.collectionView(cv, layout: self, heightForItemAt: indexPath) ?? 100
            
            let attr = UICollectionViewLayoutAttributes(forCellWith: indexPath)
            attr.frame = CGRect(x: x, y: y, width: cellWidth, height: h)
            cache.append(attr)
            
            // 更新列高
            colHeight[minCol] = y + h + interItemSpacing
        }
        
        contentHeight = colHeight.max()! + sectionInset.bottom
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        cache.filter { $0.frame.intersects(rect) }
    }
    
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
        cache[indexPath.item]
    }
    
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        newBounds.width != collectionView?.bounds.width
    }
}

// MARK: - 代理协议（动态高度）
protocol WaterfallLayoutDelegate: AnyObject {
    func collectionView(_ collectionView: UICollectionView,
                        layout: CLWaterfallLayout,
                        heightForItemAt indexPath: IndexPath) -> CGFloat
}

