    import { Color, GeometryType, Log, RendererType, SymbolType } from '../../index'
    import { defined, isNumber } from '../../util'
    import {
      SimpleFillSymbol,
      SimpleMarkerSymbol,
      SimpleLineSymbol,
      Symbol
    } from '../../base/symbol'
    import VisualVariableType from '../../base/enum/VisualVariableType'

    /**
     * @description: 简单解析数值表达式
     * @param {*} feature
     * @param {String} expression
     * @return {*}
     */
    function parseExpression(feature, expression) {
      if (!expression) return ''
      const excuteStr = expression.replace(/\$feature/g, `feature.attributes`)
      try {
        // eslint-disable-next-line no-eval
        const v = eval(excuteStr)
        return v
      } catch (err) {
        Log.info('字段表达式输入值非法')
      }
      return ''
    }

    /**
     * @description: 解析要素字段和表达式
     * @param {*} feature
     * @param {*} field
     * @param {*} expression
     * @return {*}
     */
    function parseFieldAndExpression(feature, field, expression) {
      const attributes = feature.attributes || {}
      let value = attributes[field]
      value = defined(value) ? value : parseExpression(feature, expression)
      return value
    }

    /**
     * @description: 随机颜色
     * @return {*}
     */
    function randomColor() {
      return `rgba(${Math.round(Math.random() * 255)},${Math.round(
        Math.random() * 255
      )},${Math.round(Math.random() * 255)},1)`
    }

    /**
     * @description: 计算比例
     * @param {*} value
     * @param {*} spaceMinValue
     * @param {*} spaceMaxValue
     * @return {*}
     */
    function calcSpaceRatio(value, spaceMinValue, spaceMaxValue) {
      const space = spaceMaxValue - spaceMinValue
      if (Number.isNaN(space) || space <= 0) {
        Log.error('传入的视觉变量不合法')
      }
      if (value <= spaceMinValue) {
        return 0
      } else if (value > spaceMaxValue) {
        return 1
      } else {
        return (value - spaceMinValue) / space
      }
    }

    /**
     * @description: 计算取值分段
     * @param {*} value
     * @param {*} stops
     * @param {*} func
     * @return {*}
     */
    function calcGradientInStops(value, stops, func) {
      if (!Array.isArray(stops) || stops.length <= 0) return
      // 排序颜色stop
      const sortStops = stops.sort((a, b) => a.value - b.value)
      if (sortStops.length === 1) return func(stops[0], stops[0], 1)
      // 如果小于stop.value
      const firstStop = sortStops[0]
      const endStop = sortStops[sortStops.length - 1]
      // 分段处理stop
      if (value < firstStop.value) {
        return func(firstStop, firstStop, 1)
      } else if (value >= endStop.value) {
        return func(endStop, endStop, 1)
      } else {
        for (let i = 1; i < sortStops.length; i++) {
          const f = sortStops[i - 1]
          const e = sortStops[i]
          if (value >= f.value && value <= e.value) {
            return func(f, e, calcSpaceRatio(value, f.value, e.value))
          }
        }
      }
    }

    /**
     * @description: 更新要素的符号信息
     * @param {*} feature
     * @param {*} rendererSymbol
     * @param {Boolean} visible
     * @param {Array<VisualVariable>} 视觉变量
     * @return {*}
     */
    function updateFeatureSymbol(
      feature,
      rendererSymbol,
      visible,
      visualVariables
    ) {
      if (!feature || !feature.symbol || !rendererSymbol) return
      // 处理显示或隐藏
      const applyVisible = defined(visible) ? visible : true
      if (feature.visible !== applyVisible) {
        feature.visible = applyVisible
      }

      // 对比符号JSON，决定是否更新
      const oldJSON = feature.symbol.toJSON()
      const newJSON = rendererSymbol.toJSON()
      if (oldJSON !== newJSON) {
        feature.symbol = newJSON
      }

      // 处理视觉变量
      if (
        !visualVariables ||
        !Array.isArray(visualVariables) ||
        visualVariables.length <= 0
      ) {
        return
      }
      const symbol =
        feature.symbol instanceof Symbol
          ? feature.symbol.toJSON()
          : JSON.stringify(feature.symbol)
      for (let i = 0; i < visualVariables.length; i++) {
        const visualVariable = visualVariables[i]
        const { field, type, valueExpression } = visualVariable
        let value = parseFieldAndExpression(feature, field, valueExpression)
        value = parseFloat(value)
        // eslint-disable-next-line no-continue
        if (Number.isNaN(value)) continue
        switch (type) {
          case VisualVariableType.color: {
            const { stops } = visualVariable
            const color = calcGradientInStops(
              value,
              stops,
              (firstStop, endStop, ratio) => {
                // 计算颜色分段
                const firstColor = Color.fromColor(firstStop.color)
                const endColor = Color.fromColor(endStop.color)
                const r = parseInt(
                  firstColor.red + (endColor.red - firstColor.red) * ratio
                )
                const g = parseInt(
                  firstColor.green + (endColor.green - firstColor.green) * ratio
                )
                const b = parseInt(
                  firstColor.blue + (endColor.blue - firstColor.blue) * ratio
                )
                const a = parseFloat(
                  firstColor.alpha + (endColor.alpha - firstColor.alpha) * ratio
                )
                return new Color(r, g, b, a)
              }
            )
            if (defined(color)) {
              symbol.color = color
            }
            break
          }
          case VisualVariableType.size: {
            const { stops, maxDataValue, minDataValue, maxSize, minSize } =
              visualVariable
            // size视觉的两种用法
            let calcStops = stops
            // 解析第一种视觉变量的使用方式，优先级最高
            if (
              isNumber(maxDataValue) &&
              isNumber(minDataValue) &&
              isNumber(maxSize) &&
              isNumber(minSize)
            ) {
              calcStops = [
                {
                  size: minSize,
                  value: minDataValue
                },
                {
                  size: maxSize,
                  value: maxDataValue
                }
              ]
            }
            const size = calcGradientInStops(
              value,
              calcStops,
              (firstStop, endStop, ratio) => {
                // 计算颜色分段
                const fSize = firstStop.size
                const eSize = endStop.size
                return parseInt(fSize + (eSize - fSize) * ratio)
              }
            )

            if (defined(size)) {
              symbol.size = size
            }
            break
          }
          case VisualVariableType.opacity: {
            const { stops } = visualVariable
            const alpha = calcGradientInStops(
              value,
              stops,
              (firstStop, endStop, ratio) => {
                // 计算颜色分段
                const fOpacity = firstStop.opacity
                const eOpacity = endStop.opacity
                const a =
                  parseInt((fOpacity + (eOpacity - fOpacity) * ratio) * 100) / 100
                return a
              }
            )
            if (defined(alpha) && symbol.color) {
              const color = Color.fromColor(symbol.color)
              color.alpha = alpha
              symbol.color = color
            }
            break
          }
          default: {
            break
          }
        }
        // 设置视觉变量
        feature.symbol = symbol
      }
    }

    /**
     * @description: 更新随机符号
     * @param {*} feature
     * @return {*}
     */
    function updateRandomFeatureSymbol(feature) {
      if (!feature || !feature.geometry) return
      const geometry = feature.geometry
      switch (geometry.type) {
        case GeometryType.multiPoint:
        case GeometryType.point: {
          feature.symbol = new SimpleMarkerSymbol({
            color: randomColor(),
            outline: new SimpleLineSymbol({
              color: randomColor()
            })
          })
          break
        }
        case GeometryType.multiLineString:
        case GeometryType.lineString: {
          feature.symbol = new SimpleLineSymbol({
            color: randomColor()
          })
          break
        }
        case GeometryType.polygon:
        case GeometryType.extent:
        case GeometryType.circle:
        case GeometryType.multiPolygon: {
          feature.symbol = new SimpleFillSymbol({
            color: randomColor(),
            outline: new SimpleLineSymbol({
              color: randomColor()
            })
          })
          break
        }
        default: {
          break
        }
      }
    }

    /**
     * @description 渲染要素集
     * @public
     * @param {FeatureSet|Array<Feature>} featureSet
     * @param {*} renderer
     * @return {*}
     */
    function updateRenderer(features, renderer) {
      renderer = renderer || {}
      const visualVariables = renderer.visualVariables || []
      switch (renderer.type) {
        case RendererType.simple: {
          const rendererSymbol = renderer.symbol
          features.forEach((feature) => {
            updateFeatureSymbol(feature, rendererSymbol, true, visualVariables)
          })
          break
        }
        case RendererType.uniqueValue: {
          const defaultSymbol = renderer.defaultSymbol || {}
          const defaultVisible = renderer.defaultVisible
          const uniqueValueInfos = renderer.uniqueValueInfos || []
          const valueExpression = renderer.valueExpression || ''
          for (let i = 0; i < features.length; i++) {
            const feature = features[i]
            const field = renderer.field || ''
            const value = parseFieldAndExpression(feature, field, valueExpression)
            if (defined(value)) {
              let uniqueSymbol = null
              let _uniqueValueInfo = null
              for (let j = 0; j < uniqueValueInfos.length; j++) {
                const uniqueValueInfo = uniqueValueInfos[j]
                if (uniqueValueInfo.value === value) {
                  uniqueSymbol = uniqueValueInfo.symbol
                  _uniqueValueInfo = uniqueValueInfo
                  break
                }
              }
              if (uniqueSymbol) {
                updateFeatureSymbol(
                  feature,
                  uniqueSymbol,
                  _uniqueValueInfo.visible,
                  visualVariables
                )
                // eslint-disable-next-line no-continue
                continue
              }
            }
            // 采用默认的样式
            updateFeatureSymbol(
              feature,
              defaultSymbol,
              defaultVisible,
              visualVariables
            )
          }
          break
        }
        case RendererType.classBreak: {
          const defaultSymbol = renderer.defaultSymbol || {}
          const classBreakInfos = renderer.classBreakInfos || []
          const valueExpression = renderer.valueExpression || ''
          const defaultVisible = renderer.defaultVisible
          for (let i = 0; i < features.length; i++) {
            const feature = features[i]
            const field = renderer.field || ''
            const value = parseFieldAndExpression(feature, field, valueExpression)
            if (defined(value)) {
              let classBreakSymbol = null
              let _classBreakInfo = null
              for (let j = 0; j < classBreakInfos.length; j++) {
                const classBreakInfo = classBreakInfos[j]
                const maxValue = classBreakInfo.maxValue
                const minValue = classBreakInfo.minValue
                if (value >= minValue && value < maxValue) {
                  classBreakSymbol = classBreakInfo.symbol
                  _classBreakInfo = classBreakInfo
                  break
                }
              }
              if (classBreakSymbol) {
                updateFeatureSymbol(
                  feature,
                  classBreakSymbol,
                  _classBreakInfo.visible,
                  visualVariables
                )
                // eslint-disable-next-line no-continue
                continue
              }
            }
            // 采用默认的样式
            updateFeatureSymbol(
              feature,
              defaultSymbol,
              defaultVisible,
              visualVariables
            )
          }
          break
        }
        case RendererType.random: {
          features.forEach((feature) => {
            updateRandomFeatureSymbol(feature)
          })
          break
        }
        case RendererType.rank: {
          const symbol = renderer.symbol
          const {
            minSize,
            maxSize,
            maxDataValue,
            minDataValue,
            field,
            valueExpression
          } = renderer
          if (!symbol || minSize > maxSize || (!field && !valueExpression)) {
            Log.error('等级符号专题图参数异常！')
          }
          // 计算最大数值
          let max
          let min

          features.forEach((feature) => {
            let value = parseFieldAndExpression(feature, field, valueExpression)
            value = parseFloat(value)
            if (!defined(max)) {
              max = value
            }
            if (!defined(min)) {
              min = value
            }
            max = Math.max(max, value)
            min = Math.min(min, value)
          })
          // 如果设置有数据最大范围，则用数据最大范围
          if (
            defined(minDataValue) &&
            defined(maxDataValue) &&
            maxDataValue > minDataValue
          ) {
            max = maxDataValue

            min = minDataValue
          }
          // 处理最大最小值相同的情况
          if (max - min === 0) {
            max += 0.0001
          }
          // 设置样式
          features.forEach((feature) => {
            const featureSymbol = symbol.clone()
            let value = parseFieldAndExpression(feature, field, valueExpression)
            value = parseFloat(value)

            // 计算比率
            let clampRate
            if (value < min) {
              clampRate = 0
            } else if (value > max) {
              clampRate = 1
            } else {
              clampRate = (value - min) / (max - min)
            }
            const clampSize = parseInt(clampRate * (maxSize - minSize) + minSize)
            // 判断是否有计算值
            if (isNumber(clampSize)) {
              switch (featureSymbol.type) {
                case SymbolType.simpleMarker: {
                  featureSymbol.size = clampSize
                  break
                }
                case SymbolType.pictureMarker: {
                  featureSymbol.width = clampSize
                  featureSymbol.height = clampSize
                  break
                }
                case SymbolType.text: {
                  const font = featureSymbol.font || {}
                  font.size = clampSize
                  featureSymbol.font = font
                  break
                }
                default: {
                  break
                }
              }
            }
            // 更新符号
            updateFeatureSymbol(feature, featureSymbol, true, visualVariables)
          })
          break
        }
        default: {
          const rendererSymbol = renderer.symbol
          features.forEach((feature) => {
            updateFeatureSymbol(feature, rendererSymbol, true, visualVariables)
          })
          break
        }
      }
    }

    export { updateRenderer, parseExpression }