import type { TextureData } from '@/application/types'
import { SpriteStorage } from '@/storage/storages'
import { TextureStorage } from '@/storage/textureStorage'
import { useGameStore } from '@/stores/gameStore'

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

export async function loadTexture(scene: Phaser.Scene, textureData: TextureData): Promise<boolean> {
  const gameStore = useGameStore()
  const textureStorage = new TextureStorage()

  // Check if the texture is already loaded in Phaser
  if (gameStore.game.loadedTextures.find((texture) => texture === textureData.key)) {
    return true
  }

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

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

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

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

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

    textureLoadingPromises.delete(textureData.key) // Clean up the promise
    return false
  })()

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

export async function loadSpriteTextures(scene: Phaser.Scene, sprite_id: string) {
  if (!sprite_id) return false

  const spriteStorage = new SpriteStorage()
  const sprite = await spriteStorage.get(sprite_id)

  if (!sprite) {
    console.error('Failed to load sprite:', sprite_id)
    return false
  }

  for await (const sprite_action of sprite.spriteActions) {
    const key = sprite.id + '-' + sprite_action.action
    await loadTexture(scene, {
      key,
      data: '/textures/sprites/' + sprite.id + '/' + sprite_action.action + '.png',
      group: sprite_action.frameCount > 1 ? 'sprite_animations' : 'sprites',
      updatedAt: sprite_action.updatedAt,
      originX: sprite_action.originX,
      originY: sprite_action.originY,
      frameWidth: sprite_action.frameWidth,
      frameHeight: sprite_action.frameHeight,
      frameRate: sprite_action.frameRate
    } as TextureData)

    // If the sprite has no more than one frame, skip
    if (sprite_action.frameCount <= 1) continue

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

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