<script lang="ts" setup>
import type { TabDefinition } from '@easyflow-core/typings';

import type { TabConfig, TabsProps } from '../../types';

import { computed } from 'vue';

import { Pin, X } from '@easyflow-core/icons';
import { EasyFlowContextMenu, EasyFlowIcon } from '@easyflow-core/shadcn-ui';

interface Props extends TabsProps {}

defineOptions({
  name: 'EasyFlowTabs',

  inheritAttrs: false,
});
const props = withDefaults(defineProps<Props>(), {
  contentClass: 'easyflow-tabs-content',
  contextMenus: () => [],
  tabs: () => [],
});

const emit = defineEmits<{
  close: [string];
  unpin: [TabDefinition];
}>();
const active = defineModel<string>('active');

const typeWithClass = computed(() => {
  const typeClasses: Record<string, { content: string }> = {
    brisk: {
      content: `h-full after:content-['']  after:absolute after:bottom-0 after:left-0 after:w-full after:h-[1.5px] after:bg-primary after:scale-x-0 after:transition-[transform] after:ease-out after:duration-300 hover:after:scale-x-100 after:origin-left [&.is-active]:after:scale-x-100 [&:not(:first-child)]:border-l last:border-r last:border-r border-border`,
    },
    card: {
      content:
        'h-[calc(100%-6px)] rounded-md ml-2 border border-border  transition-all',
    },
    plain: {
      content:
        'h-[calc(100%-8px)] rounded-2xl border border-transparent bg-transparent transition-all duration-150 [&.is-active]:bg-[hsl(var(--glass-tint))/0.72] [&.is-active]:shadow-[0_16px_28px_-24px_hsl(var(--foreground)/0.34)] [&:not(.is-active)]:hover:bg-[hsl(var(--nav-item-hover))/0.9]',
    },
  };

  return typeClasses[props.styleType || 'plain'] || { content: '' };
});

const tabsView = computed(() => {
  return props.tabs.map((tab) => {
    const { fullPath, meta, name, path, key } = tab || {};
    const { affixTab, icon, newTabTitle, tabClosable, title } = meta || {};
    return {
      affixTab: !!affixTab,
      closable: Reflect.has(meta, 'tabClosable') ? !!tabClosable : true,
      fullPath,
      icon: icon as string,
      key,
      meta,
      name,
      path,
      title: (newTabTitle || title || name) as string,
    } as TabConfig;
  });
});

function onMouseDown(e: MouseEvent, tab: TabConfig) {
  if (
    e.button === 1 &&
    tab.closable &&
    !tab.affixTab &&
    tabsView.value.length > 1 &&
    props.middleClickToClose
  ) {
    e.preventDefault();
    e.stopPropagation();
    emit('close', tab.key);
  }
}
</script>

<template>
  <div
    :class="contentClass"
    class="relative !flex h-full w-max items-center gap-1 overflow-hidden pr-3"
  >
    <TransitionGroup name="slide-left">
      <div
        v-for="(tab, i) in tabsView"
        :key="tab.key"
        :class="[
          {
            'is-active': tab.key === active,
            draggable: !tab.affixTab,
            'affix-tab': tab.affixTab,
          },
          typeWithClass.content,
        ]"
        :data-index="i"
        class="tab-item translate-all group relative flex min-w-0 cursor-pointer select-none"
        data-tab-item="true"
        @click="active = tab.key"
        @mousedown="onMouseDown($event, tab)"
      >
        <EasyFlowContextMenu
          :handler-data="tab"
          :menus="contextMenus"
          :modal="false"
          item-class="pr-6"
        >
          <div class="relative flex size-full items-center">
            <!-- extra -->
            <div
              class="absolute right-1.5 top-1/2 z-[3] translate-y-[-50%] overflow-hidden"
            >
              <!-- close-icon -->
              <X
                v-show="!tab.affixTab && tabsView.length > 1 && tab.closable"
                class="size-3 cursor-pointer rounded-full stroke-[hsl(var(--nav-item-muted-foreground))] transition-all hover:bg-[hsl(var(--surface-contrast-soft))/0.92] hover:stroke-[hsl(var(--foreground))] group-[.is-active]:stroke-[hsl(var(--nav-item-active-foreground))]"
                @click.stop="() => emit('close', tab.key)"
              />
              <Pin
                v-show="tab.affixTab && tabsView.length > 1 && tab.closable"
                class="mt-[1px] size-3.5 cursor-pointer rounded-full stroke-[hsl(var(--nav-item-muted-foreground))] transition-all hover:bg-[hsl(var(--surface-contrast-soft))/0.92] hover:stroke-[hsl(var(--foreground))] group-[.is-active]:stroke-[hsl(var(--nav-item-active-foreground))]"
                @click.stop="() => emit('unpin', tab)"
              />
            </div>

            <!-- tab-item-main -->
            <div
              class="mx-3 mr-4 flex h-full items-center overflow-hidden pr-3 text-[hsl(var(--nav-item-muted-foreground))] transition-all duration-150 group-[.is-active]:font-medium group-[.is-active]:text-[hsl(var(--nav-item-active-foreground))]"
            >
              <EasyFlowIcon
                v-if="showIcon"
                :icon="tab.icon"
                class="mr-2 flex size-[15px] items-center overflow-hidden"
                fallback
              />

              <span
                class="flex-1 overflow-hidden whitespace-nowrap text-[13px]"
              >
                {{ tab.title }}
              </span>
            </div>
          </div>
        </EasyFlowContextMenu>
      </div>
    </TransitionGroup>
  </div>
</template>
