import { Link } from "@onegeo-suite/gatsby-theme-onegeo"
import React from "react"
import { useEffect, useState } from "react"
import { useHeadsObserver } from "./utils/hook"

const rnd = (() => {
    const gen = (min: number, max: number) =>
        max++ &&
        [...Array(max - min)].map((s, i) => String.fromCharCode(min + i))

    const sets = {
        alphaLower: gen(97, 122),
        alphaUpper: gen(65, 90),
    }

    function* iter(len: number, set: any) {
        if (set.length < 1) set = Object.values(sets).flat()
        for (let i = 0; i < len; i++)
            yield set[(Math.random() * set.length) | 0]
    }

    return Object.assign(
        (len: number, ...set: any) => [...iter(len, set.flat())].join(""),
        sets
    )
})()

const navStyle = {
    position: "sticky -webkit-sticky",
    top: "24px",
    maxHeight: "calc(100vh - 40px)",
    overflow: "auto",
} as unknown as React.CSSProperties

let navulliStyle = {
    marginBottom: "15px",
} as React.CSSProperties

const getClassName = (level: number) => {
    switch (level) {
        case 1:
            navulliStyle = {
                ...navulliStyle,
                marginLeft: "0px",
            }
            return "head1"
        case 2:
            navulliStyle = {
                ...navulliStyle,
                marginLeft: "10px",
            }
            return "head2"
        case 3:
            navulliStyle = {
                ...navulliStyle,
                marginLeft: "20px",
            }
            return "head3"
        case 4:
            navulliStyle = {
                ...navulliStyle,
                marginLeft: "30px",
            }
            return "head4"
        default:
            return undefined
    }
}

interface Props {
    className?: string
}

const Toc = (props: Props) => {
    const { className = "" } = props
    const [headings, setHeadings] = useState<any>([])
    const { activeId } = useHeadsObserver()

    useEffect(() => {
        const elements = Array.from(
            document.querySelectorAll("h1, h2, h3, h4")
        ).map((elem) => ({
            id: elem.id ? elem.id : (elem.id = rnd(4)),
            text: elem.textContent,
            level: Number(elem.nodeName.charAt(1)),
        }))
        setHeadings(elements)
    }, [])

    return (
        <aside
            className={`bg-base-100 sticky top-24 hidden h-full max-w-xs rounded-xl p-6 shadow-lg lg:block ${className}`}
        >
            <nav style={navStyle}>
                <ul style={navulliStyle}>
                    {headings.map((heading: any) => (
                        <li
                            key={heading.id}
                            className={getClassName(heading.level)}
                            style={navulliStyle}
                        >
                            <Link to={`#${heading.id}`}>{heading.text}</Link>
                        </li>
                    ))}
                </ul>
            </nav>
        </aside>
    )
}

export default Toc