export interface TileItem {
  key: string
  url: string
  x: number
  y: number
  leftPx: number
  topPx: number
  sizePx: number
  isCenter: boolean
}

const TILE_OVERLAP_PX = 2

export interface TileGridOptions {
  urlTemplate: string
  zoom: number
  centerTileX: number
  centerTileY: number
  viewportWidth: number
  viewportHeight: number
  tileSize: number
  overdraw: number
}

export function buildTileUrl(template: string, z: number, x: number, y: number): string {
  return template
    .replace('{z}', String(z))
    .replace('{x}', String(x))
    .replace('{y}', String(y))
}

export function createTileGrid(options: TileGridOptions): TileItem[] {
  const tiles: TileItem[] = []
  const halfWidth = options.viewportWidth / 2
  const halfHeight = options.viewportHeight / 2
  const horizontalRange = Math.ceil(halfWidth / options.tileSize) + options.overdraw
  const verticalRange = Math.ceil(halfHeight / options.tileSize) + options.overdraw

  for (let dy = -verticalRange; dy <= verticalRange; dy += 1) {
    for (let dx = -horizontalRange; dx <= horizontalRange; dx += 1) {
      const x = options.centerTileX + dx
      const y = options.centerTileY + dy

      const rawLeft = halfWidth + (dx - 0.5) * options.tileSize
      const rawTop = halfHeight + (dy - 0.5) * options.tileSize

      tiles.push({
        key: `${options.zoom}-${x}-${y}`,
        url: buildTileUrl(options.urlTemplate, options.zoom, x, y),
        x,
        y,
        leftPx: Math.floor(rawLeft - TILE_OVERLAP_PX / 2),
        topPx: Math.floor(rawTop - TILE_OVERLAP_PX / 2),
        sizePx: Math.ceil(options.tileSize) + TILE_OVERLAP_PX,
        isCenter: dx === 0 && dy === 0,
      })
    }
  }

  return tiles
}
