import type { AssetDataT, Sprite } from '@/types'
import { useGameStore } from '@/stores/gameStore'
import { AssetStorage } from '@/storage/assetStorage'
import config from '@/config'

const textureLoadingPromises = new Map<string, Promise<boolean>>()

export async function loadTexture(scene: Phaser.Scene, assetData: AssetDataT): Promise<boolean> {
  const gameStore = useGameStore()
  const assetStorage = new AssetStorage()

  // Check if the texture is already loaded in Phaser
  if (gameStore.game.loadedAssets.find((asset) => asset.key === assetData.key)) {
    return Promise.resolve(true)
  }

  // If there's already a loading promise for this texture, return it
  if (textureLoadingPromises.has(assetData.key)) {
    return await textureLoadingPromises.get(assetData.key)!
  }

  // Create new loading promise
  const loadingPromise = (async () => {
    // Check if the asset is already cached
    let asset = await assetStorage.get(assetData.key)

    // If asset is not found, download it
    if (!asset) {
      await assetStorage.download(assetData)
      asset = await assetStorage.get(assetData.key)
    }

    // If asset is found, add it to the scene
    if (asset) {
      return new Promise<boolean>((resolve) => {
        // Remove existing texture if it exists
        if (scene.textures.exists(asset.key)) {
          scene.textures.remove(asset.key)
        }

        scene.textures.addBase64(asset.key, asset.data)
        scene.textures.once(`addtexture-${asset.key}`, () => {
          gameStore.game.loadedAssets.push(assetData)
          textureLoadingPromises.delete(assetData.key) // Clean up the promise
          resolve(true)
        })
      })
    }

    textureLoadingPromises.delete(assetData.key) // Clean up the promise
    return Promise.resolve(false)
  })()

  // Store the loading promise
  textureLoadingPromises.set(assetData.key, loadingPromise)
  return loadingPromise
}

export async function loadSpriteTextures(scene: Phaser.Scene, sprite: Sprite) {
  if (!sprite) return

  const sprite_actions = await fetch(config.server_endpoint + '/assets/list_sprite_actions/' + sprite?.id).then((response) => response.json())
  for await (const sprite_action of sprite_actions) {
    await loadTexture(scene, {
      key: sprite_action.key,
      data: sprite_action.data,
      group: sprite_action.isAnimated ? 'sprite_animations' : 'sprites',
      updatedAt: sprite_action.updatedAt,
      originX: sprite_action.originX ?? 0,
      originY: sprite_action.originY ?? 0,
      isAnimated: sprite_action.isAnimated,
      frameWidth: sprite_action.frameWidth,
      frameHeight: sprite_action.frameHeight,
      frameRate: sprite_action.frameRate,
      frameCount: sprite_action.frameCount
    } as AssetDataT)

    // If the sprite is not animated, skip
    if (!sprite_action.isAnimated) continue

    // Check if animation already exists
    if (scene.anims.get(sprite_action.key)) continue

    // Add the animation to the scene
    const anim = scene.textures.get(sprite_action.key)
    scene.textures.addSpriteSheet(sprite_action.key, anim, { frameWidth: sprite_action.frameWidth ?? 0, frameHeight: sprite_action.frameHeight ?? 0 })
    scene.anims.create({
      key: sprite_action.key,
      frameRate: sprite_action.frameRate,
      frames: scene.anims.generateFrameNumbers(sprite_action.key, { start: 0, end: sprite_action.frameCount! - 1 }),
      repeat: -1
    })
  }
  return Promise.resolve(true)
}
