import React, { useEffect, useMemo } from 'react';
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
import { Html, Extrude } from '@react-three/drei';
import { useLoader } from '@react-three/fiber';
import { useSceneContext } from '../../../scene/sceneContext';
import { useToggleView } from '../../../../store/builder/store';
import { useWallClassification } from './instance/helpers/useWallClassification';
import Line from '../../line/line';
import Point from '../../point/point';
import WallInstance from './instance/wallInstance';
import * as Constants from '../../../../types/world/worldConstants';

import texturePath from "../../../../assets/textures/floor/white.png";
import texturePathDark from "../../../../assets/textures/floor/black.png";

function WallInstances() {
    const { wallStore } = useSceneContext();
    const { walls } = wallStore();
    const { rooms } = useWallClassification(walls);
    const { toggleView } = useToggleView();

    useEffect(() => {
        // console.log('walls: ', walls);
    }, [walls])

    const allPoints = useMemo(() => {
        const points: Point[] = [];
        const seenUuids = new Set<string>();

        walls.forEach(wall => {
            wall.points.forEach(point => {
                if (!seenUuids.has(point.pointUuid)) {
                    seenUuids.add(point.pointUuid);
                    points.push(point);
                }
            });
        });

        return points;
    }, [walls]);

    return (
        <>
            {!toggleView && (
                <>
                    {walls.map((wall) => (
                        <WallInstance key={wall.wallUuid} wall={wall} />
                    ))}

                    <group name='Wall-Floors-Group'>
                        {rooms.map((room, index) => (
                            <Floor key={index} room={room} />
                        ))}
                    </group>
                </>
            )}

            {toggleView && (
                <>
                    <group name='Wall-Points-Group'>
                        {allPoints.map((point) => (
                            <Point key={point.pointUuid} point={point} />
                        ))}
                    </group>

                    <group name='Wall-Lines-Group'>

                        {walls.map((wall) => (
                            <React.Fragment key={wall.wallUuid}>
                                <Line points={wall.points} />
                            </React.Fragment>
                        ))}

                        {walls.map((wall) => {
                            const textPosition = new Vector3().addVectors(new Vector3(...wall.points[0].position), new Vector3(...wall.points[1].position)).divideScalar(2);
                            const distance = new Vector3(...wall.points[0].position).distanceTo(new Vector3(...wall.points[1].position));

                            return (
                                < React.Fragment key={wall.wallUuid}>
                                    {toggleView &&
                                        <Html
                                            key={`${wall.points[0].pointUuid}_${wall.points[1].pointUuid}`}
                                            userData={wall}
                                            position={[textPosition.x, 1, textPosition.z]}
                                            wrapperClass="distance-text-wrapper"
                                            className="distance-text"
                                            zIndexRange={[1, 0]}
                                            prepend
                                            sprite
                                        >
                                            <div
                                                key={wall.wallUuid}
                                                className={`distance ${wall.wallUuid}`}
                                            >
                                                {distance.toFixed(2)} m
                                            </div>
                                        </Html>
                                    }
                                </React.Fragment>
                            )
                        })}

                    </group>
                </>
            )}
        </>
    )
}

export default WallInstances;

function Floor({ room }: { room: Point[] }) {
    const savedTheme: string | null = localStorage.getItem('theme');
    const textureScale = Constants.floorConfig.textureScale;
    const floorTexture = useLoader(TextureLoader, savedTheme === "dark" ? texturePathDark : texturePath);
    floorTexture.wrapS = floorTexture.wrapT = RepeatWrapping;
    floorTexture.repeat.set(textureScale, textureScale);
    floorTexture.colorSpace = SRGBColorSpace;

    const shape = useMemo(() => {
        const shape = new Shape();
        const points = room.map(p => new Vector2(p.position[0], p.position[2]));
        if (points.length < 3) return null;
        shape.moveTo(points[0].x, points[0].y);
        points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
        return shape;
    }, [room]);

    if (!shape) return null;

    return (
        <mesh name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
            <Extrude
                receiveShadow
                castShadow
                name="Wall-Floor"
                args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]}
                position={[0, 0, 0]}
            >
                <meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
            </Extrude>
        </mesh>
    );
}
