import React, { useMemo } from "react";
import Cylinder from "3dModels/Shapes/3D/Cylinder";
import Cone from "3dModels/Shapes/3D/Cone";
import { Vector3, Euler } from "three";

interface Props {
    diameter: number;
    sidewallHeight: number;
    hopperHeight?: number;
    fillPercent: number;
}

export default function GrainFillFlat(props: Props) {
    const {
        diameter,
        sidewallHeight,
        hopperHeight = 0,
        fillPercent
    } = props;

    const radius = diameter / 2;

    // Slightly smaller to avoid z-fighting with shell
    const grainRadius = radius * 0.98;

    // --- volumes ---
    const cylinderVolume = Math.PI * radius * radius * sidewallHeight;
    const hopperVolume = hopperHeight > 0
        ? (1 / 3) * Math.PI * radius * radius * hopperHeight
        : 0;

    const totalVolume = cylinderVolume + hopperVolume;
    const filledVolume = totalVolume * fillPercent;

    // --- result values ---
    let hopperFillHeight = 0;
    let cylinderFillHeight = 0;

    if (hopperHeight > 0 && filledVolume <= hopperVolume) {
        // ONLY hopper filling
        const ratio = filledVolume / hopperVolume;

        hopperFillHeight = hopperHeight * Math.pow(ratio, 1 / 3);
        cylinderFillHeight = 0;
    } else {
        // hopper full (or no hopper)
        hopperFillHeight = hopperHeight;

        const remainingVolume = filledVolume - hopperVolume;

        cylinderFillHeight = Math.max(
            0,
            remainingVolume / (Math.PI * radius * radius)
        );
    }

    // --- positions ---

    const hopperPosition = useMemo(
        () => new Vector3(
            0,
            -(sidewallHeight / 2 + hopperHeight) + hopperFillHeight / 2, //adding the hopper height so it starts at the cone and not the flat side
            0
        ),
        [sidewallHeight, hopperFillHeight]
    );

    //flip the cone so it matches the hoppers rotation with the cone pointed down
    const hopperRotation = useMemo(
        () => new Euler(Math.PI, 0, 0),
        []
    );

    const cylinderPosition = useMemo(
        () => new Vector3(
            0,
            -sidewallHeight / 2 + cylinderFillHeight / 2,
            0
        ),
        [sidewallHeight, cylinderFillHeight]
    );

    // --- material ---
    const grainColour = "#fff302";

    return (
        <>
            {/* Hopper fill */}
            {hopperHeight > 0 && hopperFillHeight > 0 && (
                <Cone
                    geometry={{
                        radius: grainRadius * (hopperFillHeight / hopperHeight),
                        height: hopperFillHeight,
                        radialSegments: 20,
                        openEnded: false
                    }}
                    position={hopperPosition}
                    rotation={hopperRotation}
                    colour={grainColour}
                    roughness={1}
                    metalness={0}
                />
            )}

            {/* Cylinder fill */}
            {cylinderFillHeight > 0 && (
                <Cylinder
                    geometry={{
                        radiusTop: grainRadius,
                        radiusBottom: grainRadius,
                        height: cylinderFillHeight,
                        radialSegments: 20,
                        openEnded: false
                    }}
                    position={cylinderPosition}
                    colour={grainColour}
                    roughness={1}
                    metalness={0}
                />
            )}
        </>
    );
}