import * as turf from '@turf/turf'
import _ from 'lodash'
import { transformCoordinateToLngLat } from '../transform'

const EARTH_RADIUS = 6378137

export function getFeatures (photoList, imagePosDiff, zoom) {
  let features = []
  let minDiff_z = Infinity
  let maxDiff_z = -Infinity
  let ratio = getRatio(zoom, imagePosDiff)
  let endPoints = []
  // 先获取坐标系
  let item = photoList.find(d => d.meta_data.pos)
  if (item) {
    let coordinate_system = _.cloneDeep(item.meta_data.coordinate_system)
    photoList.forEach((photo, index) => {
      let {meta_data} = photo
      let startPoint = transformCoordinateToLngLat(meta_data.pos, coordinate_system)
      if (!startPoint) {
        return
      }
      let id = index + 1
      let diffItem = imagePosDiff.find(d => d.id === id)
      if (!diffItem) {
        return
      }
      // 计算z方向的误差最大值，用于给椭圆设置颜色
      let diffs = diffItem.pos_diff
      minDiff_z = Math.min(minDiff_z, diffs[2])
      maxDiff_z = Math.max(maxDiff_z, diffs[2])
      let endPoint = _.cloneDeep(startPoint)
      endPoint[0] += diffs[0] * ratio * getDegreePerMeters()
      endPoint[1] += diffs[1] * ratio * getDegreePerMeters()
      endPoints.push(endPoint)
      features.push(turf.lineString([startPoint, endPoint], {
        diff_x: 100 * diffs[0],
        diff_y: 100 * diffs[1],
        diff_z: 100 * diffs[2]
      }))
    })
  }
  return {
    geojson: turf.featureCollection(features),
    ratio,
    minDiff_z,
    maxDiff_z,
    endPoints
  }
}

// 获取误差椭圆的缩放系数。要把误差直观反应到地图上需要对误差椭圆进行缩放，其缩放的大小跟误差的大小和当前地图的级别有关
// 本函数假设要让最大的误差在当前地图层级上显示出30像素的大小，以此来预估缩放系数
function getRatio (zoom, diffs) {
  // 最大误差值
  let max = diffs.reduce((m, item) => {
    if (!item.pos_diff?.length) {
      return m
    }
    let d = Math.max(Math.abs(item.pos_diff[0]), Math.abs(item.pos_diff[1]))
    return m > d ? m : d
  })
  // 地图上30像素代表的距离
  let distance = 30 * 2 * Math.PI * EARTH_RADIUS / (Math.pow(2, zoom) * 512)
  let ratio = distance / max
  if (ratio < 1) {
    return Number(ratio.toFixed(1))
  }
  if (ratio < 10) {
    return Math.round(ratio)
  }
  if (ratio < 100) {
    return 10 * parseInt(ratio / 10)
  }
  return Math.max(Math.round(ratio / 100) * 100, 100)
}

// 墨卡托坐标系每米对应的经纬度度数
function getDegreePerMeters () {
  return 180 / (Math.PI * EARTH_RADIUS)
}