// Global ATON

import AppState from "./state.js";
import { config } from "../config.js";
import { toggleAmbientOcclusion } from "./utils/environment.js";

/**
 * @module Scene
 */

/**
 * @todo Experimental...
 * @param {THREE.Object3D} object - A THREE Object3D instance
 */
function showEdges (object) {
    const edgeMaterial = new THREE.LineBasicMaterial( { color: 0x000000 } );

    object.traverse(function(child) {
    
        if (child.isMesh) {
            let edges = new THREE.EdgesGeometry(child.geometry, 45);
            let line = new THREE.LineSegments(edges, edgeMaterial);
            child.add(line);
        
            console.log(child);
        }
    });
}

function init () {
    ATON.realize();
    ATON.UI.addBasicEvents();
    ATON.UI.init();
    // All assets for this app are stored here
    ATON.setPathCollection('/a/scaenae/assets/');
    // Initial light direction
    ATON.setMainLightDirection(new THREE.Vector3(...config.scene.initLightDir));
    ATON.toggleShadows(config.scene.shadows);
    ATON.setExposure(config.scene.initialExposure);

    AppState.camera = ATON.Nav._camera;
    AppState.renderer = ATON._renderer;
    AppState.shadows = config.scene.shadows;
    AppState.lightDirection = ATON.getMainLightDirection();
    AppState.exposure = config.scene.initialExposure;

    ATON.Nav.setUserControl(true);
    // Avoid semantic occlusion
    ATON._bQuerySemOcclusion = false;
}
/**
 * @param {Object} marker - The marker object from config
 * @param {Object[]} nodes - The flat list of nodes for this scene
 */
export function openScene (marker, nodes) {
    init();
    // Filter nodes with models first
    nodes = nodes.filter(n => n.model);
    // Load 3D models and create nodes
    loadNodes(nodes);

    ATON.setMainPanorama(marker.pano);
    // TODO: hardcoded...
    AppState.initialRotation = new THREE.Vector3(...config.scene.initRotation);

    ATON.setAutoLP(config.scene.autoLP);
    AppState.lightProbe = config.scene.autoLP;
    toggleAmbientOcclusion(config.scene.ambientOcclusion);
    AppState.ambientOcclusion = config.scene.ambientOcclusion;
    AppState.root = ATON.getRootScene();
}

/**
 * 
 * @param {Object[]} nodes 
 */
function loadNodes(nodes) {
    nodes.forEach(n => {
        let node = ATON.createSceneNode(n.label);
        node.load(n.model);
        node.setRotation(...config.scene.initRotation);

        /*
        node.setMaterial(new THREE.MeshPhongMaterial({
            transparent: false,
            color: n.color ?? '#fff',
        }));
        */

        // Apply any transparency before attaching to scene
        if (n.opacity !== undefined && n.opacity !== null) {
            node.setMaterial(new THREE.MeshPhongMaterial({
                transparent: true,
                opacity: n.opacity,
                color: '#fff'
            }));
        }

        // Disable a node for picking (shadows, light probe etc.)
        if (n.isInvisible) node.hide();

        node.attachToRoot();

        if (n.isMain) {
            AppState.mainNodeId = n.label;
            // ATON.Node.getBound() returns a THREE.Sphere object
            AppState.clipping.boundingSphere = node.getBound();
        }

        if (n.isSemantic) {
            createSemanticNode(n.model, n.label);
            AppState.semanticNodes.set(n.label, n.content);
            //ATON.getSemanticRoot().attach(semNode);
        }

        AppState.nodes.push({
            id: n.label,
            active: n.isInvisible ? false: true,
            isSemantic: n.isSemantic
        });
    });
    
    if (!AppState.clipping.boundingSphere) {
        console.error("No bounding sphere computed, clipping will fail. Ensure one node has 'isMain: true'.");
    }
}
/**
 * Creates a semantic annotation from a model
 * @param {string} model The model's path to load
 * @param {string} id The original scene node ID (3D object)
 * @returns {ATON.SceneNode}
 */
function createSemanticNode(model, id) {
    // Default/highlight materials for semantic node
    let matSemDef = new THREE.MeshStandardMaterial({
        color: '#f7e6af',
        transparent: true,
        opacity: 0.2,
    });
    let matSemHL  = ATON.MatHub.materials.semanticShapeHL;

    const semNode = ATON.createSemanticNode(id)
        .setCloneOnLoadHit(false)
        .load(model)
        .setDefaultAndHighlightMaterials(matSemDef, matSemHL)
        .attachToRoot();
    
    semNode.setRotation(...config.scene.initRotation);

    return semNode;
}
