import { Object3D, Camera, WebGLCubeRenderTarget, CubeCamera, Scene } from 'three'
import * as React from 'react'
import { useThree } from '@react-three/fiber'

type Props = {
  all?: boolean
  scene?: Object3D
  camera?: Camera
}

export function Preload({ all, scene, camera }: Props) {
  const gl = useThree(({ gl }) => gl)
  const dCamera = useThree(({ camera }) => camera)
  const dScene = useThree(({ scene }) => scene)

  // Layout effect because it must run before React commits
  React.useLayoutEffect(() => {
    const invisible: Object3D[] = []
    if (all) {
      // Find all invisible objects, store and then flip them
      ;(scene || dScene).traverse((object) => {
        if (object.visible === false) {
          invisible.push(object)
          object.visible = true
        }
      })
    }
    // Now compile the scene
    gl.compile(scene || dScene, camera || dCamera)
    // And for good measure, hit it with a cube camera
    const cubeRenderTarget = new WebGLCubeRenderTarget(128)
    const cubeCamera = new CubeCamera(0.01, 100000, cubeRenderTarget)
    cubeCamera.update(gl, (scene || dScene) as Scene)
    cubeRenderTarget.dispose()
    // Flips these objects back
    invisible.forEach((object) => (object.visible = false))
  }, [])
  return null
}
