import { useMemo, ReactNode } from "react";
import { ExtrudeGeometryOptions, Shape, Vector2, Vector3, Euler } from "three";
import { Extrude } from "@react-three/drei";
import { ThreeEvent } from "@react-three/fiber";

function ExtrudePolygon({
    name,
    points,
    options,
    userData,
    children,
    castShadow,
    receiveShadow,
    position = [0, 0, 0],
    rotation = [Math.PI / 2, 0, 0],
    onClick,
    onContextMenu,
    onDoubleClick,
    onPointerUp,
    onPointerDown,
    onPointerOver,
    onPointerOut,
    onPointerEnter,
    onPointerLeave,
    onPointerMove,
    onPointerMissed,
    onPointerCancel,
    onWheel,
}: Readonly<{
    name?: string;
    options?: ExtrudeGeometryOptions;
    userData?: Record<string, any>;
    points: Point[];
    children?: ReactNode;
    castShadow?: boolean;
    receiveShadow?: boolean;
    position?: [number, number, number] | Vector3;
    rotation?: [number, number, number] | Euler;
    onClick?: (event: ThreeEvent<MouseEvent>) => void;
    onContextMenu?: (event: ThreeEvent<MouseEvent>) => void;
    onDoubleClick?: (event: ThreeEvent<MouseEvent>) => void;
    onPointerUp?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerDown?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerOver?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerOut?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerEnter?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerLeave?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerMove?: (event: ThreeEvent<PointerEvent>) => void;
    onPointerMissed?: (event: MouseEvent) => void;
    onPointerCancel?: (event: ThreeEvent<PointerEvent>) => void;
    onWheel?: (event: ThreeEvent<WheelEvent>) => void;
}>) {
    const points2D = useMemo(() => {
        return points.map((p) => new Vector2(parseFloat(p.position[0].toFixed(2)), parseFloat(p.position[2].toFixed(2))));
    }, [points]);

    const shape = useMemo(() => {
        const shape = new Shape();
        shape.moveTo(points2D[0].x, points2D[0].y);
        for (let i = 1; i < points2D.length; i++) {
            shape.lineTo(points2D[i].x, points2D[i].y);
        }
        shape.closePath();
        return shape;
    }, [points2D]);

    if (!shape) return null;

    return (
        <Extrude
            name={name}
            args={[shape, options]}
            position={position}
            rotation={rotation}
            userData={userData}
            castShadow={castShadow}
            receiveShadow={receiveShadow}
            onClick={onClick}
            onContextMenu={onContextMenu}
            onDoubleClick={onDoubleClick}
            onPointerUp={onPointerUp}
            onPointerDown={onPointerDown}
            onPointerOver={onPointerOver}
            onPointerOut={onPointerOut}
            onPointerEnter={onPointerEnter}
            onPointerLeave={onPointerLeave}
            onPointerMove={onPointerMove}
            onPointerMissed={onPointerMissed}
            onPointerCancel={onPointerCancel}
            onWheel={onWheel}
        >
            {children}
        </Extrude>
    );
}

export default ExtrudePolygon;
