import { GeoData } from '@/types/api/domain'
import * as THREE from 'three'

// MARKERS

type GCS = [number, number]

export function parseGCS(gcsString: string): GCS {
  const parts = gcsString.split(',')
  if (parts.length == 2) {
    return [parseFloat(parts[0]), parseFloat(parts[1])]
  } else {
    throw new TypeError('GCS string must be two floats separated by a comma!')
  }
}

export function gcsToVec3(lat: number, lon: number, r: number = 0.5, h: number = -0.005) {
  const phi = (lat) * Math.PI/180
  const theta = (lon-180) * Math.PI/180

  const x = -(r+h) * Math.cos(phi) * Math.cos(theta)
  const y = (r+h) * Math.sin(phi)
  const z = (r+h) * Math.cos(phi) * Math.sin(theta)

  return new THREE.Vector3(x,y,z)
}

function createMarker(size: number, color: number, pos: THREE.Vector3, name?: string) {
  const markerGeometry = new THREE.SphereGeometry(size)
  const markerMaterial = new THREE.MeshBasicMaterial({
    color: color
  })
  const markerMesh = new THREE.Mesh(markerGeometry, markerMaterial)
  markerMesh.position.copy(pos)
  markerMesh.name = name ?? ''
  
  return markerMesh
}

export function addMarker(
  to: THREE.Object3D | THREE.Group,
  at: GCS,
  name?: string,
  color: number = 0xffffff,
  size: number = 0.01
) {
  const pos = gcsToVec3(...at)
  const marker = createMarker(size, color, pos, name)
  to.add(marker)
}

export function renderMarkers(data: GeoData[], to: THREE.Object3D) {
  // cleanup
  const existing = to.getObjectByName('markers')
  if (existing) to.remove(existing)
  //
  const group = new THREE.Group()
  for (const gd of data) {
    if (!gd || !gd.loc) continue
    const gcs = parseGCS(gd.loc)
    addMarker(group, gcs, gd.ip, 0xffffff, data.length > 15 ? 0.006 : 0.01)
  }
  group.name = 'markers'
  to.add(group)
}