import { Threebox, THREE } from "threebox-plugin";
import { Event, Evented } from "../../util/evented";
import Marker from "./marker";
import { loadObj, loadTexture } from "./utils";
import Popup from '../../ui/popup'

export default class ThreeBoxLayer extends Evented {
    constructor(map, renderTarget) {
        super();

        this.map = map;
        this.canvas = renderTarget;
        this.markerList = new Map();
        this.objectList = new Map();

        this.id = "threeBoxLayer";
        this.type = "custom";
        this.renderingMode = "3d";

        this.markerListenerAdded = false;
    }

    onAdd(map, gl) {
        this.map = map;
        window.tb = new Threebox(
            map,
            gl, //get the context from Mapbox
            { defaultLights: true,enableTooltips: true }
        );

        this.renderer = new THREE.WebGLRenderer({
            canvas: this.canvas,
            context: gl,
        });

        this.renderer.autoClear = false;
        this.fire(new Event("map.ready"));
    }

    addMarker(options, scale) {
        const id = options.id;
        if (!id) {
            throw new Error("请配置id!");
        }
        this.markerListenerAdded = false;
        
        const marker = new Marker(options, scale);
        this.markerList.set(marker.uuid, marker, this.map.getZoom());
    }

    async add3DModel(options) {
        const obj = await loadObj(options.url);
        const texture = await loadTexture(options.texture);
        const mesh = obj.children[0];
        mesh.material.map = texture;
        texture.needsUpdate = true;
        const body = tb
            .Object3D({
                obj: mesh,
                units: "meters",
            })
            .setCoords([...options.coord, options.height]);
        this.map.transform.maxZoom = options.scale;
        body.fixedZoom = true;
        body.setObjectScale(this.map.transform.scale);
        tb.add(body);
    }

    

    render(gl, matrix) {
        if(this.map.destroyed) return
        
        this.fire(new Event("three.render"));
        this.addMarkerListeners();
        tb.update();
        this.updateMarker();
    }

    updateMarker() {
        let willRepaint = false;
        const curZoom = this.map.getZoom();
        for (const uuid of this.markerList.keys()) {
            const marker = this.markerList.get(uuid);
            marker.updateScale(parseInt(curZoom));
            if (marker.hasAnimatingTexture) {
                willRepaint = true;
                marker.updateTexture();
            }
        }
        return willRepaint;
    }

    addMarkerListeners() {
        if (this.markerListenerAdded) return;
        this.markerListenerAdded = true;
        for (const uuid of this.markerList.keys()) {
            const marker = this.markerList.get(uuid);
            if (!marker.addListeners()) this.markerListenerAdded = false;
        }
    }
}
