import config from '@/application/config'
import type { Tile } from '@/application/types'
import type { TileAnalysisResult, TileWorkerMessage } from '@/types/tileTypes'
import { ref } from 'vue'

// Constants for image processing
const DOWNSCALE_WIDTH = 32
const DOWNSCALE_HEIGHT = 16
const COLOR_SIMILARITY_THRESHOLD = 30
const EDGE_SIMILARITY_THRESHOLD = 20
const BATCH_SIZE = 4

export function useTileProcessingComposable() {
  const tileAnalysisCache = ref<Map<string, { color: { r: number; g: number; b: number }; edge: number; namePrefix: string }>>(new Map())
  const processingQueue = ref<Tile[]>([])
  let isProcessing = false
  const worker = new Worker(new URL('@/workers/tileAnalyzerWorker.ts', import.meta.url), { type: 'module' })

  worker.onmessage = (e: MessageEvent<TileAnalysisResult>) => {
    const { tileId, color, edge, namePrefix } = e.data
    tileAnalysisCache.value.set(tileId, { color, edge, namePrefix })
    isProcessing = false
    processBatch()
  }

  async function processTileAsync(tile: Tile): Promise<void> {
    if (tileAnalysisCache.value.has(tile.id)) return

    return new Promise((resolve) => {
      const img = new Image()
      img.crossOrigin = 'Anonymous'
      img.onload = () => {
        const canvas = document.createElement('canvas')
        const ctx = canvas.getContext('2d')
        if (!ctx) {
          resolve()
          return
        }

        canvas.width = DOWNSCALE_WIDTH
        canvas.height = DOWNSCALE_HEIGHT
        ctx.drawImage(img, 0, 0, DOWNSCALE_WIDTH, DOWNSCALE_HEIGHT)

        const imageData = ctx.getImageData(0, 0, DOWNSCALE_WIDTH, DOWNSCALE_HEIGHT)
        const message: TileWorkerMessage = {
          imageData,
          tileId: tile.id,
          tileName: tile.name
        }
        worker.postMessage(message)
        resolve()
      }
      img.onerror = () => resolve()
      img.src = `${config.server_endpoint}/textures/tiles/${tile.id}.png`
    })
  }

  function processBatch() {
    if (isProcessing || processingQueue.value.length === 0) return
    isProcessing = true

    const batch = processingQueue.value.splice(0, BATCH_SIZE)
    Promise.all(batch.map((tile) => processTileAsync(tile))).then(() => {
      isProcessing = false
      if (processingQueue.value.length > 0) {
        setTimeout(processBatch, 0)
      }
    })
  }

  function processTile(tile: Tile) {
    if (!processingQueue.value.includes(tile)) {
      processingQueue.value.push(tile)
      processBatch()
    }
  }

  function areTilesRelated(tile1: Tile, tile2: Tile): boolean {
    const data1 = tileAnalysisCache.value.get(tile1.id)
    const data2 = tileAnalysisCache.value.get(tile2.id)

    if (!data1 || !data2) return false

    const colorDifference = Math.sqrt(Math.pow(data1.color.r - data2.color.r, 2) + Math.pow(data1.color.g - data2.color.g, 2) + Math.pow(data1.color.b - data2.color.b, 2))

    return colorDifference <= COLOR_SIMILARITY_THRESHOLD && Math.abs(data1.edge - data2.edge) <= EDGE_SIMILARITY_THRESHOLD && data1.namePrefix === data2.namePrefix
  }

  function cleanup() {
    worker.terminate()
  }

  return {
    processTile,
    areTilesRelated,
    cleanup
  }
}
