<template>
    <div class="c-shader" ref="container">
        <div class="camra-data">
            camera.position<br />
            x:{{ camera ? camera.position.x : "" }} <br />
            y:{{ camera ? camera.position.y : "" }} <br />
            z:{{ camera ? camera.position.z : "" }} <br />
        </div>
    </div>
</template>

<script>
import gsap from "gsap";
import * as THREE from "three";
import * as Stats from "stats.js";

import { TubePainter } from "three/examples/jsm/misc/TubePainter.js";
import { ARButton } from "three/examples/jsm/webxr/ARButton.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader.js";

export default {
    name: "color",
    props: {
        msg: String,
    },
    data() {
        return {
            remaining: 50,
            container: null,
            camera: null,
            scene: null,
            renderer: null,
            reticle: null,
            cursor: new THREE.Vector3(),
            hitTestSource: null,
            hitTestSourceRequested: false,
        };
    },
    created() {},
    mounted() {
        this.initStage();

        // 循环动画
        this.animate();
        // this.addAnimation();
    },
    methods: {
        initStage() {
            //基础参数
            this.container = this.$refs.container;
            this.camera = new THREE.PerspectiveCamera(
                70,
                window.innerWidth / window.innerHeight,
                0.01,
                5
            );
            this.scene = new THREE.Scene();

            // 定义 webglrender
            this.renderer = new THREE.WebGLRenderer({
                antialias: true,
                alpha: true,
            });
            this.renderer.setPixelRatio(window.devicePixelRatio);
            this.renderer.setSize(window.innerWidth, window.innerHeight);
            this.renderer.xr.enabled = true;
            if (!document.getElementById("webgl")) {
                this.renderer.domElement.id = "webgl";
                this.container.appendChild(this.renderer.domElement);
            }
            document.body.appendChild(
                ARButton.createButton(this.renderer, {
                    requiredFeatures: ["hit-test"],
                })
            );

            // 定义操控

            // 添加全局环境光
            const light = new THREE.HemisphereLight(0xffffff, 0xbbbbff, 1);
            light.position.set(0.5, 1, 0.25);
            this.scene.add(light);

            this.painter = new TubePainter();
            this.painter.setSize(0.4);
            // this.painter.mesh.material = new THREE.MeshLambertMaterial({
            // color: 0x0f19662,
            // });
            this.painter.mesh.material.side = THREE.DoubleSide;
            this.scene.add(this.painter.mesh);

            console.log(this.painter.mesh.material);

            setInterval(() => {
                this.painter.mesh.material.color.set(0xffffff * Math.random());
            }, 1000);

            // this.addPumpkin();

            let that = this;
            function onSelectEnd() {
                this.userData.isSelecting = false;
            }
            function onSelectStart() {
                that.startTime = new Date().getTime();
                this.userData.isSelecting = true;
                this.userData.skipFrames = 2;
            }

            this.controller = this.renderer.xr.getController(0);
            this.controller.addEventListener("select", () => {
                let moved = new Date().getTime() - that.startTime > 165;
                if (!moved) {
                    this.addPumpkin();
                }
            });
            this.controller.addEventListener("selectstart", onSelectStart);
            this.controller.addEventListener("selectend", onSelectEnd);
            this.controller.userData.skipFrames = 0;
            this.scene.add(this.controller);

            this.reticle = new THREE.Mesh(
                new THREE.RingGeometry(0.15, 0.2, 32).rotateX(-Math.PI / 2),
                new THREE.MeshBasicMaterial()
            );
            this.reticle.matrixAutoUpdate = false;
            this.reticle.visible = false;
            this.scene.add(this.reticle);
            // 自动缩放
            window.addEventListener("resize", this.onWindowResize);
            // this.onWindowResize();
        },
        addACyli() {
            if (this.reticle.visible) {
                const material = new THREE.MeshPhongMaterial({
                    color: 0xffffff * Math.random(),
                });
                const geometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    0.2,
                    32
                ).translate(0, 0.1, 0);
                const mesh = new THREE.Mesh(geometry, material);
                mesh.position.setFromMatrixPosition(this.reticle.matrix);
                mesh.scale.y = Math.random() * 2 + 1;
                this.scene.add(mesh);
            }
        },
        // 添加南瓜
        addPumpkin() {
            // const dracoLoader = new DRACOLoader();
            // dracoLoader.setDecoderPath("./");
            // dracoLoader.setDecoderConfig({ type: "js" });
            const loader = new GLTFLoader();
            // loader.setDRACOLoader(dracoLoader);
            loader.load(require("@/assets/model/pumpkin.gltf"), (gltf) => {
                console.log(gltf);
                gltf.scene.scale.set(0.1, 0.1, 0.1);
                // gltf.scene.rotation.y = Math.PI;

                gltf.scene.position.setFromMatrixPosition(this.reticle.matrix);
                // console.log(gltf.scene);
                this.scene.add(gltf.scene);
                gsap.to(gltf.scene.rotation, {
                    y: `+=${Math.PI * 2}`,
                    duration: 10,
                });
            });
        },
        handleController(controller) {
            const userData = controller.userData;

            this.cursor
                .set(0, 0, -0.2)
                .applyMatrix4(this.controller.matrixWorld);

            if (userData.isSelecting === true) {
                if (userData.skipFrames >= 0) {
                    // TODO(mrdoob) Revisit this

                    userData.skipFrames--;

                    this.painter.moveTo(this.cursor);
                } else {
                    this.painter.lineTo(this.cursor);
                    this.painter.update();
                }
            }
        },
        addCubes(controller) {
            this.group = new THREE.Group();
            // this.group.position.set(0, 0.1, 0);
            for (let i = 0; i < 10; i++) {
                const material = new THREE.MeshPhongMaterial({
                    color: 0x2399d3,
                });
                const geometry = new THREE.CylinderGeometry(
                    0.1,
                    0.1,
                    0.2,
                    32
                ).translate(0, 0.1, 0); //new THREE.BoxGeometry(1, 1, 1);
                const cube = new THREE.Mesh(geometry, material);
                cube.position.x = Math.random() * 4 - 2;
                cube.position.y = Math.random() * 4 - 2;
                cube.position.z = Math.random() * 4 - 2;
                cube.scale.set(0.5, 0.5, 0.5);
                // if (this.cursor)
                //     cube.position.setFromMatrixPosition(this.cursor.matrix);

                // cube.applyMatrix4(this.controller.matrixWorld);

                this.scene.add(cube);
            }
            // this.group.applyMatrix4(controller.matrixWorld);
            // this.scene.add(this.group);

            // setInterval(() => {
            //     console.log(this.camera.position);
            //     console.log(this.painter.mesh.position, 123);
            // }, 5000);
        },
        onWindowResize(event) {
            const width = window.innerWidth;
            const height = window.innerHeight;

            this.camera.aspect = width / height;
            this.camera.updateProjectionMatrix();

            this.renderer.setSize(width, height);
        },
        animate() {
            this.renderer.setAnimationLoop(this.render);
        },
        render(timestamp, frame) {
            this.handleController(this.controller);
            if (frame) {
                const referenceSpace = this.renderer.xr.getReferenceSpace();
                const session = this.renderer.xr.getSession();

                if (this.hitTestSourceRequested === false) {
                    session
                        .requestReferenceSpace("viewer")
                        .then((referenceSpace) => {
                            session
                                .requestHitTestSource({ space: referenceSpace })
                                .then((source) => {
                                    this.hitTestSource = source;
                                });
                        });

                    session.addEventListener("end", () => {
                        this.hitTestSourceRequested = false;
                        this.hitTestSource = null;
                    });

                    this.hitTestSourceRequested = true;
                }

                if (this.hitTestSource) {
                    const hitTestResults = frame.getHitTestResults(
                        this.hitTestSource
                    );

                    if (hitTestResults.length) {
                        const hit = hitTestResults[0];

                        this.reticle.visible = true;
                        this.reticle.matrix.fromArray(
                            hit.getPose(referenceSpace).transform.matrix
                        );
                    } else {
                        this.reticle.visible = false;
                    }
                }
            }

            this.renderer.render(this.scene, this.camera);
        },
        addAnimation() {
            // 自旋转
            gsap.to(this.group.rotation, {
                y: -Math.PI * 2,
                x: 0.1,
                duration: 5,
                // yoyo: true,
                // repeat: -1,
                onUpdate: () => {
                    // this.renderer.toneMappingExposure = Math.pow(
                    //     this.params.exposure,
                    //     4.0
                    // );
                    // this.render();
                    // console.log(this.params.scene);
                },
            });
        },
    },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="less">
.c-shader {
    width: 100vw;
    height: 100vh;
    position: relative;
    z-index: 0;
    .camra-data {
        display: none;
        .paLayout(0, 0, 150px, 80px, 10);
        background: rgba(255, 255, 255, 0.75);
        border-radius: 0 0 10px 0;
        color: #333;
        text-align: center;
        line-height: 20px;
    }
    .select-btn {
        // background-color: #fff;
        .paCenterBottom(2%,50%,auto,10);
    }
}
</style>
