'use strict'

modules['cube'] = {
    config: [
        ['fov', 'angle', 90],
        ['roll', 'angle', 0],
        ['pitch', 'angle', 0],
        ['yaw', 'angle', 0],
        ['brightness', 'float', 1],
        ['texture', 'texture', 'default'],
        ['size', 'float', 4],
        ['scale', 'float3', [1, 1, 1]],
    ],

    render: async (time, self, config) => {
        const {
            fov,
            roll,
            pitch,
            yaw,
            brightness,
            texture,
            size,
            scale,
        } = { ...config }

        const texSize = texture.size
        const texData = texture.data

        let m = m4.yRotation(yaw)
        m = m4.xRotate(m, pitch)
        m = m4.zRotate(m, roll)

        let cubeDist = texSize * size
        const depthBrightnessScaler = 1 / (texSize * size * .03)
        const greyscaleBuffer = greyscaleBuffers[getOutputBufferId()]
        const iHalfWidth = 1 / 240
        const iHalfHeight = 1 / 320
        let index = 0
        for (let y = 0; y < 480; ++y) {
            for (let x = 0; x < 640; ++x) {
                const direction = [(x - 320) * iHalfWidth, (y - 240 ) * iHalfHeight, fov, 0]
                const l = m4.transformVector(m, direction)

                const dx = Math.abs(cubeDist / l[0])
                const dy = Math.abs(cubeDist / l[1])
                const dz = Math.abs(cubeDist / l[2])
                
                let u, v
                const dmin = Math.min(Math.min(dx, dy), dz)
                if (dmin === dx) {
                    u = Math.abs(l[1] * dx) * scale[0]
                    v = Math.abs(l[2] * dx) * scale[0]
                } else if (dmin === dy) {
                    u = Math.abs(l[0] * dy) * scale[1]
                    v = Math.abs(l[2] * dy) * scale[1]
                } else {
                    u = Math.abs(l[0] * dz) * scale[2]
                    v = Math.abs(l[1] * dz) * scale[2]
                }

                const directionNormal = m4.normalize(direction)
                const tx = directionNormal[0] * dmin
                const ty = directionNormal[1] * dmin
                const tz = directionNormal[2] * dmin
                const distance = Math.sqrt(tx*tx + ty*ty + tz*tz) * .01
                const depthBrightness = 1 - (distance * depthBrightnessScaler)

                const greyscale = texData[Math.floor((u%texSize)) + Math.floor((v%texSize)) * texSize]
                greyscaleBuffer[index++] = Math.max(0, greyscale * brightness * depthBrightness)
            }
        }
    }
}
