Source: sketchLayer/sketch-layer.js

/* eslint vars-on-top: 0, newline-after-var: 0, consistent-return:0, no-throw-literal:0, space-before-function-paren:0 */

import VectorLayer from 'ol/layer/Vector'
import VectorSource from 'ol/source/Vector'
import Collection from 'ol/Collection'
import Draw from 'ol/interaction/Draw'

import { Cross } from '../style-literal/'
import guid from '../utils/Guid'

/**
 * Module de gestion générique des couches
 * @module commonLayer
 */
const libNamespace = 'sketchLayer'

const SKETCH_LAYER_TYPE = 'sketch'
const SKETCH_MAP_MODE = 'sketch'

class SketchLayer {
  constructor (viewer, options) {
    viewer.SKETCH = true
    this.ctx = viewer

    // Paramètre du dessin à réaliser
    this.settings = {
      style: Cross(),
      type: 'Point',
      freehand: false,
    }

    this.layerId = 'sketchLayer'

    Object.assign(this, options)
  }

  _onSketchEnd ({ feature }) {
    // Applique un id unique sur la feature
    feature.setId(guid())

    // Force le style spécifique sur la feature
    const style = this.settings.style
    feature.setStyle((_feature, resolution) => {
      return typeof style === 'function'
        ? style(_feature, resolution)
        : style
    })

    // Lève un event avec la feature
    this.ctx.dispatchEvent('sketchEnd', { feature })
  }

  _createSketchInteraction() {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)
    const interaction = new Draw({ source, ...this.settings })
    interaction.on('drawend', event => this._onSketchEnd(event))
    return interaction
  }

  /**
   * Permet d'initialiser la couche de croquis
   *
   * @param {Object} options Options du layer
   * @param {Number} options.zIndex zIndex du layer
   */
  initSketchLayer (options = {}) {
    if (this.ctx.commonLayer.layerExist(this.layerId, SKETCH_LAYER_TYPE)) {
      this.ctx.commonLayer.removeMapMode(SKETCH_MAP_MODE)
      this.ctx.commonLayer.removeLayer(this.layerId, SKETCH_LAYER_TYPE)
    }

    const layer = new VectorLayer({
      [this.ctx.commonLayer.propertiesName.ID_LAYER]: options.layerId,
      source: new VectorSource({ features: new Collection() }),
      zIndex: options.zIndex,
      displayInLayerSwitcher: false,
    })
    this.ctx.commonLayer.addLayer(layer, SKETCH_LAYER_TYPE)
    this.layerId = options.layerId

    this.ctx.commonLayer.upsertMapMode({
      name: SKETCH_MAP_MODE,
      interactions: [this._createSketchInteraction()],
    })
  }

  changeSketchSettings({ style, type, freehand } = {}) {
    this.settings = {
      style: style || this.settings.style,
      type: type || this.settings.type,
      freehand: freehand !== undefined ? freehand : this.settings.freehand,
    }

    this.ctx.commonLayer.upsertMapMode({
      name: SKETCH_MAP_MODE,
      interactions: [this._createSketchInteraction()],
    })
  }

  addFeature (feature) {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)
    source.addFeature(feature)
  }

  /**
   * Permet de récupérer tous les croquis sous forme de features.
   * @return {Array<ol.Feature>} Tableau des croquis
   */
  getSketchFeatures () {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)

    if (source) {
      return source.getFeatures().slice()
    }
  }

  /**
   * Permet de supprimer le dernier croquis créé.
   */
  removeLastSketch () {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)

    if (source) {
      const collection = source.getFeaturesCollection()
      const length = collection.getLength()
      if (length) {
        this.ctx.dispatchEvent('sketchRemove', {
          feature: collection.item(length - 1),
        })

        collection.removeAt(length - 1)
      }
    }
  }

  /**
   * Permet de supprimer tous les croquis existants.
   */
  removeAllSketches () {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)

    if (source) {
      this.ctx.dispatchEvent('sketchRemoveAll', {
        features: this.getSketchFeatures(),
      })
      source.getFeaturesCollection().clear()
    }
  }

  clearSketches () {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)
    if (source) {
      source.clear()
    }
  }

  addFeatures (features) {
    const source = this.ctx.commonLayer.getSource(this.layerId, SKETCH_LAYER_TYPE)
    if (source) {
      features.forEach(feature => source.addFeature(feature))
    }
  }
}

// Permet d'etendre le module
export default function extendCoreLib (options) {
  return function patch (viewer) {
    viewer[libNamespace] = new SketchLayer(viewer, options)
    return viewer
  }
}