import { useEffect, useRef, useState } from 'preact/hooks'
import { simplifyCurve } from '../../lib/math/curves.js'

class KnotSimulation {
    constructor(knotRef) {
        this.knotRef = knotRef
        this.ghostPath = null
    }

    onMouseDrag(x, y) {
        if (!this.ghostPath) {
            this.ghostPath = []
        }

        this.ghostPath.push([x, y])
    }

    onMouseUp() {
        this.knotRef.current.points = simplifyCurve(this.ghostPath, 15)
        this.ghostPath = null
    }

    update() {}

    /** @param {CanvasRenderingContext2D} g */
    render(g) {
        const w = g.canvas.width
        const h = g.canvas.height
        const knot = this.knotRef.current

        g.clearRect(0, 0, w, h)
        g.lineWidth = 3
        g.lineCap = 'round'
        g.lineJoin = 'round'

        g.strokeStyle = '#333'
        if (this.ghostPath && this.ghostPath.length > 0) {
            g.strokeStyle = '#888'
            g.beginPath()
            {
                const [x0, y0] = this.ghostPath[0]
                g.moveTo(x0, y0)
                for (const [x, y] of this.ghostPath) {
                    g.lineTo(x, y)
                }
            }
            g.stroke()
        } else if (knot.points.length > 0) {
            g.beginPath()
            const [x0, y0] = knot.points[0]
            g.moveTo(x0, y0)

            for (const [x, y] of knot.points) {
                g.lineTo(x, y)
            }
            g.stroke()

            g.fillStyle = '#080'
            for (const [x, y] of knot.points) {
                g.beginPath()
                g.ellipse(x, y, 3, 3, 0, 0, Math.PI * 2)
                g.fill()
            }
        }
    }
}

export const KnotLayer = ({ knotRef }) => {
    const canvasRef = useRef(null)
    const [knotSim] = useState(() => new KnotSimulation(knotRef))

    useEffect(() => {
        window.addEventListener('resize', () => {
            // trigger repaint and get a new context
        })
    }, [])

    useEffect(() => {
        let simTimerHandle

        if (canvasRef.current) {
            canvasRef.current.width = canvasRef.current.offsetWidth
            canvasRef.current.height = canvasRef.current.offsetHeight

            const g = canvasRef.current.getContext('2d')

            simTimerHandle = setInterval(() => {
                knotSim.update()
                requestAnimationFrame(() => knotSim.render(g))

                console.log('Prova')
            }, 1000 / 30)
        }

        return () => {
            if (simTimerHandle) {
                clearInterval(simTimerHandle)
            }
        }
    }, [canvasRef.current])

    return (
        <canvas
            ref={canvasRef}
            onMouseDown={e => {
                if (e.buttons === 1) {
                    knotSim.onMouseDrag(e.offsetX, e.offsetY)
                }
            }}
            onMouseMove={e => {
                if (e.buttons === 1) {
                    knotSim.onMouseDrag(e.offsetX, e.offsetY)
                }
            }}
            onMouseUp={e => {
                knotSim.onMouseUp()
            }}
        />
    )
}
