<template>
  <!-- Activity List -->
  <div
    class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 w-full h-full"
  >
    <div class="flex justify-between items-center my-2 flex-wrap">
      <p class="h2">Activity List&nbsp;({{ data.length }})</p>
    </div>
    <!-- Table -->
    <div
      class="overflow-y-auto overflow-x-auto scrollbar -mx-2 h-[calc(100%_-_64px)]"
    >
      <table
        class="border-separate border-spacing-x-2 table-auto min-w-full text-sm"
        :class="data.length === 0 ? 'h-full' : null"
      >
        <caption class="hidden">
          Activity List
        </caption>
        <thead class="sticky top-0 left-0 z-10 bg-neutral-10">
          <tr>
            <th
              class="text-start font-semibold leading-10 px-2 border-b border-neutral-500"
            >
              Activity
            </th>
            <th
              class="font-semibold leading-10 px-2 border-b border-neutral-500 text-start"
              colspan="3"
            >
              Occurrences
            </th>
          </tr>
        </thead>
        <Draggable
          :list="data"
          :group="{ name: 'activity', pull: 'clone', put: false }"
          itemKey="name"
          tag="tbody"
          animation="300"
          @end="onEnd"
          :fallbackTolerance="5"
          :forceFallback="true"
          :ghostClass="'ghostSelected'"
          :dragClass="'dragSelected'"
          :sort="false"
        >
          <template #item="{ element, index }">
            <tr
              @dblclick="moveActItem(index, element)"
              :class="listSequence.includes(element) ? 'text-primary' : ''"
            >
              <td class="px-4 py-2" :id="element.label">{{ element.label }}</td>
              <td class="px-4 py-2 w-24">
                <div
                  class="h-4 min-w-[96px] bg-neutral-300 rounded-sm overflow-hidden"
                >
                  <div
                    class="h-full bg-primary"
                    :style="progressWidth(element.occ_value)"
                  ></div>
                </div>
              </td>
              <td class="px-4 py-2 text-right">{{ element.occurrences }}</td>
              <td class="px-4 py-2 text-right">
                {{ element.occurrence_ratio }}
              </td>
            </tr>
          </template>
        </Draggable>
      </table>
    </div>
  </div>
  <!-- Sequence -->
  <div
    class="bg-neutral-10 border border-neutral-300 rounded-xl px-4 pb-4 w-full h-full relative text-sm"
  >
    <p class="h2 border-b border-500 my-2">
      Sequence&nbsp;({{ listSeq.length }})
    </p>
    <!-- No Data -->
    <div
      v-if="listSequence.length === 0"
      class="p-4 w-[calc(100%_-_32px)] h-5/6 flex justify-center items-center absolute"
    >
      <p class="text-neutral-500">
        Please drag and drop at least two activities here and sort.
      </p>
    </div>
    <!-- Have Data -->
    <div class="py-4 m-auto w-full h-[calc(100%_-_56px)]">
      <div
        class="w-full h-full overflow-y-auto overflow-x-auto scrollbar px-4 text-center listSequence"
      >
        <draggable
          class="h-full"
          :list="listSequence"
          :group="{ name: 'activity' }"
          itemKey="name"
          animation="300"
          :forceFallback="true"
          :fallbackTolerance="5"
          :dragClass="'!opacity-100'"
          @start="onStart"
          @end="onEnd"
          :component-data="getComponentData()"
          :ghostClass="'!opacity-0'"
        >
          <template #item="{ element, index }">
            <div>
              <div class="flex justify-center items-center">
                <div
                  class="w-full p-2 border border-primary rounded text-primary bg-neutral-10"
                  @dblclick="moveSeqItem(index, element)"
                >
                  <span>{{ element.label }}</span>
                </div>
                <span
                  class="material-symbols-outlined pl-1 cursor-pointer duration-300 hover:text-danger"
                  @click.stop="moveSeqItem(index, element)"
                  >close</span
                >
              </div>
              <span
                v-show="
                  index !== listSeq.length - 1 && index !== lastItemIndex - 1
                "
                class="pi pi-chevron-down !text-lg inline-block py-2 pr-7"
              ></span>
            </div>
          </template>
        </draggable>
      </div>
    </div>
  </div>
</template>
<script setup>
// The Lucia project.
// Copyright 2023-2026 DSP, inc.  All rights reserved.
// Authors:
//   chiayin.kuo@dsp.im (chiayin), 2023/1/31
/**
 * @module components/Discover/Map/Filter/ActAndSeq Activity list
 *   with drag-and-drop sequence builder for creating filter
 *   rules.
 */

import { ref, computed, watch } from "vue";
import { sortNumEngZhtwForFilter } from "@/module/sortNumEngZhtw.js";

const props = defineProps({
  filterTaskData: {
    type: Array,
    required: true,
  },
  progressWidth: {
    type: Function,
    required: false,
  },
  listSeq: {
    type: Array,
    required: true,
  },
});

const emit = defineEmits(["update:listSeq"]);

const listSequence = ref([]);
const filteredData = ref(props.filterTaskData);
const lastItemIndex = ref(null);

const data = computed(() => {
  // Sort the Activity List
  return [...filteredData.value].sort((x, y) => {
    const diff = y.occurrences - x.occurrences;
    return diff === 0 ? sortNumEngZhtwForFilter(x.label, y.label) : diff;
  });
});

watch(
  () => props.listSeq,
  (newval) => {
    listSequence.value = newval;
  },
);

watch(
  () => props.filterTaskData,
  (newval) => {
    filteredData.value = newval;
  },
);

/**
 * Moves an activity from the list to the sequence on double-click.
 * @param {number} index - The item index in the activity list.
 * @param {Object} element - The activity data object.
 */
function moveActItem(index, element) {
  listSequence.value.push(element);
}

/**
 * Removes an activity from the sequence on double-click.
 * @param {number} index - The item index in the sequence.
 * @param {Object} element - The activity data object.
 */
function moveSeqItem(index, element) {
  listSequence.value.splice(index, 1);
}

/** Emits the current sequence list to the parent component. */
function getComponentData() {
  emit("update:listSeq", listSequence.value);
}

/**
 * Handles drag start: hides original element and last arrow.
 * @param {Event} evt - The drag start event.
 */
function onStart(evt) {
  const lastChild = evt.to.lastChild.lastChild;
  lastChild.style.display = "none";
  // Hide the dragged element at its original position
  const originalElement = evt.item;
  originalElement.style.display = "none";
  // When dragging the last element, hide the arrow of the second-to-last element
  const listIndex = listSequence.value.length - 1;
  if (evt.oldIndex === listIndex) lastItemIndex.value = listIndex;
}

/**
 * Handles drag end: restores element visibility.
 * @param {Event} evt - The drag end event.
 */
function onEnd(evt) {
  // Show the dragged element
  const originalElement = evt.item;
  originalElement.style.display = "";
  // Show the arrow after drag ends, except for the last element
  const lastChild = evt.item.lastChild;
  const listIndex = listSequence.value.length - 1;
  if (evt.oldIndex !== listIndex) {
    lastChild.style.display = "";
  }
  // Reset: hide the second-to-last element's arrow when dragging the last element
  lastItemIndex.value = null;
}
</script>
<style scoped>
@reference "../../../../assets/tailwind.css";
.ghostSelected {
  @apply shadow-[0px_0px_100px_-10px_inset] shadow-neutral-200;
}
.dragSelected {
  @apply shadow-[0px_0px_4px_2px] bg-neutral-10 shadow-neutral-300 !opacity-100;
}
</style>
