<template>
  <div class="tabs d-flex flex-column">
    <ul class="nav nav-tabs">
      <li class="nav-item" v-for="tab in tabs" :key="tab.id">
        <button @click="activeTab = tab" class="nav-link" :class="{ active: tab.active }">
          {{ tab.title }}
          <span v-if="invalidTabs.includes(tab)" class="badge badge-pill badge-danger">!</span>
        </button>
      </li>
    </ul>

    <div class="card tabs-content">
      <slot></slot>
    </div>
  </div>
</template>

<script lang="ts">
import { Vue, Component, Watch } from 'vue-property-decorator';

import Tab from './tab.vue';

@Component
export default class Tabs extends Vue {
  activeTab: Tab | null = null;
  tabs: Tab[] = [];
  invalidTabs: Tab[] = [];

  mounted() {
    this.tabs = this.$slots?.default?.filter(slot => slot.componentInstance instanceof Tab).map(slot => slot.componentInstance as Tab) || [];
    this.$on('validate', this.onTabValidate);

    if (this.tabs.length > 0) {
      this.activeTab = this.tabs[0];
    }
  }

  beforeDestroy() {
    this.$off('validate', this.onTabValidate);
  }

  selectTabByTitle(title: string) {
    const requestedTab = this.tabs.find(tab => tab.title.toLowerCase() === title.toLowerCase());
    if (requestedTab) {
      this.activeTab = requestedTab;
    }
  }

  onTabValidate(tab: Tab, isValid: boolean) {
    isValid ? this.invalidTabs.splice(this.invalidTabs.findIndex(t => t === tab), 1) : this.invalidTabs.push(tab);
  }

  @Watch('activeTab', { immediate: true })
  onActiveTabChange(tab: Tab, prevTab: Tab) {
    if (prevTab) {
      prevTab.active = false;
    }

    if (tab && this.activeTab) {
      this.activeTab.active = true;
    }
  }
}
</script>

<style lang="scss" scoped>
@import '../variables';

.tabs {
  min-width: 0;

  .nav-tabs {
    height: $tabs-nav-height;
    background-color: #F8F9FA;

    .nav-link {
      color: #212529;
      background: transparent;
      position: relative;

      &.active {
        background: #FFFFFF;
      }

      .badge {
        position: absolute;
        top: 1px;
        right: 1px;
      }
    }
  }
}
</style>
