// GeoJSON 导出:KML 文档 → GeoJSON FeatureCollection。
//
// 输出 RFC 7946 的 FeatureCollection;几何映射:
// Point → Point,LineString → LineString,Polygon → Polygon,
// MultiGeometry → 拆成多个 Feature。

///|
/// 追加一个字符串(JSON 字符串转义)。
fn push_json_string(out : Array[Byte], text : String) -> Unit {
  out.push(b'"')
  let data = @utf8.encode(text)
  let mut i = 0
  while i < data.length() {
    let b = data[i]
    if b == b'"' || b == b'\\' {
      out.push(b'\\')
      out.push(b)
    } else if b == b'\n' {
      out.push(b'\\')
      out.push(b'n')
    } else if b == b'\t' {
      out.push(b'\\')
      out.push(b't')
    } else if b == b'\r' {
      out.push(b'\\')
      out.push(b'r')
    } else {
      out.push(b)
    }
    i = i + 1
  }
  out.push(b'"')
}

///|
/// 序列化一个坐标对。
fn push_position(out : Array[Byte], lon : Double, lat : Double) -> Unit {
  push_lit(out, "[")
  push_lit(out, lon.to_string())
  push_lit(out, ",")
  push_lit(out, lat.to_string())
  push_lit(out, "]")
}

///|
/// 序列化 Point。
fn push_geojson_point(out : Array[Byte], p : KmlPoint) -> Unit {
  push_lit(out, "{\"type\":\"Point\",\"coordinates\":")
  push_position(out, p.lon, p.lat)
  push_lit(out, "}")
}

///|
/// 序列化 LineString。
fn push_geojson_linestring(out : Array[Byte], ls : KmlLineString) -> Unit {
  push_lit(out, "{\"type\":\"LineString\",\"coordinates\":[")
  let mut i = 0
  while i < ls.points.length() {
    push_position(out, ls.points[i].lon, ls.points[i].lat)
    if i + 1 < ls.points.length() {
      push_lit(out, ",")
    }
    i = i + 1
  }
  push_lit(out, "]}")
}

///|
/// 序列化 Polygon。
fn push_geojson_polygon(out : Array[Byte], poly : KmlPolygon) -> Unit {
  push_lit(out, "{\"type\":\"Polygon\",\"coordinates\":[")
  push_ring(out, poly.outer)
  let mut i = 0
  while i < poly.inner.length() {
    push_lit(out, ",")
    push_ring(out, poly.inner[i])
    i = i + 1
  }
  push_lit(out, "]}")
}

///|
/// 序列化一个环。
fn push_ring(out : Array[Byte], ring : LinearRing) -> Unit {
  push_lit(out, "[")
  let mut i = 0
  while i < ring.points.length() {
    push_position(out, ring.points[i].lon, ring.points[i].lat)
    if i + 1 < ring.points.length() {
      push_lit(out, ",")
    }
    i = i + 1
  }
  push_lit(out, "]")
}

///|
/// 序列化一个 Geometry。
fn push_geojson_geometry(out : Array[Byte], geometry : Geometry) -> Unit {
  match geometry {
    Geometry::Point(p) => push_geojson_point(out, p)
    Geometry::LineString(ls) => push_geojson_linestring(out, ls)
    Geometry::Polygon(poly) => push_geojson_polygon(out, poly)
    Geometry::MultiGeometry(_) => push_lit(out, "null")
  }
}

///|
/// 序列化一个 Feature。
fn push_feature(out : Array[Byte], pm : Placemark) -> Unit {
  push_lit(out, "{\"type\":\"Feature\",")
  push_lit(out, "\"properties\":{")
  push_json_string(out, "name")
  push_lit(out, ":")
  push_json_string(out, pm.name)
  if pm.description != "" {
    push_lit(out, ",")
    push_json_string(out, "description")
    push_lit(out, ":")
    push_json_string(out, pm.description)
  }
  push_lit(out, "},")
  push_lit(out, "\"geometry\":")
  match pm.geometry {
    Some(g) => push_geojson_geometry(out, g)
    None => push_lit(out, "null")
  }
  push_lit(out, "}")
}

///|
/// 把 KML 文档导出为 GeoJSON FeatureCollection。
pub fn to_geojson(doc : KmlDocument) -> String {
  let out : Array[Byte] = []
  push_lit(out, "{\"type\":\"FeatureCollection\",\"features\":[")
  let mut i = 0
  while i < doc.placemarks.length() {
    push_feature(out, doc.placemarks[i])
    if i + 1 < doc.placemarks.length() {
      push_lit(out, ",")
    }
    i = i + 1
  }
  push_lit(out, "]}")
  @utf8.decode_lossy(Bytes::from_array(out))
}