/**
 * WGS84 → GCJ-02 → BD-09 坐标转换工具
 * 百度地图需要使用 BD-09 坐标系
 */

const PI = Math.PI
const X_PI = (PI * 3000.0) / 180.0
const A = 6378245.0
const EE = 0.00669342162296594323

function transformLat(lng, lat) {
  let ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lat * PI) + 40.0 * Math.sin((lat / 3.0) * PI)) * 2.0) / 3.0
  ret += ((160.0 * Math.sin((lat / 12.0) * PI) + 320 * Math.sin((lat * PI) / 30.0)) * 2.0) / 3.0
  return ret
}

function transformLng(lng, lat) {
  let ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
  ret += ((20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0) / 3.0
  ret += ((20.0 * Math.sin(lng * PI) + 40.0 * Math.sin((lng / 3.0) * PI)) * 2.0) / 3.0
  ret += ((150.0 * Math.sin((lng / 12.0) * PI) + 300.0 * Math.sin((lng / 30.0) * PI)) * 2.0) / 3.0
  return ret
}

/** WGS84 → GCJ-02 (火星坐标) */
function wgs84ToGcj02(lng, lat) {
  let dLat = transformLat(lng - 105.0, lat - 35.0)
  let dLng = transformLng(lng - 105.0, lat - 35.0)
  const radLat = (lat / 180.0) * PI
  let magic = Math.sin(radLat)
  magic = 1 - EE * magic * magic
  const sqrtMagic = Math.sqrt(magic)
  dLat = (dLat * 180.0) / (((A * (1 - EE)) / (magic * sqrtMagic)) * PI)
  dLng = (dLng * 180.0) / ((A / sqrtMagic) * Math.cos(radLat) * PI)
  return [lng + dLng, lat + dLat]
}

/** GCJ-02 → BD-09 (百度坐标) */
function gcj02ToBd09(lng, lat) {
  const z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI)
  const theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI)
  return [z * Math.cos(theta) + 0.0065, z * Math.sin(theta) + 0.006]
}

/** WGS84 → BD-09 一步转换 */
export function wgs84ToBd09(lng, lat) {
  const [gcjLng, gcjLat] = wgs84ToGcj02(lng, lat)
  return gcj02ToBd09(gcjLng, gcjLat)
}

/** 转换管线数据中的坐标数组 */
export function convertPipeline(pipeline) {
  return {
    ...pipeline,
    path: pipeline.path ? pipeline.path.map(([lng, lat]) => wgs84ToBd09(lng, lat)) : undefined,
    points: pipeline.points
      ? (Array.isArray(pipeline.points[0])
          ? pipeline.points.map(([lng, lat]) => wgs84ToBd09(lng, lat))
          : pipeline.points.map(p => ({ ...p, lng: wgs84ToBd09(p.lng, p.lat)[0], lat: wgs84ToBd09(p.lng, p.lat)[1] })))
      : undefined
  }
}

/** 转换单个坐标点 */
export function convertCoord(lng, lat) {
  return wgs84ToBd09(lng, lat)
}

/** 批量转换点数组中的 lng/lat */
export function convertPoints(points) {
  return points.map(p => {
    const [lng, lat] = wgs84ToBd09(p.lng, p.lat)
    return { ...p, lng, lat }
  })
}
