import * as THREE from 'three';
import * as OBC from 'openbim-components';
import * as OBF from '@thatopen/components-front';
import * as WEBIFC from 'web-ifc';

/**
 * @namespace BIM
 */
const BIM = {};

/**
 * 
 * @param {HTMLElement} container The scene container element
 * @returns {object} {components, world}
 */
BIM.init = function (container) {
    const components = new OBC.Components();
    const worlds = components.get(OBC.Worlds);

    const world = worlds.create();
    
    world.scene = new OBC.SimpleScene(components);
    world.renderer = new OBC.SimpleRenderer(components, container);
    world.camera = new OBC.SimpleCamera(components);

    // Starts the app and updates components at 60 fps
    components.init();
    this.world = world;
    this.components = components;
}
/**
 * @param {HTMLElement} container The scene container element
 * @returns {OBC.Components}
 */
BIM.createScene = function (container) {
    this.init(container);

    this.world.scene.setup();
    // Add a grid to the scene
    const grids = this.components.get(OBC.Grids);
    const grid = grids.create(this.world);
    // (zoom_level, position)
    this.world.camera.controls.setLookAt(15, 15, 15, 0, 0, 0);
}
/**
 * @todo Serve web-ifc.wasm locally via AJAX
 * @param {ArrayBuffer} buffer The uploaded IFC file 
 * @param {string} name The filename to be used as the model's name
 * @returns {OBC.FragmentsGroup} model
 */
BIM.loadIfc = async function (buffer, name) {
    if (this.fragments) {
        this.fragments.dispose();
    }

    const fragments = this.components.get(OBC.FragmentsManager);

    const fragmentIfcLoader = this.components.get(OBC.IfcLoader);
    // NOTE: loads web-ifc WASM from https://unpkg.com/web-ifc@0.0.53/
    //await fragmentIfcLoader.setup();
    fragmentIfcLoader.settings.wasm = {
      path: "./vendor/web-ifc/",
      absolute: false
    };
    // Excludes IFC categories from the fragment
    const excludedCats = [
        WEBIFC.IFCTENDONANCHOR,
        WEBIFC.IFCREINFORCINGBAR,
        WEBIFC.IFCREINFORCINGELEMENT,
    ];

    for (const cat of excludedCats) {
        fragmentIfcLoader.settings.excludedCategories.add(cat);
    }

    fragmentIfcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
    fragmentIfcLoader.settings.webIfc.OPTIMIZE_PROFILES = true;

    const model = await fragmentIfcLoader.load(buffer);
    model.name = name;
    this.world.scene.three.add(model);

    // Useful?
    this.fragments = fragments;
    this.model = model;

    return model;
}

/**
 * @param {OBC.FragmentsGroup} model The loaded IFC model
 */
BIM.setupHighligther = async function (model) {
    const world = this.world;
    const indexer = this.components.get(OBC.IfcRelationsIndexer);
    await indexer.process(model);

    let highlighter = null;

    if (!this.highlighter) {
        highlighter = this.components.get(OBF.Highlighter);
        highlighter.setup({ world });
    } else {
        highlighter = this.highlighter;
    }

    const li = document.querySelector('#selected-prop');
    highlighter.events.select.onHighlight.add(async (property) => {
        const set = property[Object.keys(property)[0]]
        const expressID = Array.from(set.entries())[0][0];
        
        let testProp = await model.getProperties(Number.parseInt(expressID)); 

        // BAD just for testing
        if (testProp !== null) {
            li.innerHTML = `
                <ul>
                    <li><strong>Name</strong>: ${testProp['Name'].value}</span>
                    <li><strong>Tag</strong>: ${testProp['Tag'].value}</li>
                </ul>
            `;
        }
    });

    highlighter.events.select.onClear.add(() => {
        li.innerHTML = '';
    });

    this.highlighter = highlighter;
}

export default BIM;