Source: public/javascript/modules/olqv_shapes.js

import {getProjection} from "./olqv_projections.js";
import { FITS_HEADER } from "./fitsheader.js";
import {highlightedFeature, standardFeature} from "./olqv_shapestyle.js";

/**
 * @classdesc A super class of classes acting as factories of graphic objects
 * such as boxes, markers, contours.
 * 
 * 
 * A constructor of this class is meant to be called *exclusively* by a constructor of one of its subclasses and never directly by the end user. 
 */

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

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

    /**
     * @class
     * @param {Viewer} viewer -  an instance of class Viewer
     * @param {string} title - a string describing the type of shape 
     */
    constructor(viewer, title) {
        ShapesFactory.enter(this.constructor.name);
        this.viewer = viewer;
        this.viewerId = viewer.getDivId();
        this.infosBlock = viewer.infosBlock;
        this.projection = getProjection(FITS_HEADER.projectionType);
        this.map = viewer.getMap();

        this.source = new ol.source.Vector();
        // this.factoryIndex = ShapesFactory.zindexes.length;
        /*
        ShapesFactory.zindexes.unshift(this.factoryIndex + 10); 
        ShapesFactory.layers.push(new ol.layer.Vector({ source: this.source, style: this.style_f, zIndex: ShapesFactory.zindexes[this.factoryIndex] }));
        */
        //this.map.addLayer(this.layer);
        //this.layer = new ol.layer.Vector({ source: this.source, style: this.style_f});
        this.layer = new ol.layer.Vector({ source: this.source, style: null });
        this.layer.set('title', title);
        this.viewer.addShapesLayer(this.layer);

        this.relFITSFilePath = viewer.getRelFITSFilePath();
        this.selector = viewer.getSelector();

        var target = this.map.getTarget();
        this.jTarget = typeof target === "string" ? $("#" + target) : $(target);

        this.visible = true;
        this.isOpened = false;

        this.overlay = null;
        this.container = document.getElementById('popup');
        this.content = document.getElementById('popup-content');
        this.closer = document.getElementById('popup-closer');

        this.highlightstyle_f = (feature) => {
            return highlightedFeature(feature);
        };

        this.style_f = (feature) => {
            return standardFeature(feature);
        };

        this._mode = "undefined";
        console.log("done");
        ShapesFactory.exit();
    }

    /**
     * A mutator defining the kind of subclass.
     * 
     * @param s - an instance of an object created by a subclass (e.g. an object created by a MarkerFactory)
     */
    set mode(s) {
        var name = s.constructor.name;
        if (name.endsWith("Factory")) {
            name = name.substring(0, name.length - 7);
        }
        this._mode = name;
    }

    /**
     * A getter to obtain the kind of object created by a subclass.
     * 
     * @returns a string
     */
    get mode() { return this._mode; }

    /* get layer() { return ShapesFactory.layers[this.factoryIndex]; }*/

    /**
     * Make this factory active.
     * 
     * Displays a cursor ( expectedly characteristic of the factory subclass ) and define
     * the interaction in use as long as it's active.
     * 
     * @see {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_interaction_Interaction-Interaction.html} 
     * 
     * 
     * @param interaction - Interaction in the OpenLayers meaning 
     * @param {string} cursor - A name picked in the standard CSS - Cursors list
     */
    open(interaction, cursor) {
        ShapesFactory.enter(this.open.name);

        // Is 'Selection' the current mode ? Then close it
        if (this.viewer.currentInteraction == this.selector.interaction) { this.selector.close(); }

        // If we are playing with Shapes and are we opening a factory different than the current one
        // then start by closing the current one.
        if (ShapesFactory.currentShapesFactory && ShapesFactory.currentShapesFactory != this) {
            ShapesFactory.currentShapesFactory.close();
        }

        // 
        // And then install the selected factory
        ShapesFactory.currentShapesFactory = this;
        this.viewer.setCurrentInteraction(interaction, cursor);
        if (this.viewer.hasMouse) {
            this.viewer.startCurrentInteraction();
        }
        this.isOpened = true;
        this.infosBlock.setMode(this.mode);
        ShapesFactory.exit();
    }

    /**
     * @description Close this factory. Disable its interaction processor.
     */
    close() {
        ShapesFactory.enter(this.close.name);
        this.infosBlock.clear();
        this.viewer.removeCurrentInteraction();
        this.isOpened = false;
        ShapesFactory.exit();
    }

    /**
     * @description Modify the look of {@link feature} to show that it's been selected. ( e.g. highlite it )
     * @param feature - An instance created by a subclass 
     */
    selected(feature) {
        ShapesFactory.enter(this.selected.name);
        feature.setStyle(new ol.style.Style());
        feature.setStyle(this.highlightstyle_f(feature));
        ShapesFactory.exit();
    }

     /**
     * @description Modify the look of {@link feature} to show that it's been unselected. ( e.g. display it normally )
     * @param feature - an instance created by a subclass.
     */
    unselected(feature) {
        ShapesFactory.enter(this.unselected.name);
        feature.setStyle(this.style_f(feature));
        ShapesFactory.exit();
    }

    highlight(feature) {
        ShapesFactory.enter(this.highlight.name);
        feature.setStyle(this.highlightstyle_f(feature));
        ShapesFactory.exit();
    }

    /**
     * @description Hide all the objects created by one subclass. (e.g. all the markers)
     */
    hide() {
        ShapesFactory.enter(this.hide.name);
        this.layer.setVisible(false);
        ShapesFactory.exit();
    }

    /**
     * @description Make visible all the objects created by one subclass. (e.g. all the markers)
     */
    show() {
        ShapesFactory.enter(this.show.name);
        this.layer.setVisible(true);
        ShapesFactory.exit();
    }

    clear() {
        ShapesFactory.enter(this.clear.name);
        if (this.lastSelectedContour) this.lastSelectedContour.setStyle(undefined);
        this.lastSelectedContour = null;
        this.source.clear();
        ShapesFactory.exit();
    }

    /**
     * @description Remove one object created by a subclass.
     * @param {*} feature the object to remove.
     */
    remove(feature) {
        ShapesFactory.enter(this.remove.name);
        this.unselected(feature);
        feature.setStyle(new ol.style.Style());
        this.source.removeFeature(feature);
        ShapesFactory.exit();
    }
} // end of class ShapesFactory

ShapesFactory.currentShapesFactory = undefined;

export{
    ShapesFactory
}