import { useEffect, useRef, useState } from 'react'
import type { BackendArt } from '../../functions/BackendTypes'
import { useScrollRoot } from '../../functions/Context'
import { routeIntercept } from '../../functions/Route'
import { CDN_BASE } from '../../functions/Backend'
import './styles/LayoutBrowser.css'

interface PropsForLayoutBrowser {
    items: BackendArt[]
    position: number
    onEndReached?: () => void
}

export interface RecoverForLayoutBrowser {
    position: number
    items: BackendArt[]
}

export default function LayoutBrowser({ items, position, onEndReached }: PropsForLayoutBrowser) {
    const [columnCount, setColumnCount] = useState(3)
    const containerRef = useRef<HTMLDivElement>(null)
    const scrollRoot = useScrollRoot()
    const didRestore = useRef(false)

    // Endless Scrolling
    useEffect(() => {
        if (!onEndReached || !scrollRoot) return
        const onScroll = () => {
            const { scrollTop, scrollHeight, clientHeight } = scrollRoot
            if (scrollTop + clientHeight >= scrollHeight - 100) {
                onEndReached()
            }
        }
        scrollRoot.addEventListener('scroll', onScroll)
        return () => scrollRoot.removeEventListener('scroll', onScroll)
    }, [onEndReached, scrollRoot])

    // Restore Scrolling
    useEffect(() => {
        if (!scrollRoot || didRestore.current) return

        // avoid race conditions
        const raf = requestAnimationFrame(() => {
            scrollRoot.scrollTo({ top: position })
            didRestore.current = true
        })

        return () => {
            cancelAnimationFrame(raf)
        }
    }, [scrollRoot, position, items])

    // Calculate Column Count
    useEffect(() => {
        const el = containerRef.current
        if (!el) return
        const ro = new ResizeObserver(([entry]) => {
            setColumnCount(Math.max(1, Math.floor(entry.contentRect.width / 160)))
        })
        ro.observe(el)
        return () => ro.disconnect()
    }, [])

    const columns: BackendArt[][] = Array.from({ length: columnCount }, () => [])
    items.forEach((item, i) => columns[i % columnCount].push(item))

    return (
        <div className="layout-browser" ref={containerRef}>
            {columns.map((column, columnIdx) => (
                <div key={columnIdx} className="column">
                    {column.map((item, itemIdx) => {
                        const animationOrder = Math.min(columnIdx + itemIdx * columnCount, 25)
                        const animationDelay = `calc(${animationOrder} * var(--animation-step-delay))`
                        return (
                            <a
                                className="item"
                                href={`/art/${item.id}`}
                                onClick={(e) =>
                                    routeIntercept(e, item, {
                                        position: scrollRoot?.scrollTop ?? 0,
                                        items: items,
                                    } as RecoverForLayoutBrowser)
                                }>
                                <img
                                    style={{ animationDelay }}
                                    className="preview animation-fall-in"
                                    src={`${CDN_BASE}/${item.id}/preview.avif`}
                                />
                                <div className="metadata">
                                    <div className="title">{item.title}</div>
                                </div>
                            </a>
                        )
                    })}
                </div>
            ))}
        </div>
    )
}
