Source: package/mesh/mesh_group.js

import { Group } from '../../../node_modules/three/build/three.module.js';
import { Reporter } from '../../reporter/reporter.js';
import { checkPropTypes } from '../../lib.js';
import { BuildableComponent } from '../component/buildable_component.js';
import { PositionedMesh } from './positioned_mesh.js';
import { MaterialSet } from '../material/material_set.js';
import { Project } from '../../project.js';


/**
 * Group of objects that are covariant within the same material variant group.
 */

class MeshGroup extends BuildableComponent {

    /** 
     * @param {Reporter} reporter
     * @param {Object} settings
     * @param {UUID} [settings.id]
     * @param {string} [settings.name]
     * @param {Array<PositionedMesh>} settings.positionedMeshes
     * @param {Array<MaterialSet>} [settings.assignable]
     */

    constructor(reporter, settings) {

        super(
            reporter,
            settings,
            {
                parse: {
                    positionedMeshes: 'integral'
                }
            }
        );

        // console.log( settings )

        checkPropTypes(
            settings,
            {
                positionedMeshes: [
                    {
                        test: val => Array.isArray(val),
                        msg: 'Value is not an array'

                    },
                    {
                        test: val => val.every(m => m instanceof PositionedMesh),
                        msg: 'Array element is not a PositionedMesh'
                    }
                ]
                // val.every(em =>
                //     em.position instanceof Vector3 &&
                //     em.quaternion instanceof Quaternion &&
                //     em.mesh instanceof WrappedMesh
                // )
            },
            {}
        );

        this.subAssignables = settings.positionedMeshes.filter( pm => pm.assignable === true );
    }

    static _exportName = {
        singular: 'meshGroup',
        plural: 'meshGroups'
    };


    /**
     * @param {ComponentPart} part 
     * @param {LoadingQuality} quality 
     * @param {Object<string,any>} dependencies
     */

    async _build(part, quality, dependencies) {

        this._status[part][quality].setState('loading');

        switch (part) {

            case 'UI':

                if (this._settings.thumbnail) {
                    this._setContent('UI', quality, this._settings.thumbnail.content.main[quality]);
                }
                else {
                    this._setContent('UI', quality, Project.defaultImages.missing.cloneNode(true));
                }
                break;

            case 'main':

                /** @type {Array<PositionedMesh>} */

                const positionedMeshes = Object.values(this._settings.positionedMeshes);

                if (this._debug) {
                    console.log(positionedMeshes)
                    // console.log( dependencies )
                }


                /** @type {THREE.Group} */

                const group = new Group();

                // clone and add the wrapped THREE.Meshes to the group
                // and position correcty

                for (let positionedMesh of positionedMeshes) {

                    /** @type {THREE.Mesh} */

                    const posMeshClone = positionedMesh.content.main[quality].clone();

                    group.add( posMeshClone );

                    group.castShadow = true;
                    group.receiveShadow = true;

                    // posMeshClone.position.set( 
                    //     positionedMesh.position.x,
                    //     positionedMesh.position.y,
                    //     positionedMesh.position.z,
                    // );

                    // posMeshClone.quaternion.set( 
                    //     positionedMesh.quaternion.w,
                    //     positionedMesh.quaternion.x,
                    //     positionedMesh.quaternion.y,
                    //     positionedMesh.quaternion.z,
                    // );
                    
                }

                this._setContent('main', quality, group);

                break;
                
            default:

                this._setContent(part, quality, null);
                
                break;
        }

        return this;
    }
}

export { MeshGroup };