<template>
  <div
    class="nv-list"
    :class="[
      ...sizeableClasses,
      rounded,
      { dark: dark ?? parentDark, 'mini-level': parent?.mini },
    ]"
    :style="{ 'min-width': mini ? 0 : `${minWidth ?? parentMinWidth}px` }"
    v-click-outside="onClickOutside"
  >
    <div v-if="hasTitle" class="nv-list__title">
      <NvIcon
        v-if="icon"
        :icon="icon"
        :class="{ 'mr-4': ($slots.title || title) && !mini }"
      />
      <div v-if="!mini">
        <div v-if="title">{{ title }}</div>
        <slot name="title" />
      </div>
    </div>
    <slot name="default">
      <nv-list-item
        v-for="(item, idx) in items"
        :key="idx"
        :customClass="item.customClass"
        :disabled="item.disabled"
        :divider="item.divider"
        :hidden="item.hidden"
        :hotkey="item.hotkey"
        :icon="item.icon"
        :icon-right="item.iconRight"
        :list="item.list"
        :submenu="item.submenu"
        :target="item.target"
        :title="item.title"
        :to="item.to"
        :tooltip="item.tooltip"
      />
    </slot>
  </div>
</template>

<script>
import useSize from "../../composables/sizeable";
import { computed, inject } from "vue";

export default {
  name: "NvList",

  props: {
    absolute: { type: Boolean, default: undefined },
    accordeon: { type: Boolean, default: undefined },
    customClass: { type: String, default: undefined },
    dark: { type: Boolean, default: undefined },
    icon: { type: String, default: "" },
    items: { type: Array, default: () => [] },
    minWidth: { type: Number, default: undefined },
    multiple: { type: Boolean, default: undefined },
    noAction: { type: Boolean, default: undefined },
    size: { type: String, default: "md" },
    title: { type: String, default: "" },
  },

  inject: {
    mini: { default: false },
    parentAbsolute: { default: false },
    parentAccordeon: { default: false },
    parentActiveItems: { default: undefined },
    parentCustomClass: { default: "" },
    parentDark: { default: false },
    parentMinWidth: { default: 200 },
    parentMultiple: { default: false },
    parentNoAction: { default: false },
    parentOpenItems: { default: undefined },
    parentRounded: { default: undefined },
    parentItemRounded: { default: undefined },
  },

  data: () => {
    return {
      activeItems: [],
      id: "",
      children: [],
      openItems: [],
    };
  },

  provide() {
    return {
      parentAbsolute: this.absolute ?? this.parentAbsolute,
      parentAccordeon: this.accordeon ?? this.parentAccordeon,
      parentActiveItems: computed(
        () => this.parentActiveItems ?? this.activeItems
      ),
      parentCustomClass: this.customClass ?? this.parentCustomClass,
      parentDark: this.dark ?? this.parentDark,
      parentItemRounded: computed(() => this.rounded),
      parentMinWidth: this.minWidth ?? this.parentMinWidth,
      parentMultiple: this.multiple ?? this.parentMultiple,
      parentNoAction: computed(() => this.noAction ?? this.parentNoAction),
      parentOpenItems: computed(() => this.parentOpenItems ?? this.openItems),
      parentRounded: computed(() => this.parentRounded ?? this.rounded),
      parentSize: computed(() => this.parentSize ?? this.size),
    };
  },

  computed: {
    hasTitle() {
      return this.icon || this.title || this.$slots.title;
    },

    rounded() {
      if (this.parentItemRounded) return this.parentItemRounded;
      let rounded = this.parentRounded ?? "";
      let result = this.$attrs.class;
      if (result) {
        result = result
          .split(" ")
          .filter((c) => c.includes("rounded"))
          .join(" ");
        if (result) rounded = result;
      }
      return rounded;
    },
  },

  watch: {
    activeItems() {
      if (!this.parent) return;
      this.parent.activeItems = [...this.activeItems];
    },
    openItems() {
      if (!this.parent) return;
      this.parent.openItems = [...this.openItems];
    },

    "$route.path"() {
      this.activeItems = [];
    },
  },

  created() {
    this.getParent();
    if (this.parent) {
      this.id = `${this.parent.id ?? 0}/`;
    }
  },

  methods: {
    onClickOutside() {
      if (this.mini || (this.absolute ?? this.parentAbsolute)) {
        this.openItems = [];
      }
    },

    getParent() {
      let component = null;
      let parent = this.$parent;
      while (parent && !component) {
        if (
          parent.$options.name === "NvListItem" ||
          parent.$options.name === "NvNavigationDrawer"
        ) {
          component = parent;
        }
        parent = parent.$parent;
      }
      this.parent = component;
    },
  },

  setup(props) {
    const parentSize = inject("parentSize", undefined);
    const { sizeableClasses } = useSize({
      size: parentSize || props.size,
    });

    return { parentSize, sizeableClasses };
  },
};
</script>

<style lang="scss" scoped>
.nv-list {
  @apply bg-white;

  &.dark {
    @apply bg-black text-white;
  }
}

.nv-list__title {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 5px 20px;
}

.nv-navigation-drawer .nv-list__title {
  @apply min-h-[64px] font-semibold;
}

::-webkit-scrollbar {
  @apply w-0;
}

.nv-navigation-drawer__content > .nv-list {
  @apply w-full;
}

.nv-navigation-drawer.left .nv-list .nv-list.mini-level {
  @apply left-[64px] shadow-md fixed top-0 h-screen overflow-y-auto pt-[64px];
}

.nv-navigation-drawer.right .nv-list .nv-list.mini-level {
  @apply left-auto right-[64px];
}
</style>
