/**
 * Convert an array of items to GeoJSON FeatureCollection
 */
export function toGeoJSON<T>(
  items: T[],
  getLngLat: (item: T) => [number, number],
  getProperties?: (item: T) => Record<string, unknown>
): GeoJSON.FeatureCollection {
  return {
    type: 'FeatureCollection',
    features: items.map((item, index) => {
      const [lng, lat] = getLngLat(item)
      return {
        type: 'Feature',
        id: index,
        geometry: {
          type: 'Point',
          coordinates: [lng, lat],
        },
        properties: getProperties ? getProperties(item) : {},
      }
    }),
  }
}

/**
 * Convert GeoJSON FeatureCollection to array of items
 */
export function fromGeoJSON<T>(
  fc: GeoJSON.FeatureCollection,
  transform: (feature: GeoJSON.Feature) => T
): T[] {
  return fc.features.map(transform)
}

/**
 * Create a GeoJSON Point
 */
export function createPoint(
  coordinates: [number, number],
  properties: Record<string, unknown> = {}
): GeoJSON.Feature<GeoJSON.Point> {
  return {
    type: 'Feature',
    geometry: {
      type: 'Point',
      coordinates,
    },
    properties,
  }
}

/**
 * Create a GeoJSON Polygon
 */
export function createPolygon(
  coordinates: [number, number][],
  properties: Record<string, unknown> = {}
): GeoJSON.Feature<GeoJSON.Polygon> {
  // Ensure the polygon is closed
  const closed = [...coordinates]
  if (
    coordinates.length > 0 &&
    (coordinates[0][0] !== coordinates[coordinates.length - 1][0] ||
      coordinates[0][1] !== coordinates[coordinates.length - 1][1])
  ) {
    closed.push(coordinates[0])
  }

  return {
    type: 'Feature',
    geometry: {
      type: 'Polygon',
      coordinates: [closed],
    },
    properties,
  }
}

/**
 * Create a GeoJSON LineString
 */
export function createLineString(
  coordinates: [number, number][],
  properties: Record<string, unknown> = {}
): GeoJSON.Feature<GeoJSON.LineString> {
  return {
    type: 'Feature',
    geometry: {
      type: 'LineString',
      coordinates,
    },
    properties,
  }
}

/**
 * Create an empty FeatureCollection
 */
export function createFeatureCollection(
  features: GeoJSON.Feature[] = []
): GeoJSON.FeatureCollection {
  return {
    type: 'FeatureCollection',
    features,
  }
}
