<template>
  <div
    v-if="!hidden"
    class="nv-expansion-panel"
    :class="[
      rounded,
      {
        dark: parentDark ?? dark,
        disabled: disabled,
        opened: opened,
      },
    ]"
  >
    <div
      v-if="hasTitle"
      class="nv-expansion-panel__title"
      :class="[
        customClass,
        parentCustomClass,
        rounded,
        {
          'rounded-b-none': computedOpened,
        },
      ]"
      @click="click"
    >
      <NvIcon v-if="icon" :icon="icon" class="nv-expansion-panel__icon" />
      <div class="nv-expansion-panel__title-content">
        <div
          class="nv-expansion-panel__title-text"
          :class="{ icon: icon, 'icon-right': iconRight }"
        >
          <div v-if="title">{{ title }}</div>
          <slot name="title" />
        </div>
        <NvIcon
          v-if="iconRight"
          :icon="iconRight"
          class="nv-expansion-panel__icon-right"
        />
        <NvIcon
          icon="nvi-chevron-right"
          class="nv-expansion-panel__title-arrow"
        />
      </div>
    </div>
    <div
      ref="content"
      v-show="computedOpened"
      class="nv-expansion-panel__content rounded-t-none"
      :class="rounded"
    >
      <slot name="default"> </slot>
    </div>
  </div>
</template>

<script>
export default {
  name: "NvExpansionPanel",

  props: {
    customClass: { type: String, default: undefined },
    dark: Boolean,
    disabled: Boolean,
    hidden: Boolean,
    icon: { type: String, default: "" },
    iconRight: { type: String, default: "" },
    title: { type: String, default: "" },
  },

  inject: {
    parentAccordeon: { default: false },
    parentCustomClass: { default: "" },
    parentDark: { default: undefined },
    parentOpenItems: { default: [] },
    parentRounded: { default: "" },
  },

  data: () => {
    return {
      active: false,
      computedOpened: false,
      id: "",
      parent: null,
    };
  },

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

    opened() {
      return this.parent ? this.parentOpenItems.includes(this.id) : this.active;
    },

    rounded() {
      let result = this.$attrs.class;
      if (result) {
        result = result
          .split(" ")
          .filter((c) => c.includes("rounded"))
          .join(" ");
        console.log("|" + result + "|");
        if (result) return result;
      }

      let rounded = "";
      if (this.parent) {
        rounded = this.parentRounded;
        const index = this.parent.children.indexOf(this.id);
        if (!this.opened) {
          if (
            index !== 0 &&
            !this.parentOpenItems.includes(this.parent.children[index - 1])
          ) {
            rounded += " rounded-t-none";
          }
          if (
            index !== this.parent.children.length - 1 &&
            !this.parentOpenItems.includes(this.parent.children[index + 1])
          ) {
            rounded += " rounded-b-none";
          }
        }
      }
      return rounded;
    },
  },

  watch: {
    opened() {
      if (this.opened) {
        this.computedOpened = this.opened;
        this.$nextTick(() => {
          this.openAnimation();
        });
      } else {
        this.closeAnimation();
        const content = this.$refs.content;
        const height = content.clientHeight;
        const duration = Math.max(0.2, (height / 500) * 0.2); // 0.2s на каждые 500 пикс
        setTimeout(() => {
          this.computedOpened = this.opened;
        }, duration * 1000);
      }
    },
  },

  created() {
    this.getParent();
    if (this.parent) {
      this.id = `${this.parent.id}${this.parent.children.length}`;
      this.parent.children.push(this.id);
    }
  },

  methods: {
    click() {
      if (this.disabled) return;
      if (this.opened) {
        this.closeItem();
      } else {
        this.openItem();
      }
    },

    closeAnimation() {
      const content = this.$refs.content;
      const height = content.clientHeight;
      const duration = Math.max(0.2, (height / 500) * 0.2); // 0.2s на каждые 500 пикс
      content.style.height = `${height}px`;
      setTimeout(() => {
        content.style.transition = `height ${duration}s ease-out`;
        content.style.height = 0;
        setTimeout(() => {
          content.style.transition = "none";
          content.style.height = "auto";
        }, duration * 1000);
      }, 0);
    },

    closeItem() {
      if (this.parent) {
        this.parent.openItems = this.parent.openItems.filter(
          (i) => i !== this.id
        );
      } else {
        this.active = false;
      }
    },

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

    openAnimation() {
      const content = this.$refs.content;
      const height = content.clientHeight;
      const duration = Math.max(0.2, (height / 500) * 0.2); // 0.2s на каждые 500 пикс
      content.style.height = 0;
      setTimeout(() => {
        content.style.transition = `height ${duration}s ease-out`;
        content.style.height = `${height}px`;
        setTimeout(() => {
          content.style.transition = "none";
          content.style.height = "auto";
        }, duration * 1000);
      }, 0);
    },

    openItem() {
      if (this.parent) {
        if (this.parentAccordeon) {
          this.parent.openItems = [this.id];
        } else {
          const cleared = this.parent.openItems.filter((i) => i !== this.id);
          cleared.push(this.id);
          this.parent.openItems = [...cleared];
        }
      } else {
        this.active = true;
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.nv-expansion-panel {
  @apply bg-white cursor-default flex flex-col relative;
  transition: 0.2s;

  &.disabled .nv-expansion-panel__title {
    @apply bg-gray-100 opacity-60;
  }

  &.dark {
    @apply bg-black text-white;
    &.disabled .nv-expansion-panel__title {
      @apply bg-black;
    }
  }

  &.opened:not(:first-child) {
    @apply mt-4;
  }
  &.opened + .nv-expansion-panel {
    @apply mt-4;
  }
}

.nv-expansion-panel__title {
  @apply flex items-center min-h-[44px] px-5 py-2 hover:bg-gray-100;
}

.dark.nv-expansion-panel > .nv-expansion-panel__title {
  @apply hover:bg-[#3c3c3c];
}

.opened > .nv-expansion-panel__title {
  @apply bg-primary text-white hover:bg-primary-darken;
}

.dark.opened > .nv-expansion-panel__title {
  @apply bg-[#3c3c3c];
}

.nv-expansion-panel__title-content {
  @apply flex items-center grow;
}

.nv-expansion-panel__title-text {
  @apply grow;
}

.nv-expansion-panel__title-arrow {
  @apply ml-4;
  transition: transform 0.2s;
}

.opened .nv-expansion-panel__title-arrow {
  @apply rotate-90;
}

.nv-expansion-panel__content {
  @apply overflow-hidden;
  transition: height 0.2s ease-out;
}
</style>
