<template>
  <div>
    <slot></slot>
    <div
      :class="[isDisabled ? 'opacity-50' : '', buttonWrapperClass]"
      class="relative inline-block text-left"
    >
      <button
        ref="selectBorderButton"
        :type="type"
        class="h-9 inline-flex w-full justify-center border px-3 py-2 text-sm font-medium shadow-sm focus:outline-none disabled:cursor-not-allowed"
        :style="computedStyles"
        :class="[
          classes,
          buttonClass,
          type !== 'white' ? 'border-transparent' : '',
        ]"
        :aria-label="label"
        aria-haspopup="listbox"
        aria-expanded="true"
        aria-labelledby="listbox-label"
        :id="id"
        :disabled="isDisabled"
        @click="toggleDropdown = !toggleDropdown"
      >
        <c-icon v-if="isLoading" class="mr-2 h-5 w-5" name="loader"></c-icon>

        <c-icon
          v-if="labelIcon"
          :type="labelIcon.type"
          :class="labelIcon.class"
          :name="labelIcon.name"
          :viewBox="labelIcon.viewBox"
          cursorType="pointer"
        ></c-icon>

        <p v-if="label">{{ label }}</p>

        <c-icon
          name="chevron-down"
          type="solid"
          :class="['ml-2 h-5 w-5', iconClass]"
          cursorType="pointer"
        ></c-icon>
      </button>

      <div
        v-if="toggleDropdown"
        ref="selectBorderDropdown"
        :class="[
          getDropdownPosition,
          dropdownPositionClass,
          shouldOpenAbove ? 'mb-2' : 'mt-2',
        ]"
        class="absolute z-10 -mr-1 w-56 rounded-md bg-white shadow-lg ring-1 ring-gray-900 ring-opacity-5"
      >
        <ul
          class="py-1"
          tabindex="-1"
          role="listbox"
          aria-labelledby="listbox-label"
        >
          <div v-for="(item, index) in items" :key="index">
            <!-- to have a border pass a object { hasNoData: true } after the object
            below which the border is required -->
            <hr
              v-if="item.hasNoData"
              class="border-1 mt-1 h-1 w-full border-gray-200 pt-1"
            />
            <!-- item.isDisabled will make the list item unclickable and reduce the opacity -->
            <li
              v-else
              :class="[
                item.isDisabled ? 'pointer-events-none opacity-50 ' : '',
                item.itemClass,
              ]"
              :id="getActionIDFn(item.text)"
              class="flex cursor-pointer px-3 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900"
              @mousedown="emitOption(item)"
            >
              <c-icon
                v-if="item.icon"
                :type="item.iconType"
                :class="['mr-2 h-5 w-5 text-gray-400', item.iconClass]"
                :name="item.icon"
                :viewBox="item.iconViewBox"
              ></c-icon>
              <slot name="customIcon" v-if="item.customIcon"></slot>
              <p :class="[item.itemClass]">{{ item.text }}</p>
            </li>
          </div>
        </ul>
      </div>
    </div>
  </div>
</template>

<script>
import { getActionID } from "../../helper";
import { COLOR_CONFIG } from "../../colorConfig";
import CIcon from "../CIcon/CIcon.vue";
export default {
  name: "CButtonSelectBorder",
  components: { CIcon },
  props: {
    label: {
      type: String,
      required: true,
    },
    id: {
      type: String,
    },
    type: {
      type: String,
      default: "primary",
    },
    items: {
      type: Array,
      required: true,
    },
    isLoading: {
      type: Boolean,
      default: false,
    },
    dropdownPositionClass: {
      type: String,
    },
    isDisabled: {
      type: Boolean,
      default: false,
    },
    buttonWrapperClass: {
      type: String,
      default: "",
    },
    buttonClass: {
      type: String,
      default: "",
    },
    labelIcon: {
      type: Object,
    },
    iconClass: {
      type: String,
    },
    preferredColor: {
      type: String,
      default: "indigo",
    },
  },
  data() {
    return {
      toggleDropdown: false,
      shouldOpenAbove: false,
    };
  },

  computed: {
    classes() {
      return {
        "text-gray-700 border-gray-300 rounded-md border-transparent hover:bg-gray-50 focus:ring-indigo-600":
          this.type == "secondary",
        "text-white rounded-md border-transparent primary-button-classes":
          this.type == "primary",
        "text-white rounded-md  hover:bg-red-800 bg-red-700 border-transparent focus:ring-red-600":
          this.type == "danger",
        "text-white rounded-md hover:bg-green-800 bg-green-700 border-transparent focus:ring-green-600":
          this.type == "success",
        "cursor-default rounded-md border-transparent pointer-events-none":
          this.isLoading,
        //the type-white property contains the class rounded-r-md that would only round the button corner in the right direction
        //while the other type property will round the button corners for all 4 direction
        "text-gray-700 border-gray-300 rounded-r-md border-transparent hover:bg-gray-50 focus:ring-indigo-600 bg-white":
          this.type == "white-rounded-right",
        "text-gray-700 border bg-white border-gray-300 rounded-md hover:bg-gray-50 focus:ring-indigo-600":
          this.type == "white",
        "bg-gray-900 text-white hover:bg-gray-800 rounded-md focus:ring-gray-700":
          this.type == "dark-blue",
        "text-gray-700 bg-white rounded-md shadow-none hover:bg-gray-100 focus:ring-0":
          this.type == "white-plain",
      };
    },
    computedStyles() {
      const colors = COLOR_CONFIG[this.preferredColor] || COLOR_CONFIG.indigo;
      return {
        "--primary-background-color": colors.shade700,
        "--primary-background-color-hover": colors.shade800,
        "--primary-ring-color": colors.shade600,
      };
    },
    getDropdownPosition() {
      return this.shouldOpenAbove ? "bottom-full" : "top-full";
    },
  },
  methods: {
    getActionIDFn(name) {
      return getActionID(name, this.id);
    },
    checkAvailableSpace() {
      if (!this.$refs.selectBorderButton) return false;

      const button = this.$refs.selectBorderButton;
      const rect = button.getBoundingClientRect();
      const viewportHeight = window.innerHeight;
      const bottomSpace = viewportHeight - rect.bottom;
      const dropdown = this.$refs.selectBorderDropdown;
      const componentHeight = dropdown
        ? dropdown.getBoundingClientRect().height
        : 0;

      // Check if bottom space is less than 80% of the component height
      return bottomSpace < (componentHeight * 4) / 5;
    },
    emitOption(item) {
      this.$emit("buttonActions", item);
      this.close();
    },
    close() {
      this.toggleDropdown = false;
    },
    handleClickOutside(event) {
      const dropdown = this.$refs.selectBorderDropdown;
      const button = this.$refs.selectBorderButton;

      if (
        dropdown &&
        !dropdown.contains(event.target) &&
        button &&
        !button.contains(event.target)
      ) {
        this.close();
      }
    },
  },
  watch: {
    toggleDropdown(newVal) {
      if (newVal) {
        // Recalculate position when dropdown opens
        this.$nextTick(() => {
          this.shouldOpenAbove = this.checkAvailableSpace();
        });
      }
    },
  },
  mounted() {
    document.addEventListener("mousedown", this.handleClickOutside);
  },
  beforeDestroy() {
    document.removeEventListener("mousedown", this.handleClickOutside);
  },
};
</script>

<style scoped>
.primary-button-classes {
  background-color: var(--primary-background-color);
}
.primary-button-classes:hover {
  background-color: var(--primary-background-color-hover);
}
.primary-button-classes:focus {
  outline: none;
  box-shadow: 0 0 0 2px white, 0 0 0 4px var(--primary-ring-color) !important;
}
</style>
