Source: ol/style/IconLib.js

/**
 * @module nyc/ol/style/IconLib
 */

import $ from 'jquery'
import Style from 'ol/style/Style'
import Icon from 'ol/style/Icon'
import EventHandling from 'nyc/EventHandling'


/**
 * @desc Class to load icons from a library
 * @public
 * @class
 */
class IconLib extends EventHandling {
  /**
   * @desc Create an instance of IconLib
   * @public
   * @constructor
   * @param {url=} url The URL to the icon library
   */
  constructor(url) {
    super()
    this.url = url || IconLib.URL
    this.svg = {}
    this.icons = {}
  }
  /**
   * @private
   * @method
   * @param {module:nyc/ol/style/IconLib~IconLib.StyleOptions} options The icon style options
   * @returns {module:nyc/ol/style/IconLib~IconLib.Icon} The icon
   */
  parseIcon(options) {
    const icon = options.icon
    if (typeof icon === 'string') {
      const ico = icon.split('#')[0]
      return {
        library: ico.split('/')[0],
        name: ico.split('/')[1],
        fill: options.fill || `#${icon.split('#')[1]}`,
        stroke: options.stroke
      }
    }
    return icon
  }
  /**
   * @desc Create an icon style
   * @public
   * @method
   * @param {module:nyc/ol/style/IconLib~IconLib.Icon} options The style options
   * @param {ol.style.Style=} style The style on which to set the icon image
   * @return {ol.style.Style} The icon style
   */
  style(options, style) {
    const ico = this.parseIcon(options)
    const prefix = IconLib.LIBRARIES[ico.library].prefix
    const suffix = IconLib.LIBRARIES[ico.library].suffix
    const url = `${this.url}/${ico.library}/${prefix}${ico.name}${suffix}.svg`
    const svg = this.svg[url]
    style = style || new Style({})
    if (!svg) {
      fetch(url).then(response => {
        if (response.ok) {
          response.text().then(txt => {
            this.svg[url] = $(txt)[2]
            this.style(options, style)
            this.trigger('icon-loaded', style)
          })
        } else {
          this.svg[url] = IconLib.NOT_FOUND_ICON.svg
          this.style(options, style)
          console.error('Icon not found', url)
          this.trigger('icon-not-found', this)
        }
      })
    } else {
      const key = `${ico.library}-${ico.name}-${ico.fill}`
      let scale = options.width / IconLib.LIBRARIES[ico.library].width
      if (svg === IconLib.NOT_FOUND_ICON.svg) {
        scale = options.width / IconLib.NOT_FOUND_ICON.width
      }
      if (!this.icons[key]) {
        const div = $('<div></div>').html(svg)
        if (svg !== IconLib.NOT_FOUND_ICON.svg) {
          const stroke = ico.stroke
          const css = div.find('svg').attr('style') || ''
          let cssAdd = `fill:${ico.fill}`
          if (stroke) {
            cssAdd = `${cssAdd};stroke-width:${stroke.width};stroke:${stroke.color}`
          }
          div.find('svg').attr('style', `${css};${cssAdd}`)
        }
        this.icons[key] = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(div.html())}`
      }
      style.setImage(new Icon({src: this.icons[key], scale}))
    }
    return style
  }
}

/**
 * @desc Icon definition object
 * @public
 * @typedef {Object}
 * @property {string} library The icon library
 * @property {string} name The icon name
 * @property {string} fill The icon fill color
 * @property {module:nyc/ol/style/IconLib~IconLib.Stroke} stroke The icon stroke
 */
IconLib.Icon

/**
 * @desc Icon definition object
 * @public
 * @typedef {Object}
 * @property {number} width The width
 * @property {string} color The stroke color
 */
IconLib.Stroke

/**
 * @private
 * @const
 * @type {string}
 */
IconLib.URL = 'https://maps.nyc.gov/nyc-lib/icons'

/**
 * @public
 * @const
 * @type {string}
 */
IconLib.LIBRARIES = {
  'mapbox-maki': {
    width: 15,
    prefix: '',
    suffix: '-15'
  }
}

/**
 * @desc Default icon when requested icon is unavailable
 * @const
 * @type {Object}
 */
IconLib.NOT_FOUND_ICON = {
  svg: '<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32"><circle cx="16" cy="16" r="14" stroke="#000" stroke-width="2" fill="rgba(0,0,0,.5)" /></svg>',
  width: 32
}

/**
 * @desc Option for {@link module:nyc/ol/style/IconLib~IconLib#style}
 * @public
 * @typedef {Object}
 * @property {string|module:nyc/ol/style/IconLib~IconLib.Icon} icon The icon
 * @property {number} width The icon width
 * @property {string=} fill An override color for the icon
 * @property {module:nyc/ol/style/IconLib~IconLib.Stroke=} stroke An override color for the stroke
 */
IconLib.StyleOptions

export default IconLib