import { cos, Fn, fwidth, If, smoothstep, uniform, vec4 } from 'three/tsl'
import { TempNode, type NodeBuilder } from 'three/webgpu'

import type { Node } from '@takram/three-geospatial/webgpu'

import { getAtmosphereContext } from './AtmosphereContext'
import { getSolarLuminance } from './runtime'

export class SunNode extends TempNode {
  static override get type(): string {
    return 'SunNode'
  }

  rayDirectionECEF?: Node

  angularRadius = uniform(0.004675) // ≈ 16 arcminutes
  intensity = uniform(1)

  constructor() {
    super('vec4')
  }

  override setup(builder: NodeBuilder): unknown {
    const atmosphereContext = getAtmosphereContext(builder)

    const { rayDirectionECEF } = this
    if (rayDirectionECEF == null) {
      return
    }
    const { sunDirectionECEF } = atmosphereContext

    return Fn(() => {
      const chordThreshold = cos(this.angularRadius).oneMinus().mul(2)
      const chordVector = rayDirectionECEF.sub(sunDirectionECEF)
      const chordLength = chordVector.dot(chordVector)
      const filterWidth = fwidth(chordLength)

      const luminance = vec4(0).toVar()
      If(chordLength.lessThan(chordThreshold), () => {
        const antialias = smoothstep(
          chordThreshold,
          chordThreshold.sub(filterWidth),
          chordLength
        )
        luminance.assign(
          vec4(getSolarLuminance().mul(this.intensity), antialias)
        )
      })
      return luminance
    })()
  }
}
