Source: filter/mapviewer-filter.js

/* eslint-disable no-case-declarations */
/* eslint vars-on-top: 0, newline-after-var: 0, consistent-return:0, no-throw-literal:0 */

import Collection from 'ol/Collection'
import { asArray } from 'ol/color'

import Colorize from 'ol-ext/filter/Colorize'
import Texture from 'ol-ext/filter/Texture'
import Fold from 'ol-ext/filter/Fold'

/**
 * Module de gestion des filtres de carte
 * @module filter
 */
const libNamespace = 'filter'

const PRESET = {
  grayscale: { operation: 'hue', color: [0, 0, 0, 1] },
  invert: { operation: 'difference', color: [255, 255, 255, 1] },
  sepia: { operation: 'color', color: [153, 102, 51, 0.6] },
}

class Filter {
  constructor (viewer, options) {
    viewer.FILTER_LOADED = true
    this.ctx = viewer
    // Collection des filtres sur la carte
    this.filters_ = new Collection([], true)
    this.customTexture_ = {}
    this.customPreset_ = {}

    Object.assign(this, options)
  }

  getFilter_ (id) {
    return this.filters_.getArray().find(item => item.get('id') === id)
  }

  getFiltersId () {
    return this.filters_.getArray().map(item => item.get('id'))
  }

  filterExist (id) {
    return !!this.getFilter_(id)
  }

  getTexture_ (name) {
    // TODO Vérifier l'obtention de Texture[name]
    console.log('GET TEXTURE', name)
    return this.customTexture_[name] || name
  }

  getPreset_ (name) {
    return this.customPreset_[name] || PRESET[name]
  }

  addFilter (backgroundLayerId, id, options) {
    console.log('ADD FILTER', { id, options })
    options = options || {}
    let filter

    if (this.filterExist(id)) {
      return false
    }

    switch (options.type) {
      case 'colorize':
        filter = new Colorize()
        break
      case 'texture':
        filter = new Texture()
        break
      case 'fold':
        filter = new Fold()
        break
      default:
        return false
    }

    filter.set('id', id)
    filter.set('type', options.type)
    filter.set('backgroundLayerId', backgroundLayerId)

    this.filters_.push(filter)

    const bgLayer = this.ctx.commonLayer.getLayer(backgroundLayerId)
    if (bgLayer) {
      bgLayer.addFilter(filter)
    }

    this.setFilter(backgroundLayerId, id, options)
  }

  removeFilter (backgroundLayerId, id) {
    const filter = this.getFilter_(id)
    backgroundLayerId = backgroundLayerId || filter.get('backgroundLayerId')
    const bgLayer = this.ctx.commonLayer.getLayer(backgroundLayerId)
    if (filter && bgLayer) {
      bgLayer.removeFilter(filter)
      this.filters_.remove(filter)
    }
  }

  setFilter (backgroundLayerId, id, options) {
    options = options || {}
    const filter = this.getFilter_(id)
    console.log('SET FILTER', { id, options })
    if (filter) {
      // si on fait un setfilter d'un filter existant mais non présent sur le calque demandé, on l'ajoute au calque
      // exemple analyse supprime le background a chaque maj de filter
      backgroundLayerId = backgroundLayerId || filter.get('backgroundLayerId')
      const bgLayer = this.ctx.commonLayer.getLayer(backgroundLayerId)
      if (bgLayer && !bgLayer.getFilters().find((bgFilter) => bgFilter.get('id') === filter.get('id'))) {
        bgLayer.addFilter(filter)
      }

      switch (filter.get('type')) {
        case 'fold':
          if (options.fold === false) {
            filter.set('active', false)
            break
          }
          Object.keys(options).forEach(key => {
            if (['fold', 'margin', 'padding', 'fsize'].includes(key)) {
              filter.set(key, options[key])
            }
          })
          filter.set('active', true)
          break
        case 'texture':
          const opacity = typeof options.opacity === 'number'
            ? options.opacity
            : filter.get('opacity')

          const src = options.texture

          // ndhe: a priori on ne pouvait pas enlever un effet de texture vu qu'on prenait soit le nouveau, soit l'existant..
          // je laisse en commentaire au cas ou ce soit le comportement voulu et que j'ai introduit un bug..
          // const src = this.getTexture_(options.texture || filter.get('texture'))

          if (src) {
            filter.setFilter({ src, opacity, rotateWithView: true })
            // filter.set('texture',  || filter.get('texture'))
            filter.set('texture', options.texture)
            filter.set('active', true)
          } else {
            filter.set('active', false)
          }
          break
        case 'colorize':
          if (options.preset) {
            options = this.getPreset_(options.preset)
          }

          if (options && options.color) {
            options.color = typeof options.color === 'string'
              ? asArray(options.color)
              : options.color

            options.color[3] = typeof options.intensity === 'number'
              ? options.intensity
              : options.color[3]

            filter.setFilter({
              operation: options.operation,
              color: options.color,
              value: options.color[3],
            })
            filter.set('active', true)
          } else {
            filter.set('active', false)
          }
          break
      }
    }
  }
}

// Permet d'etendre le module
export default function extendCoreLib (options) {
  return function patch (viewer) {
    const functions = { }

    functions[libNamespace] = new Filter(viewer, options)
    return Object.assign(viewer, functions)
  }
}