import Circle, { CircleGeometry } from "3dModels/Shapes/3D/Circle"
import Cone, { ConeGeometry } from "3dModels/Shapes/3D/Cone"
import Cylinder, { CylinderGeometry } from "3dModels/Shapes/3D/Cylinder"
import React from "react"
import { Euler, Vector3 } from "three"

interface Props {
    radialSegments: number
    binBodyColour: string
    binMetalness: number
    binRoughness: number
    binOpacity: number
    diameter: number
    sidewallHeight: number
    roofHeight: number
    hopperHeight?: number
    wireframe?: boolean
    renderOrder?: number
}

export default function BinShell(props: Props) {
    const { radialSegments, binBodyColour, binMetalness, binRoughness, binOpacity, diameter, sidewallHeight, roofHeight, hopperHeight, wireframe, renderOrder } = props
    const cylinderGeometry = React.useMemo(() => ({
        radiusTop: diameter / 2,
        radiusBottom: diameter / 2,
        height: sidewallHeight,
        radialSegments,
        heightSegments: 2,
        openEnded: true,
    } as CylinderGeometry), [diameter, sidewallHeight, radialSegments]);

    const roofGeometry = React.useMemo(() => ({
        height: roofHeight,
        radius: diameter /2,
        radialSegments: radialSegments,
        openEnded: true
    } as ConeGeometry), [diameter, roofHeight, radialSegments])

    const hopperGeometry = React.useMemo(() => ({
        height: hopperHeight,
        radius: diameter /2,
        radialSegments: radialSegments,
        openEnded: true
    } as ConeGeometry),[hopperHeight, diameter, radialSegments])

    const flatBottomGeometry = React.useMemo(() => ({
        radius: diameter/2,
        radialSegments: radialSegments
    } as CircleGeometry),[diameter, radialSegments])

    const roofPosition = React.useMemo(
        () => new Vector3(0, sidewallHeight/2 + roofHeight/2, 0),
        [sidewallHeight, roofHeight]
    );

    const bottomPosition = React.useMemo(
        () => {
            if(hopperHeight !== undefined && hopperHeight > 0){
                //this returns the position for the center of the cone for the hopper
                return new Vector3(0, (sidewallHeight/2 + hopperHeight/2)*-1, 0)
            } else {
                //this returns the position for the circle for the flat bottom
                return new Vector3(0, -sidewallHeight/2, 0)
            }
        },
        [sidewallHeight, hopperHeight]
    )

    const hopperRotation = React.useMemo(
        () => new Euler(Math.PI, 0, 0),
        []
    );
    
    const flatBottomRotation = React.useMemo(
        () => new Euler(-Math.PI / 2, 0, 0),
        []
    );

    return (
        <React.Fragment>
            {/* bin roof - cone */}
            <Cone 
                geometry={roofGeometry} 
                colour={binBodyColour} 
                wireframe= {wireframe}
                metalness={binMetalness} 
                position={roofPosition} 
                roughness={binRoughness}
                side={2}
                opacity={binOpacity}
                depthWrite={false}
                depthTest={false}
                renderOrder={renderOrder}/>
            {/* bin sidewall - cylinder (open ended for the roof and bottom)*/}
            <Cylinder 
                geometry={cylinderGeometry} 
                colour={binBodyColour} 
                wireframe= {wireframe}
                metalness={binMetalness} 
                roughness={binRoughness}
                opacity={binOpacity}
                depthWrite={false}
                depthTest={false}
                renderOrder={renderOrder}/>
            {/* bin bottom - cone -OR- circle depending on the bins shape*/}
            {hopperHeight !== undefined && hopperHeight > 0 ?
                <Cone 
                    geometry={hopperGeometry}
                    colour={binBodyColour} 
                    wireframe= {wireframe} 
                    metalness={binMetalness} 
                    position={bottomPosition} 
                    rotation={hopperRotation} 
                    roughness={binRoughness} 
                    opacity={binOpacity}
                    side={2}
                    depthWrite={false}
                    depthTest={false}
                    renderOrder={renderOrder}
                />
            :
                <Circle 
                    geometry={flatBottomGeometry} 
                    colour={binBodyColour}
                    wireframe= {wireframe}
                    metalness={binMetalness}
                    position={bottomPosition}
                    rotation={flatBottomRotation} 
                    roughness={binRoughness}
                    opacity={binOpacity}
                    side={2}
                    depthWrite={false}
                    depthTest={false}
                    renderOrder={renderOrder}
                />
            }
        </React.Fragment>
    )

}