<template>
  <div class="h-full flex flex-col relative">
    <div class="flex-shrink-0 flex order-1">
      <ObjectCardDropZone
          label="Benutzen"
          class="bg-green-800"
          :has-floating="useFloatingObjectIds.size > 0"
          @object-change="(v, i) => createSetInclusionSetter(useFloatingObjectIds)(v, i)"
          @object-drop="onObjectUseDrop"
      />
      <ObjectCardDropZone
          label="Kombinieren"
          class="bg-blue-900"
          :has-floating="combineFloatingObjectIds.size > 0"
          @object-change="(v, i) => createSetInclusionSetter(combineFloatingObjectIds)(v, i)"
          @object-drop="onObjectInteractionDrop"
      />
    </div>
    <transition-group tag="div" name="list" class="grid gap-3 grid-cols-2 flex-grow auto-rows-min p-4 pt-0 relative">
      <ObjectCard
          v-for="object in game.visibleObjectsById.values()"
          :key="object.id"
          :object="object"
          :is-over-dropzone="allFloatingObjectIds.has(object.id)"
          :marked-for="getMarkedFor(object.id)"
          @drag-start="onObjectDragStart"
          @drag-end="onObjectDragEnd"
      />
    </transition-group>
  </div>
</template>

<style module lang="scss">

</style>

<script setup lang="ts">
  import ObjectCard from "../components/ObjectCard.vue"
  import { useGame } from "../game"
  import { computed, reactive, ref } from "vue"
  import { useScrollLock } from "@vueuse/core"
  import ObjectCardDropZone from "../components/ObjectCardDropZone.vue"

  const game = useGame()

  const dragCounter = ref(0)

  const useFloatingObjectIds = reactive(new Set())
  const combineFloatingObjectIds = reactive(new Set())
  const allFloatingObjectIds = computed(() => new Set([...useFloatingObjectIds, ...combineFloatingObjectIds]))

  const firstCombinationObjectId = ref<null | string>(null)

  function createSetInclusionSetter<T>(set: Set<T>) {
    return (value: T, isIncluded: boolean) => {
      if (isIncluded) set.add(value)
      else set.delete(value)
    }
  }

  function getMarkedFor(objectId: string) {
    if (firstCombinationObjectId.value !== null) {
      if (firstCombinationObjectId.value === objectId) return "combine-first"
    } else if (game.currentInteraction !== null) {
      switch (game.currentInteraction.type) {
        case "use":
          if (game.currentInteraction.objectId === objectId) return "use"
          break

        case "combine":
          if (game.currentInteraction.objectIds.has(objectId)) return "combine"
          break
      }
    }

    return null
  }

  function onObjectDragStart() {
    dragCounter.value++
  }

  function onObjectDragEnd() {
    dragCounter.value--
    if (dragCounter.value <= 0) {
      // lock scrolling?
    }
  }

  function onObjectUseDrop(objectId: string) {
    game.voteForInteraction({
      type: "use",
      objectId
    })
  }

  function onObjectInteractionDrop(objectId: string) {
    if (firstCombinationObjectId.value === null) {
      game.revokeCurrentInteractionVote()
      firstCombinationObjectId.value = objectId
    } else {
      if (firstCombinationObjectId.value === objectId) {
        firstCombinationObjectId.value = null
        return
      }

      game.voteForInteraction({
        type: "combine",
        objectIds: new Set([firstCombinationObjectId.value, objectId])
      })

      firstCombinationObjectId.value = null
    }
  }
</script>