import * as FileSystem  from 'expo-file-system';
import { FASTEST_MAP_HOST } from 'src/constants';

const baseTilesDir = `${FileSystem.cacheDirectory}tiles/`;

interface TileType {
  url: string;
  type: string;
  maxZoom: number;
}

async function ensureDirExists(dirPath: string): Promise<void> {
  const dirInfo = await FileSystem.getInfoAsync(dirPath);

  if (!dirInfo.exists) {
    await FileSystem.makeDirectoryAsync(dirPath, { intermediates: true });
  }
}

async function downloadTile(z: number, x: number, y: number, tile: TileType): Promise<void> {
  try {
    const tileUrl = `${FASTEST_MAP_HOST}${tile.url}/${z}/${x}/${y}`;
    const filePath = `${baseTilesDir}${tile.type}/${z}/${x}/${y}`;
    await FileSystem.downloadAsync(tileUrl, filePath);

  } catch (error) {
    console.error(`Error downloading tile ${z}/${x}/${y} for ${tile.type}:`, error);
  }
}

async function checkTilesExistence(tileType: TileType): Promise<boolean> {
  const dirPath = `${baseTilesDir}${tileType.type}/`;
  const MIN_SIZE_BYTES = 1024 * 512;
  try {
    const fileInfo = await FileSystem.getInfoAsync(dirPath, { size: true });

    return fileInfo.exists && fileInfo.size < MIN_SIZE_BYTES;
  } catch (error) {
    console.error(`Error fetching directory size: ${dirPath}:`, error);
    return true;
  }
}

async function downloadTiles(tileType: TileType): Promise<void> {
  await ensureDirExists(`${baseTilesDir}${tileType.type}/`);
  const tilesExist = await checkTilesExistence(tileType);

  if (tilesExist) {
    for (let z = 2; z <= tileType.maxZoom; z++) {
      const maxTile = Math.pow(2, z);

      for (let x = 0; x < maxTile; x++) {
        const dirPath = `${baseTilesDir}${tileType.type}/${z}/${x}`;
        await ensureDirExists(dirPath);

        for (let y = 0; y <= maxTile; y++) {
          await downloadTile(z, x, y, tileType);
        }
      }
    }
  }
}

export async function initTilesDownload(userId: string): Promise<void> {
  let tileTypes: TileType[] = [
    {url: '/tiles_osm', type: 'background', maxZoom: 5},
    {url: '/tiles_nm/grid', type: 'grid', maxZoom: 5},
    {url: '/tiles_nm/regions_mqp', type: 'regions_mqp', maxZoom: 4},
  ];

  for (const type of tileTypes) {
    await downloadTiles(type);
  }
}
