<template>
    <div class="mode">
        <canvas ref="canvas"></canvas>
    </div>
</template>

<script>
import { ref, onMounted, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
export default {
    props: {
        info: {
            type: Object,
            default: () => {
                return {};
            }
        },
        pageType: {
            type: String,
            default: 'product'
        }
    },
    data() {
        return {
            scene: null,
            light: null,
            camera: null,
            renderer: null,
            controls: null,
            mesh: null,
            angularSpeed: 0.2,
            lastTime: 0,
            farmeCount: 0
        };
    },
    setup(props) {
        const canvas = ref(null);
        const self = this;
        let destroy = false;
        onMounted(() => {
            console.log(canvas.value);
            let camera, scene, renderer, stats;
            const dev = /test/.test(location.href) || /192\.168/.test(location.href);
            const clock = new THREE.Clock();

            let mixer;

            init();
            animate();

            function init() {
                camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerWidth, 1, 20000);
                camera.position.set(0, 0, 600);

                scene = new THREE.Scene();
                // scene.background = new THREE.Color(0xa0a0a0);

                const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
                hemiLight.position.set(0, 200, 0);
                scene.add(hemiLight);

                const dirLight = new THREE.DirectionalLight(0x00ffffff);
                dirLight.position.set(0, 200, 100);
                dirLight.castShadow = true;
                dirLight.shadow.camera.top = 180;
                dirLight.shadow.camera.bottom = -100;
                dirLight.shadow.camera.left = -120;
                dirLight.shadow.camera.right = 120;
                scene.add(dirLight);

                // scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );

                // ground
                // const mesh = new THREE.Mesh(
                //     new THREE.PlaneGeometry(2000, 2000),
                //     new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false })
                // );
                // mesh.rotation.x = -Math.PI / 2;
                // mesh.receiveShadow = true;
                // scene.add(mesh);

                // const grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000);
                // grid.material.opacity = 0.2;
                // grid.material.transparent = true;
                // scene.add(grid);

                // model
                const loader = new FBXLoader();
                loader.load(props.info.url, function (object) {
                    let scale = Number(new URL(props.info.url).searchParams.get('scale') || '1');
                    let yOffset = Number(new URL(props.info.url).searchParams.get('yOffset') || '0');
                    const bounding = new THREE.Box3().setFromObject(object);

                    let size_x = Math.abs(bounding.max.x - bounding.min.x);
                    let size_y = Math.abs(bounding.max.y - bounding.min.y);
                    let size_z = Math.abs(bounding.max.z - bounding.min.z);

                    let center_x = (bounding.max.x + bounding.min.x) / 2;
                    let center_y = (bounding.max.y + bounding.min.y) / 2;
                    let center_z = (bounding.max.z + bounding.min.z) / 2;

                    console.log('model size: x=' + size_x + ', y=' + size_y + ', z=' + size_z);
                    let isY = size_y >= size_x;

                    camera.lookAt(new THREE.Vector3(center_x, center_y, center_z));
                    camera.position.set(center_x, center_y + yOffset, (isY ? size_y : size_x) * 1.8 * scale);
                    object.position.set(0, yOffset, 0);

                    hemiLight.position.set(0, center_y + size_y * 2, 0);
                    if (controls) {
                        controls.target.set(center_x, center_y, center_z);
                        controls.update();
                    }

                    mixer = new THREE.AnimationMixer(object);

                    if (object.animations && object.animations[0]) {
                        const action = mixer.clipAction(object.animations[0]);
                        action.play();
                    }

                    object.traverse(function (child) {
                        if (child.isMesh) {
                            child.castShadow = true;
                            child.receiveShadow = true;
                        }
                    });
                    scene.add(object);
                });

                renderer = new THREE.WebGLRenderer({ canvas: canvas.value, antialias: true, alpha: true });
                renderer.setPixelRatio(window.devicePixelRatio);
                renderer.setSize(window.innerWidth, window.innerWidth);
                renderer.shadowMap.enabled = true;

                let controls = null;
                controls = new OrbitControls(camera, renderer.domElement);
                controls.target.set(0, 150, 0);
                controls.enableZoom = dev;
                controls.enablePan = dev;
                controls.enabled = dev ? true : props.pageType === 'asset';
                controls.update();

                window.addEventListener('resize', onWindowResize);

                // stats
            }

            function onWindowResize() {
                camera.aspect = window.innerWidth / window.innerWidth;
                camera.updateProjectionMatrix();

                renderer.setSize(window.innerWidth, window.innerWidth);
            }

            //

            function animate() {
                if (destroy) return;
                requestAnimationFrame(animate);

                const delta = clock.getDelta();

                if (mixer) mixer.update(delta);

                renderer.render(scene, camera);
            }
        });
        onBeforeUnmount(() => {
            destroy = true;
        });
        return {
            canvas
        };
    },
    mounted() {}
};
</script>

<style lang="less" scoped>
.mode {
    canvas {
        width: calc(100vw - 50px) !important;
        height: calc(100vw - 50px) !important;
        // height: 100vw -150px;
    }
}
</style>
