<script setup lang="ts">
import { FrontSide, RepeatWrapping } from 'three';
import { TresCanvas, useTexture } from '@tresjs/core'
import { OrbitControls, useGLTF } from '@tresjs/cientos'

const fence_section = use_fence_section()
const section_count = use_section_count()
const extra_section = use_extra_section()
const max_size = use_max_size()

const controlsState = reactive({
    distance: section_count.value,
    minDistance: 7,
    maxDistance: 20,
    position: { x: 0, y: 0, z: 0 },
    enablePan: false,
    maxPolarAngle: (Math.PI / 2) - 0.2,
})
const cameraStat = reactive({
    position: [-4, 2, 8],
    aspect: 1920 / 600,
    fov: 40,
})

const pointLight = ref()

const groundMaterial = ref({
    color: "#555",
    roughness: 0.2,
    metalness: 0,
    side: FrontSide,
})
const loadAll = async () => {
    const { scene: light } = await useGLTF('/models_light/zabor_so_svetom.glb')
    pointLight.value = light.children[2]
    pointLight.value.color = '#f0dea9'
    pointLight.value.shadow.camera.near = 50
    pointLight.value.shadow.bias = -0.002

    const pbrTexture = await useTexture({
        map: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Color.png',
        displacementMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Displacement.png',
        roughnessMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_Roughness.png',
        normalMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_NormalDX.png',
        aoMap: '/texture/Grass004_2K-PNG/Grass004_2K-PNG_AmbientOcclusion.png',
    })
    const repeat = 10
    for (const key in pbrTexture) {
        if (Object.prototype.hasOwnProperty.call(pbrTexture, key)) {
            const key_p = key as keyof typeof pbrTexture
            const element = pbrTexture[key_p]
            if (element && element.wrapS) {
                element.wrapS = RepeatWrapping
                element.wrapT = RepeatWrapping
                element.repeat.x = repeat
                element.repeat.y = repeat
                element.flipY = false
            }
        }
    }
    groundMaterial.value = Object.assign(groundMaterial.value, {
        map: pbrTexture.map,
        displacementMap: pbrTexture.displacementMap,
        normalMap: pbrTexture.normalMap,
    })
}
const camera = ref("camera")

onMounted(() => {
    cameraStat.aspect = window.innerWidth / (window.innerHeight * 0.5)
    loadAll()
})
watch([section_count, extra_section], () => {
    let v = (section_count.value + ~~(!!extra_section.value)) * 1.5
    if (v < controlsState.minDistance) v = controlsState.minDistance
    if (v > controlsState.maxDistance) v = controlsState.maxDistance
    camera.value.position.normalize().multiplyScalar(v)
})
</script>
<template>
    <div class="container min-w-full relative h-[50vh]">
        <ClientOnly fallback-tag="div">
            <template #fallback>
                <div class="fallback">
                    Загрузка 3D модели
                </div>
            </template>
            <Loader />
            <TresCanvas shadows>
                <TresPerspectiveCamera v-bind="cameraStat" ref="camera" />
                <OrbitControls v-bind="controlsState" make-default />
                <TresGroup :position-x="Math.min(section_count, max_size) * fence_section * -1" :position-y="-3">
                    <Suspense>
                        <ModelParametric />
                    </Suspense>
                </TresGroup>
                <TresMesh receive-shadow :position-y="-3.65" name="ground">
                    <TresCircleGeometry :args="[50, 32]" :rotate-x="-Math.PI * 0.5" />
                    <TresMeshStandardMaterial v-bind="groundMaterial" />
                </TresMesh>

                <template v-if="pointLight">
                    <TresPointLight v-bind="pointLight" :intensity="pointLight.intensity"
                        :position="Object.values(pointLight.position).map((el: any) => el * 8)" cast-shadow />
                </template>

                <TresAmbientLight color="rgb(191,231,255)" :intensity="5" />
            </TresCanvas>
        </ClientOnly>
    </div>
</template>