<script setup lang="ts">
import { LinePath as svgdomarrowsLinePath } from 'svg-dom-arrows'

defineProps<{
  tree: ItemTree
  parentCount?: number
}>()

const emit = defineEmits<{
  mount: [end: Element]
  refresh: []
}>()

const { data: items } = useFetch<Array<{ id: number; iconPath: string }>>('/api/cdragon/items', {
  lazy: true, // Don't block rendering
  server: false // Client-side only
})

// Create item map reactively
const itemMap = reactive(new Map<number, { id: number; iconPath: string }>())
watch(
  items,
  newItems => {
    if (newItems) {
      itemMap.clear()
      for (const item of newItems) {
        itemMap.set(item.id, item)
      }
    }
  },
  { immediate: true }
)

function getItemIconPath(itemId: number): string {
  const item = itemMap.get(itemId)
  return item ? CDRAGON_BASE + mapPath(item.iconPath) : ''
}

const start: Ref<Element | null> = useTemplateRef('start')
const arrows: Array<svgdomarrowsLinePath> = []

onMounted(() => {
  // Only refresh arrows and emit if start element is available
  if (start.value) {
    refreshArrows()
    emit('mount', start.value)
  }
})

onBeforeUpdate(() => {
  for (const arrow of arrows) {
    arrow.release()
  }
  arrows.splice(0, arrows.length)
})

onUpdated(() => {
  if (start.value) {
    refreshArrows()
    emit('mount', start.value)
  }
})

onUnmounted(() => {
  for (const arrow of arrows) {
    arrow.release()
  }
})

function drawArrow(start: Element, end: Element) {
  if (start == null || end == null) return

  const arrow = new svgdomarrowsLinePath({
    start: {
      element: start,
      position: {
        top: 0.5,
        left: 1
      }
    },
    end: {
      element: end,
      position: {
        top: 0.5,
        left: 0
      }
    },
    style: 'stroke:var(--color-on-surface);stroke-width:2;fill:transparent;',
    appendTo: document.body
  })
  arrows.push(arrow)
  // Redraw immediately after creation to ensure correct position
  requestAnimationFrame(() => {
    arrow.redraw()
  })
}

function refreshArrows() {
  for (const arrow of arrows) {
    arrow.redraw()
  }
}

// Redraw arrows on window resize
addEventListener('resize', _ => {
  refreshArrows()
})
addEventListener('scroll', _ => {
  refreshArrows()
})

function handleSubtreeMount(end: Element) {
  if (start.value) {
    drawArrow(start.value, end)
    refreshArrows()
  }
  emit('refresh')
}
function handleRefresh() {
  refreshArrows()
  emit('refresh')
}
</script>

<template>
  <div class="item-tree-container">
    <div v-if="tree.data != undefined && tree.data != null" class="item-tree-node">
      <img
        ref="start"
        class="item-tree-img"
        :alt="tree.data.toString()"
        :src="getItemIconPath(tree.data)"
      />
      <span class="item-tree-pickrate">{{ ((tree.count / parentCount!!) * 100).toFixed(0) }}%</span>
    </div>

    <div class="item-tree-children">
      <div v-for="child in tree.children" :key="child.data" class="item-tree-child">
        <ItemTree
          :tree="child"
          :parent-count="tree.count"
          @refresh="handleRefresh"
          @mount="end => handleSubtreeMount(end)"
        />
      </div>
    </div>
  </div>
</template>

<style>
.item-tree-container {
  display: flex;
  align-items: center;
  justify-content: flex-start;
}

.item-tree-node {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: fit-content;
}

.item-tree-img {
  width: 48px;
  height: 48px;
  border-radius: 4px;
  border: 1px solid var(--color-on-surface);
}

.item-tree-pickrate {
  font-size: 0.65rem;
  color: var(--color-on-surface);
  opacity: 0.6;
  margin-top: 2px;
}

.item-tree-children {
  margin-left: 32px;
}

.item-tree-child {
  width: fit-content;
}

@media only screen and (max-width: 900px) {
  .item-tree-img {
    width: 40px;
    height: 40px;
  }

  .item-tree-children {
    margin-left: 20px;
  }
}
</style>
