Source: public/javascript/modules/olqv_selector.js

import {BoxesFactory} from "./olqv_boxes.js";
import {ShapesFactory} from "./olqv_shapes.js";
import {SelectorButton} from "./olqv_olbuttons.js";

/**
 * what happens when a box is translated
 * this is added to the Selector object in order to add
 * different translation to different objects if necessary
 */
let box2DTranslator = {
    setTranslateInteraction(boxFactory){
        const translate = new ol.interaction.Translate({
            features: this._interaction.getFeatures(),
        });
        this._viewer.map.addInteraction(translate); 
    
        translate.on('translateend', evt => {  
            evt.features.forEach(feat => {
                boxFactory.measure(feat, false);
            })
          })
    }
}

/**
 * what happens when a box is translated
 * this is added to the Selector object in order to add
 * different translation to different objects if necessary
 */
let box3DTranslator = {
    setTranslateInteraction(boxFactory){
        const translate = new ol.interaction.Translate({
            features: this._interaction.getFeatures(),
        });
        this._viewer.map.addInteraction(translate); 

        translate.on('translateend', evt => {  
            evt.features.forEach(feat => {
                boxFactory.selectAction(feat);
            })
          })
    }
}

class Selector {
    static enter(what) {
        console.group(this.name + "." + what);
    }

    static exit() {
        console.groupEnd();
    } 

    constructor(viewer) {
        Selector.enter(this.constructor.name);
        this._viewer = viewer;  
        /*
        ** One should be able to select one or many shape(s) with a [shift-key] click.
        */
        this._cursor = 'pointer';
        this._interaction = new ol.interaction.Select({ condition: ol.events.click, hitTolerance: 2 });
        this._interaction.on('select', event => {
            Selector.enter("### Select action");
            console.log(`${event.selected.length} features selected`);
            console.log(`${event.deselected.length} features deselected`);

            event.deselected.forEach((f) => {
                this.unselectAFeature(f);             
            });

            event.selected.forEach((f) => {
                this.selectAFeature(f);
            });

            /* If the click has selected NOTHING then unselect everything */
            if (event.selected.length === 0) {
                console.log("Nothing selected");
                this.unselectAll();
            }

            //viewer.getMap().addInteraction(this._interaction);
            Selector.exit();
        });

        this._selection = undefined;

        // An array containing all the selected features.
        this._selected = [];

        // A dictionary of actions to perform on selection based on the type of the selected feature
        this._select = {};

        // A dictionary of actions to perform on deselection based on the type of the deselected feature
        this._unselect = {};

        // A dictionary of actions to perform based on the type of the selected feature to remove
        this._remove = {}; 
        
        this._mode = 'Selection';

        this._opened = false;

        this._buttonObject = new SelectorButton(viewer);
        let self = this;
        let f = function () {  
            if (self._opened){
                self.close();
                self._buttonObject.unsetActive();
            } else{
                self.open();
                self._buttonObject.setActive();
            }
            console.warn(self._opened);
        };
        this._buttonObject.setClickAction(f);

        Selector.exit();
    }

    getButtonObject() {
        return this._buttonObject;
    }

    get mode() { return this._mode; }

    push(feature) {
        Selector.enter(this.push.name);
        if (this._selected.indexOf(feature) < 0) {
            this._selected.push(feature);
        }
        Selector.exit();
    }
    get interaction() { return this._interaction;}
    get cursor() { return this._cursor; }
    get remove() { return this._remove; }
    get select() { return this._select; }
    get unselect() { return this._unselect; }

    open() {
        Selector.enter(this.open.name);
        // If any factory is opened let's close it
        if (ShapesFactory.currentShapesFactory && ShapesFactory.currentShapesFactory != this) {
            ShapesFactory.currentShapesFactory.close();
            ShapesFactory.currentShapesFactory = undefined;
        }   
        
        if (this._viewer.currentInteraction == this._interaction) { this.close(); }

        this._viewer.setCurrentInteraction(this._interaction, this._cursor);
        this._viewer.startCurrentInteraction();
        this._viewer.infosBlock.setMode(this._mode);
        this._viewer.infosBlock.headline(">");
        this._viewer.infosBlock.shownAction = this.report.bind(this);
        this._opened = true;
        Selector.exit();
    };

    close() {
        Selector.enter(this.close.name);
        this._viewer.removeCurrentInteraction();
        this._opened = false;
        Selector.exit();
    }

    isOpened() { return this._opened; }

    removeSelection() {
        Selector.enter(this.removeSelection.name);
        this._selected.forEach((f) => {
            this.remove[f.getGeometry().getType()](f);
        });
        this._selected.length = 0;
        Selector.exit()
    }

    unselectAFeature(f) {
        Selector.enter(this.unselectAFeature.name);
        let featureType = f.getGeometry().getType();
        this._unselect[featureType](f);
        let selIndex = this._selected.indexOf(f);
        this._selected.splice(selIndex, 1);         
        Selector.exit();
    }

    unselectAll() {
        Selector.enter(this.unselectAll.name);
        this._selected.forEach((f) => {
            let featureType = f.getGeometry().getType();
            this._unselect[featureType](f);
        });
        this._selected.length = 0;
        Selector.exit();
    }

    selectAFeature(f) {
        Selector.enter(this.selectAFeature.name);
        let featureType = f.getGeometry().getType();
        this._selected.push(f);
        this._select[featureType](f);        
        Selector.exit();
    } 

    selectAll() {
        Selector.enter(this.selectAll.name);

        /*
        ** Retrieve all the features and select them
        */
        this._viewer.shapesLayerGroup.getLayers().forEach(layer => {
            if (layer.get('title') !== "contour") {
                layer.getSource().forEachFeature(f => {
                    if (this._selected.indexOf(f) < 0) {
                        this.selectAFeature(f);
                    }
                })
            }
        });
        Selector.exit();
    }

    report() {
        Selector.enter(this.report.name);
        let infosBlock = this._viewer.infosBlock;
        let context = infosBlock.getContext();
        let btype = context['array-phys-chars']['type'];
        let bunit = context['array-phys-chars']['unit'];
        let pixelValueColumnName = `${btype} (${bunit})`;

        infosBlock.populate("Selected objects");

        infosBlock.openSectionList();

        /* Markers */
        let markers = this._selected.filter(f => f.getGeometry().getType() === "Point");
        if (markers.length > 0) {
            infosBlock.section(`Markers`,markers.map((marker) => $.extend({"label":{"value":marker.get("label"), "unit": ""}}, marker.get("properties")["measurements"])));
        }

        /* Contours */
        let contours = this._selected.filter(f =>  f.getGeometry().getType() === "LineString" );
        if (contours.length > 0) {
            infosBlock.section(`Contours`,contours.map((contour) => $.extend({"level": contour.get("properties")["level"]}, contour.get("properties")["measurements"])));
        }

        /* Boxes */
        let boxes = this._selected.filter(f =>  f.getGeometry().getType() === "Polygon" );
        if (boxes.length > 0) {
            infosBlock.section(`Boxes`, boxes.map((box) => $.extend({ "label": { "value": box.get("label"), "unit": "" }}, box.get("properties")["measurements"])));
        }    
        Selector.exit();
    }
}

export{
    Selector,
    box2DTranslator,
    box3DTranslator,
}