import {
  GeometryType,
  SymbolType,
  Feature,
  defaultValue
} from '@mapgis/webclient-common'
import ConvertSymbolToGraphicStyle from './ConvertSymbolToGraphicStyle'
import ConvertGeometryUtil from '../ConvertGeometryUtil'

// 转换符号
const convertSymbol = ConvertSymbolToGraphicStyle.convertSymbolToGraphicStyle
// 转换几何
const convertGeometry = ConvertGeometryUtil.toCartesian3Array
/**
 * @description 创建cesium 几何对象
 * @param {Object} object 几何体options
 * @return {Cesium.Graphic}
 */
function createGraphic(object) {
  const graphic = new Cesium.Graphic(object)
  return graphic
}

function convertPointToGraphic(feature, options) {
  let graphicType = 'point'
  // 设置graphics类型
  if (feature.symbol && feature.symbol.type === SymbolType.pictureMarker) {
    graphicType = 'billboard'
  }
  const style = convertSymbol(feature.symbol, graphicType)
  // 解析高度信息
  style.offsetHeight = 0
  if (options.elevationInfo) {
    const elevationInfo = options.elevationInfo
    style.offsetHeight = defaultValue(elevationInfo.offset, 0)
  }
  // 添加高度(此处是因为graphicLayer设置高度不生效)
  if (feature.geometry && feature.geometry.hasZ) {
    const coordinates = feature.geometry.coordinates
    style.offsetHeight += coordinates[2]
  }
  const graphicPositions = convertGeometry(feature.geometry, {
    spatialReference: options.spatialReference
  })
  // 无法设置高度，仅能通过offsetHeight属性设置
  const graphicOption = {
    type: graphicType,
    style,
    show: feature.visible,
    attributes: JSON.parse(JSON.stringify(feature.attributes)),
    name: feature.id,
    positions: graphicPositions,
    id: feature.id
  }
  return createGraphic(graphicOption)
}

function convertPolylineToGraphic(feature, options) {
  const graphicType = 'polyline'
  const style = convertSymbol(feature.symbol, graphicType)
  // 解析高度信息
  let offsetHeight = 0
  if (options.elevationInfo) {
    const elevationInfo = options.elevationInfo
    offsetHeight = defaultValue(elevationInfo.offset, 0)
  }
  const graphicOption = {
    type: graphicType,
    style,
    show: feature.visible,
    attributes: JSON.parse(JSON.stringify(feature.attributes)),
    name: feature.id,
    positions: convertGeometry(feature.geometry, {
      offsetHeight,
      spatialReference: options.spatialReference
    }),
    id: feature.id
  }
  return createGraphic(graphicOption)
}

function convertPolygonToGraphic(feature, options) {
  const graphicType = 'polygon'
  const style = convertSymbol(feature.symbol, graphicType)
  // 解析高度信息
  let offsetHeight = 0
  if (options.elevationInfo) {
    const elevationInfo = options.elevationInfo
    offsetHeight = defaultValue(elevationInfo.offset, 0)
  }
  style.perPositionHeight = true
  const graphicOption = {
    type: graphicType,
    style,
    show: feature.visible,
    attributes: JSON.parse(JSON.stringify(feature.attributes)),
    name: feature.id,
    positions: convertGeometry(feature.geometry, {
      offsetHeight,
      spatialReference: options.spatialReference
    }),
    id: feature.id
  }
  return createGraphic(graphicOption)
}

function convertExtentToGraphic(feature, options) {
  const graphicType = 'rectangle'
  const style = convertSymbol(feature.symbol, graphicType)
  // 解析高度信息
  let offsetHeight = 0
  if (options.elevationInfo) {
    const elevationInfo = options.elevationInfo
    offsetHeight = defaultValue(elevationInfo.offset, 0)
  }
  // 添加高度(此处是因为graphicLayer设置高度不生效)
  if (feature.geometry && feature.geometry.hasZ) {
    const zMax = feature.geometry.zmax
    const zMin = feature.geometry.zmin
    style.extrudedHeight = zMax - zMin
    offsetHeight = zMin + offsetHeight
  }
  style.offsetHeight = offsetHeight
  const graphicOption = {
    type: graphicType,
    style,
    show: feature.visible,
    attributes: JSON.parse(JSON.stringify(feature.attributes)),
    name: feature.id,
    positions: convertGeometry(feature.geometry, {
      offsetHeight,
      spatialReference: options.spatialReference
    }),
    id: feature.id
  }
  return createGraphic(graphicOption)
}

function convertCircleToGraphic(feature, options) {
  const graphicType = 'circle'
  const style = convertSymbol(feature.symbol, graphicType)
  const geometry = feature.geometry
  const center = geometry.center
  // 解析高度信息
  let offsetHeight = 0
  if (options.elevationInfo) {
    const elevationInfo = options.elevationInfo
    offsetHeight = defaultValue(elevationInfo.offset, 0)
  }
  style.radius = geometry.radius
  style.offsetHeight = geometry.hasZ ? offsetHeight + center[2] : offsetHeight

  const graphicOption = {
    type: graphicType,
    style,
    show: feature.visible,
    attributes: JSON.parse(JSON.stringify(feature.attributes)),
    name: feature.id,
    positions: convertGeometry(feature.geometry, {
      offsetHeight,
      spatialReference: options.spatialReference
    }),
    id: feature.id
  }
  return createGraphic(graphicOption)
}
// 转换要素为cesium 几何图形
class ConvertFeatureToGraphicUtil {
  constructor() {}

  static convertFeature(feature, options) {
    const opt = defaultValue(options, {})
    let graphic = null
    switch (feature.geometry.type) {
      case GeometryType.point: {
        graphic = convertPointToGraphic(feature, opt)
        break
      }
      case GeometryType.lineString: {
        graphic = convertPolylineToGraphic(feature, opt)
        break
      }
      case GeometryType.polygon: {
        graphic = convertPolygonToGraphic(feature, opt)
        break
      }
      case GeometryType.extent: {
        graphic = convertExtentToGraphic(feature, opt)
        break
      }
      case GeometryType.circle: {
        const _circleFeature = Feature.fromJSON(feature)
        _circleFeature.geometry = _circleFeature.geometry.toPolygon()
        graphic = convertPolygonToGraphic(_circleFeature, opt)
        break
      }
      default: {
        break
      }
    }
    return graphic
  }
}
export default ConvertFeatureToGraphicUtil
