import config from '@/application/config'
import type { TextureData } from '@/application/types'
import Dexie from 'dexie'

export class TextureStorage {
  private dexie: Dexie

  constructor() {
    this.dexie = new Dexie('textures')
    this.dexie.version(1).stores({
      textures: 'key, group'
    })
  }

  async download(texture: TextureData) {
    try {
      // Check if the texture already exists, then check if updatedAt is newer
      const _texture = await this.dexie.table('textures').get(texture.key)
      if (_texture && _texture.updatedAt > texture.updatedAt) {
        return
      }

      // Download the texture
      const response = await fetch(config.server_endpoint + texture.data)
      const blob = await response.blob()

      // Store the texture in the database
      await this.dexie.table('textures').put({
        key: texture.key,
        data: blob,
        group: texture.group,
        updatedAt: texture.updatedAt,
        originX: texture.originX,
        originY: texture.originY,
        frameRate: texture.frameRate,
        frameWidth: texture.frameWidth,
        frameHeight: texture.frameHeight,
        frameCount: texture.frameCount
      })
    } catch (error) {
      console.error(`Failed to add texture ${texture.key}:`, error)
    }
  }

  async get(key: string) {
    try {
      const texture = await this.dexie.table('textures').get(key)
      if (texture) {
        return {
          ...texture,
          data: URL.createObjectURL(texture.data) // Convert blob to data URL
        }
      }
    } catch (error) {
      console.error(`Failed to retrieve texture ${key}:`, error)
    }
    return null
  }

  async getByGroup(group: string) {
    try {
      const textures = await this.dexie.table('textures').where('group').equals(group).toArray()
      return textures.map((texture) => ({
        ...texture,
        data: URL.createObjectURL(texture.data) // Convert blob to data URL
      }))
    } catch (error) {
      console.error(`Failed to retrieve textures for group ${group}:`, error)
      return []
    }
  }

  async delete(key: string) {
    try {
      await this.dexie.table('textures').delete(key)
    } catch (error) {
      console.error(`Failed to delete texture ${key}:`, error)
    }
  }

  async reset() {
    try {
      await this.dexie.table('textures').clear()
    } catch (error) {
      console.error(`Failed to clear textures:`, error)
    }
  }

  async destroy() {
    try {
      await this.dexie.delete()
    } catch (error) {
      console.error(`Failed to destroy textures:`, error)
    }
  }
}
