<template>
  <div :class="`relative ${mainCustomClass}`" ref="dropdownRoot">
    <button
      class="relative flex h-9 w-max cursor-pointer items-center justify-between gap-2 rounded-md border border-gray-300 bg-white p-2 hover:bg-gray-100"
      @click="handleToggleDropdown"
      @mouseenter="showTooltip(true)"
      @mouseleave="showTooltip(false)"
      @focus="showTooltip(true)"
      @blur="showTooltip(false)"
    >
      <c-icon
        type="solid"
        name="funnel-mini"
        class="h-5 w-5 text-gray-400"
        cursorType="cursor-pointer"
        viewBox="0 0 22 22"
      ></c-icon>
      <p
        v-if="filterSelected"
        class="flex items-center justify-center rounded-full border border-gray-200 bg-gray-50 px-2.5 text-sm text-gray-700"
      >
        {{ filterSelected }}
      </p>
      <c-icon
        v-if="!filterSelected"
        name="chevron-down"
        type="solid"
        class="h-5 w-5 text-gray-400"
        cursorType="cursor-pointer"
      ></c-icon>
      <c-tool-tip
        v-if="hasToolTip && displayTooltip"
        :tooltipText="tooltipText"
        :isTopAligned="true"
        color="#1f2937"
        classes="text-white absolute -mt-12 whitespace-nowrap top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 font-normal  bg-gray-800 w-auto"
      ></c-tool-tip>
    </button>
    <div
      v-if="toggleDropdown"
      :class="`absolute top-11 ${
        menuDirection === 'left' ? 'left-0' : 'right-0'
      } z-50 flex w-56 rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5`"
    >
      <div class="my-1 w-56">
        <button
          v-for="(option, index) in options"
          :key="index"
          class="relative w-56 hover:bg-gray-100 focus:bg-gray-100"
          @mouseenter="handleMainOptionMouseEnter(option, index)"
          @mouseleave="closeSubmenuWithDelay"
          @focus="handleMainOptionMouseEnter(option, index)"
        >
          <div
            class="group flex cursor-pointer items-center justify-between px-3 py-2 text-sm text-gray-700"
          >
            <div class="flex items-center gap-1">
              <p class="text-sm text-gray-900">
                {{ option.label }}
              </p>
              <p
                v-if="option.selectedOptionCount"
                class="flex items-center justify-center rounded-full border border-gray-200 bg-gray-50 px-2.5"
              >
                {{ option.selectedOptionCount }}
              </p>
            </div>
            <c-icon
              v-if="hasSubOptions(option)"
              name="chevron-right-mini-v2"
              type="solid"
              class="h-5 w-5 text-gray-400"
              cursorType="cursor-pointer"
            ></c-icon>
          </div>
          <div
            v-if="activeOptionIndex === index && hasSubOptions(option)"
            :class="`absolute top-0 ${
              effectiveSubmenuDirection === 'right'
                ? 'left-full ml-2'
                : 'right-full mr-2'
            }`"
            style="z-index: 60"
            @mouseenter="clearSubmenuCloseTimeout"
          >
            <template v-if="option.hasSearch">
              <c-input
                @input="(value) => handleSearchInput(index, value)"
                @focus="handleSearchFocus(index)"
                @blur="handleSearchBlur"
                :value="option.searchTerm"
                :isValidate="true"
                :placeholder="option.searchPlaceholder"
                :inputWrapperClass="'rounded-md shadow-sm'"
                type="text"
                :id="getActionIDFn(option.label)"
                :isSearchEnabled="true"
              ></c-input>
            </template>
            <div
              class="max-h-48 w-56 overflow-auto rounded-md bg-white py-1 shadow-lg ring-1 ring-gray-900 ring-opacity-5"
              :class="option.hasSearch ? 'mt-1' : ''"
            >
              <div
                v-for="(sub, subIdx) in option.options"
                :key="subIdx"
                tabindex="0"
                class="flex cursor-pointer items-center py-2 px-3 text-left hover:bg-gray-100 focus:bg-gray-100"
                :class="option.showUserAvatar ? '' : 'gap-3'"
                @click="selectFilter(sub.isSelected ? 0 : 1, index, subIdx)"
                @keydown.enter="
                  selectFilter(sub.isSelected ? 0 : 1, index, subIdx)
                "
              >
                <c-checkbox
                  :value="sub.isSelected"
                  setMarginLeft="ml-0"
                ></c-checkbox>
                <c-avatar
                  v-if="option.showUserAvatar"
                  class="mr-2 ml-3"
                  size="extraextraextrasmall"
                  :image="sub.image_240"
                  :nameInitials="sub.initials"
                  :rounded="true"
                ></c-avatar>
                <p class="text-sm text-gray-700">{{ sub.label }}</p>
              </div>
              <div
                v-if="
                  option.hasSearch &&
                  option.searchTerm &&
                  option.options.length == 0
                "
                class="items-center justify-center text-sm text-gray-500"
              >
                {{
                  option.noResultsText ||
                  "We couldn't find anyone. Try searching a different name."
                }}
              </div>
            </div>
          </div>
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import CIcon from "../CIcon/CIcon.vue";
import CToolTip from "../CToolTip/CToolTip.vue";
import CCheckbox from "../CCheckbox/CCheckbox.vue";
import CInput from "../CInput/CInput.vue";
import CAvatar from "../CAvatar/CAvatar.vue";
import { getActionID } from "../../helper";
export default {
  name: "CGroupedFilterDropdown",
  components: { CIcon, CToolTip, CCheckbox, CInput, CAvatar },
  props: {
    mainCustomClass: {
      type: String,
      default: "",
    },
    tooltipText: {
      type: String,
      default: "",
    },
    submenuDirection: {
      type: String,
      default: "right",
    },
    menuDirection: {
      type: String,
      default: "right",
    },
    options: {
      type: Array,
      required: true,
      default: () => [],
    },
    hasToolTip: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    return {
      toggleDropdown: false,
      activeOptionIndex: null,
      submenuCloseTimeout: null,
      subMenuLocked: false,
      displayTooltip: false,
      internalSubmenuDirection: null,
    };
  },
  computed: {
    filterSelected() {
      return this.options.filter((option) => option.selectedOptionCount).length;
    },
    effectiveSubmenuDirection() {
      return this.internalSubmenuDirection || this.submenuDirection;
    },
  },
  methods: {
    isFocusInsideDropdown() {
      const root = this.$refs.dropdownRoot;
      const activeEl = document.activeElement;
      return !!(root && activeEl && root.contains(activeEl));
    },
    showTooltip(value) {
      this.displayTooltip = value;
    },
    handleToggleDropdown() {
      this.toggleDropdown = !this.toggleDropdown;
      if (this.toggleDropdown) {
        this.updateEventListeners();
      } else {
        document.removeEventListener("click", this.handleClickOutside);
        this.internalSubmenuDirection = null;
      }
    },
    getActionIDFn(name) {
      return getActionID(name, "filter_search");
    },
    closeSubmenuWithDelay() {
      if (!this.subMenuLocked && !this.isFocusInsideDropdown()) {
        this.submenuCloseTimeout = setTimeout(() => {
          this.activeOptionIndex = null;
          this.subMenuLocked = false;
        }, 200);
      }
    },
    computeSubmenuDirection() {
      try {
        const rootEl = this.$refs.dropdownRoot;
        if (!rootEl) {
          this.internalSubmenuDirection = null;
          return;
        }
        const rect = rootEl.getBoundingClientRect();
        const viewportWidth =
          window.innerWidth || document.documentElement.clientWidth;
        const rightSpace = viewportWidth - rect.right;
        const submenuWidthPx = 224 + 8;
        this.internalSubmenuDirection =
          rightSpace < submenuWidthPx ? "left" : "right";
      } catch (e) {
        this.internalSubmenuDirection = null;
      }
    },
    handleMainOptionMouseEnter(option, index) {
      this.clearSubmenuCloseTimeout();
      if (this.subMenuLocked && this.activeOptionIndex !== index) {
        this.subMenuLocked = false;
        this.activeOptionIndex = index;
      } else if (!this.subMenuLocked && this.hasSubOptions(option))
        this.activeOptionIndex = index;
      else this.activeOptionIndex = index;
      if (this.hasSubOptions(option)) {
        this.computeSubmenuDirection();
      }
    },
    hasSubOptions(option) {
      if (
        !option ||
        !option.options ||
        !Array.isArray(option.options) ||
        (!option.options.length && !option.hasSearch)
      )
        return false;
      return true;
    },
    clearSubmenuCloseTimeout() {
      if (this.submenuCloseTimeout) {
        clearTimeout(this.submenuCloseTimeout);
        this.submenuCloseTimeout = null;
      }
    },
    selectFilter(value, index, subIdx) {
      this.options[index].options[subIdx].isSelected = value ? true : false;
      if (value) {
        this.options[index].selectedOptionCount++;
      } else {
        this.options[index].selectedOptionCount--;
      }
      this.$emit(
        "filter-changed",
        this.options[index].options[subIdx].isSelected,
        this.options[index].label,
        this.options[index].options[subIdx],
        this.options[index].selectedOptionCount,
      );
    },
    handleClickOutside(event) {
      if (
        this.$refs.dropdownRoot &&
        !this.$refs.dropdownRoot.contains(event.target)
      ) {
        this.activeOptionIndex = null;
        this.subMenuLocked = false;
        this.toggleDropdown = false;
        this.internalSubmenuDirection = null;
        document.removeEventListener("click", this.handleClickOutside);
      }
    },
    updateEventListeners() {
      document.addEventListener("click", this.handleClickOutside);
    },
    handleSearchInput(index, value) {
      this.$emit("search-input", index, value);
    },
    handleSearchFocus(index) {
      this.clearSubmenuCloseTimeout();
      this.subMenuLocked = true;
      this.activeOptionIndex = index;
    },
    handleSearchBlur() {
      this.$nextTick(() => {
        this.subMenuLocked = false;
        if (!this.isFocusInsideDropdown()) {
          this.closeSubmenuWithDelay();
        }
      });
    },
  },
  beforeDestroy() {
    document.removeEventListener("click", this.handleClickOutside);
  },
};
</script>
