Source: tools/services/styles-literal.js

import Fill from 'ol/style/Fill'
import Stroke from 'ol/style/Stroke'
import Text from 'ol/style/Text'
import Icon from 'ol/style/Icon'
import RegularShape from 'ol/style/RegularShape'
import Circle from 'ol/style/Circle'
import Style from 'ol/style/Style'

import * as olGeom from 'ol/geom'

import Chart from 'ol-ext/style/Chart'

// #region style Karteis Analyse

/**
 * Permet de convertir un objet litéral représentant un style
 * en objet ol.style.Style pour OpenLayers
 *
 * @param {Object} literalStyle Definition du style sous forme d'objet literal
 * @param {Object} literalStyle.fill Definition du remplissage sous forme literal {@link buildFillStyleFromLiteral}
 * @return {ol.style.Style} Style OpenLayers
 */
export function buildStyleFromLiteral ({ fill, stroke, text, icon, shape, circle, geometry, ...options }, buildOptions) {
  if (fill) {
    options.fill = buildFillStyleFromLiteral(fill)
  }

  if (stroke) {
    options.stroke = buildStrokeStyleFromLiteral(stroke)
  }

  if (text) {
    options.text = buildTextStyleFromLiteral(text)
  }

  if (icon) {
    options.image = buildIconStyleFromLiteral(icon)
  } else if (shape) {
    if (shape.type) {
      options.image = buildTypedShapeStyleFromLiteral(shape)
    } else {
      options.image = buildShapeStyleFromLiteral(shape)
    }
  } else if (circle) {
    options.image = buildCircleStyleFromLiteral(circle)
  }

  const skipGeometry = buildOptions && buildOptions.skip && buildOptions.skip.geometry
  if (geometry && !skipGeometry) {
    options.geometry = buildGeometryFromLiteral(geometry)
  }

  const style = new Style(options)
  return style
}

/**
 * Crée un style de remplissage
 * @param {Object} fill options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_Fill-Fill.html OpenLayer Fill}
 * @returns {ol.style.Fill}
 */
export function buildFillStyleFromLiteral (fill) {
  return new Fill(fill)
}

/**
 * Crée un style de ligne
 * @param {stroke} stroke options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_Stroke-Stroke.html OpenLayer Stroke}
 * @returns {ol.style.Stroke}
 */
export function buildStrokeStyleFromLiteral (stroke) {
  return new Stroke(stroke)
}

/**
 * Crée un style de texte
 * @param {Object} literalStyle
 * @param {Object} literalStyle.stroke bordure du texte, options style de ligne calqués sur {@link buildStrokeStyleFromLiteral}
 * @param {Object} literalStyle.fill couleur du texte, options style de remplissage calqués sur {@link buildFillStyleFromLiteral}
 * @param {Object} literalStyle.backgroundStroke boite autour du texte, options style de ligne calqués sur {@link buildStrokeStyleFromLiteral}
 * @param {Object} literalStyle.backgroundFill surlignage du texte, options style de remplissage calqués sur {@link buildFillStyleFromLiteral}
 * @param {*} [literalStyle.args] reste des options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_Text-Text.html OpenLayer Text}
 * @returns {ol.style.Text}
 */
export function buildTextStyleFromLiteral ({ fill, stroke, backgroundStroke, backgroundFill, ...text }) {
  if (fill) {
    text.fill = buildFillStyleFromLiteral(fill)
  }
  if (stroke) {
    text.stroke = buildStrokeStyleFromLiteral(stroke)
  }
  if (backgroundFill) {
    text.backgroundFill = buildFillStyleFromLiteral(backgroundFill)
  }
  if (backgroundStroke) {
    text.backgroundStroke = buildStrokeStyleFromLiteral(backgroundStroke)
  }
  const style = new Text(text)

  return style
}

/**
 * Crée un style de point basé sur une icone (image)
 * @param {Object} icon options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_Icon-Icon.html OpenLayer Icon}
 * @returns {ol.style.Icon}
 */
export function buildIconStyleFromLiteral (icon) {
  const style = new Icon(icon)

  return style
}

/**
 * Helper pour construire un style forme
 * @param {Object} options
 * @param {'square'|'triangle'|'star'|'cross'|'diamond'|'plus'|'pie'|'pie3D'|'bar'|'donut'} [options.type="square"] Type de forme a créer, renvoi un cecle si on choisi un style non reconnu
 * @param @param {*} [options.args] restes des options pour le style choisi
 * @see {@link buildShapeStyleFromLiteral} pour type = square, triangle, star, cross, diamond, plus
 * @see {@link buildChartStyleFromLiteral} pour type = pie, pie3D, bar, donut
 * @return {ol.style.RegularShape | ol-ext.style.Chart}
 */
function buildTypedShapeStyleFromLiteral (options) {
  const { type = 'square', ...styles } = options

  switch (type) {
    case 'square':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 4,
        angle: Math.PI / 4,
      })
    case 'triangle':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 3,
        angle: 0,
      })
    case 'star':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 5,
        radius2: styles.radius / 2,
        angle: 0,
      })
    case 'cross':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 4,
        radius2: 0,
        angle: 0,
      })
    case 'diamond':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 4,
        angle: 0,
      })
    case 'plus':
      return buildShapeStyleFromLiteral({
        ...styles,
        points: 4,
        radius2: styles.radius > 3 ? 1.05 * Math.log2(styles.radius) : 1,
        angle: 0,
      })

    case 'pie':
    case 'pie3D':
    case 'bar':
    case 'donut':
      return buildChartStyleFromLiteral({ ...styles, type })
    default: // Retourne un cercle si on a rempli un style loufoque
      return buildCircleStyleFromLiteral({ radius: 10, ...styles })
  }
}

/**
 * Crée un style de point basé sur une forme
 * @param {Object} literalStyle
 * @param {Object} literalStyle.stroke options style de ligne calqués sur {@link buildStrokeStyleFromLiteral}
 * @param {Object} literalStyle.fill options style de remplissage calqués sur {@link buildFillStyleFromLiteral}
 * @param @param {*} [literalStyle.args] reste des options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_RegularShape-RegularShape.html OpenLayer RegularShape}
 * @returns {ol.style.RegularShape}
 */
export function buildShapeStyleFromLiteral ({ fill, stroke, ...shape }) {
  if (fill) {
    shape.fill = buildFillStyleFromLiteral(fill)
  }
  if (stroke) {
    shape.stroke = buildStrokeStyleFromLiteral(stroke)
  }
  const style = new RegularShape(shape)

  return style
}

/**
 * Crée un style de point basé sur un cercle
 * @param {Object} literalStyle
 * @param {Object} literalStyle.stroke options style de ligne calqués sur {@link buildStrokeStyleFromLiteral}
 * @param {Object} literalStyle.fill options style de remplissage calqués sur {@link buildFillStyleFromLiteral}
 * @param {*} [literalStyle.args] reste des options calqués sur {@link https://openlayers.org/en/latest/apidoc/module-ol_style_Circle-CircleStyle.html OpenLayer CircleStyle}
 * @returns {ol.style.Circle}
 */
export function buildCircleStyleFromLiteral ({ fill, stroke, ...circle }) {
  if (fill) {
    circle.fill = buildFillStyleFromLiteral(fill)
  }
  if (stroke) {
    circle.stroke = buildStrokeStyleFromLiteral(stroke)
  }
  const style = new Circle(circle)

  return style
}

/**
 * créer une geometrie a partir de tableau de coordoonées
 * @param {string} Type type de géométrie demandée
 * @param {Coordinate[]} coordinates tableaux de coordonnées
 * @param {string} geometries tableaux de tableaux de coordonnées pour faire un type géometrieCollection
 * @returns {ol.geom.Geometry}
 */
export function buildGeometryFromLiteral ({ type, coordinates, geometries }) {
  if (type === 'GeometryCollection') {
    return geometries.map(buildGeometryFromLiteral)
  }

  return new olGeom[type](coordinates)
}

/**
 * Crée un style de point basé sur un chart
 * @param {Object} literalStyle
 * @param {Object} literalStyle.stroke options style de ligne calqués sur {@link buildStrokeStyleFromLiteral}
 * @param {Object} literalStyle.fill options style de remplissage calqués sur {@link buildFillStyleFromLiteral}
 * @param {*} [literalStyle.args] reste des options calqués sur {@link http://viglino.github.io/ol-ext/doc/doc-pages/ol.style.Chart.html ol-ext Chart}
 * @returns {ol-ext.style.Chart}
 */
export function buildChartStyleFromLiteral ({ fill, stroke, ...opts }) {
  if (fill) {
    opts.fill = new Fill({ ...fill })
  }
  if (stroke) {
    opts.stroke = new Stroke({ ...stroke })
  }
  const style = new Chart({
    ...opts,
  })

  return style
}

// #endregion