Source: layers/graphic.js

let AbstractLayer = require('./abstract');

let ol = require('openlayers');
let identifyResult = require('../../modules/tasks/identifyResult');
let searchResult = require('../../modules/tasks/searchResult');
let fuse = require('fuse.js');

/**
 * Класс GraphicLayer
 * @extends AbstractLayer
 */
class GraphicLayer extends AbstractLayer {
    /**
     * @param params
     * @param params.url - адрес геосервера
     * @param params.className - имя слоя
     * @returns {ol.layer.Vector}
     */
    constructor(params) {
        super(params);
        this.initStore(params);
    }

    /**
     * @param params
     * @param params.className - имя класса
     * @param params.mappings - объект, содержащий трансляцию полей (подстановка)
     */
    initStore(params) {
        this.store = {};
        this.store.id = params.id;
        this.store.className = params.className;
        this.store.alias = params.alias;
        this.store.layerType = "opengis.layers.vector";
        this.store.mappings = params.mappings || {};
        this.layer = create(params);
        this.store.layer = this.layer;
        this.store.source = this.layer.getSource();
    }

    identify(params) {
        let geometry = params.geometry || params.coordinate;
        let radius = params.radius || 20;
        let extent = [geometry[0] - radius, geometry[1] - radius, geometry[0] + radius, geometry[1] + radius];
        let store = this.store;
        let source = store.layer.getSource();

        let features = source.getFeaturesInExtent(extent);
        features = features.map(function (item) {
            let featureAttributes = item.getProperties();
            let featureGeometry = item.getGeometry();
            delete featureAttributes.geometry;

            let resultAttributes = generateField(featureAttributes, store);

            return new identifyResult({
                layerId: store.id,
                layerName: store.alias,
                queryGeometry: geometry,
                attributes: featureAttributes,
                preparedAttributes: resultAttributes,
                geometry: featureGeometry,
                dirtyData: item
            });
        });
        return features;
    }

    query(params) {
    }

    setStyle(style) {
        this.layer.setStyle(style.getStyle());
    }

    snap() {

    }

    setDefaultStyle() {
        let style = new ol.styles.Style({
            image: new ol.styles.Circle({
                radius: 5,
                snapToPixel: false,
                stroke: new ol.styles.Stroke({
                    color: 'rgba(255, 0, 0, ' + 1 + ')',
                    width: 1
                })
            })
        });
        this.layer.setStyle(style);
    }

    setOptions() {

    }

    add(params) {
        let source = this.store.layer.getSource();
        source.addFeature(params.feature);
    }

    addGeometry(params) {
        let source = this.store.layer.getSource();
        let feature = new ol.Feature({
            geometry: params.geometry,
            id: Math.round(Math.random()*10000000)
        });
        source.addFeature(feature);
    }

    addPoint(params) {
        let source = this.store.layer.getSource();
        let transform = params.transform;
        let sourceGeometry = params.geometry;
        let properties = params.properties || {};
        let geometry = transform === undefined ? new ol.geom.Point(sourceGeometry) : new ol.geom.Point(ol.proj.transform(sourceGeometry, transform.source, transform.destination));
        let featureProperties = Object.assign({}, properties);
        featureProperties.geometry = geometry;
        let feature = new ol.Feature(featureProperties);
        source.addFeature(feature);
    }

    remove(feature) {

    }

    clear() {
        let source = this.layer.getSource();
        source.clear();
    }


    /**
     * Получить список объектов источника
     * @param params
     * @return {*|Array.<ol.Feature|ol.render.Feature>|ol.Collection.<ol.Feature>|Array.<ol.Feature>}
     */
    getFeatures(params) {
        return this.layer.getSource().getFeatures(params);
    }

    /**
     * Добавить объекты в источник
     * @param data
     */
    addFeatures(data) {
        this.layer.getSource().addFeatures(data);
    }

    /**
     * Удаление feature из источника
     * @param feature
     */
    removeFeature(feature) {
        this.layer.getSource().removeFeature(feature)
    }

    /**
     * Удаление feature из источника через указания свойства и значения
     * @param {object} params - параметры поиска
     * @param params.key {string} - имя свойства
     * @param params.value {string} - искомое значение
     */
    removeFeatureByProperty(params) {
        throw "this method is not implemented";
    }

    search(params) {
        let query = params.query;
        let layer = this.layer;
        let store = this.store;
        let source = layer.getSource();
        let features = source.getFeatures().map(function (item) {
            let result = item.getProperties();
            return result;
        });
        let keys = features.length > 0 ? Object.keys(features[0]) : {};
        let task = new fuse(features, {
            caseSensitive: true,
            includeScore: true,
            shouldSort: true,
            threshold: 0.2,
            minMatchCharLength: 1,
            keys: keys
        });
        let result = task.search(query);
        result = result.map(function (element) {
            let geometry = element.item.geometry;
            let resultAttributes = generateField(element.item, store);
            return new searchResult({
                layerId: store.id,
                layerName: store.alias,
                queryGeometry: geometry,
                attributes: element.item,
                preparedAttributes: resultAttributes,
                geometry: geometry,
                dirtyData: element.item,
                score: element.score
            })
        });
        return result;
    }
}

function create(params) {
    let source = new ol.source.Vector({
        wrapX: false
    });

    //создание векторного соля
    let layer = new ol.layer.Vector({
        source: source
    });

    return layer;
}

function generateEmptyMapping(name, value) {
    let mapping = {
        name: name,
        alias: name,
        group: "none",
        value: value
    };
    return mapping;
}

function generateField(featureAttributes, store) {
    let resultAttributes = [];
    for (let key in featureAttributes) {
        let localMapping = store.mappings[key] === undefined ? generateEmptyMapping(key, featureAttributes[key]) : store.mappings[key];
        resultAttributes.push({
            name: key,
            alias: localMapping.alias,
            group: localMapping.group,
            value: featureAttributes[key]
        });
    }
    return resultAttributes;
}

module.exports = GraphicLayer;