<script setup lang="ts">
import type { Category } from '~/src/classes.ts';

const filter = defineModel<string>();
const filterCategory = defineModel<string>('category');

const props = defineProps<{
    categories?: Category[] | undefined;
    submitButton?: boolean;
}>();

const emit = defineEmits<{
    submitClicked: [];
}>();

const filterInput = useTemplateRef<HTMLInputElement>('filterInput');

const { $translator: translator } = useNuxtApp();
const allCategory: Category = { key: '', text: translator.translate('crud.all'), icon: 'clipboard-list' };
const categoriesWithAllCategory = computed(() => [allCategory, ...(props.categories ?? [])]);

defineExpose({
    focus: () => filterInput.value?.focus(),
});

const categoryList = useTemplateRef('categoryList');
const categoryButtonKeydown = (event: KeyboardEvent) => {
    if (filterCategory.value === undefined) {
        return;
    }
    const activeIndex = categoriesWithAllCategory.value.map((category) => category.key).indexOf(filterCategory.value);
    if (activeIndex === -1) {
        return;
    }

    if ((event.key === 'ArrowUp' || event.key === 'ArrowLeft') &&
        activeIndex > 0) {
        filterCategory.value = categoriesWithAllCategory.value[activeIndex - 1].key;
        (categoryList.value?.children[activeIndex - 1] as HTMLButtonElement | undefined)?.focus();
    } else if ((event.key === 'ArrowDown' || event.key === 'ArrowRight') &&
        activeIndex < categoriesWithAllCategory.value.length - 1) {
        filterCategory.value = categoriesWithAllCategory.value[activeIndex + 1].key;
        (categoryList.value?.children[activeIndex + 1] as HTMLButtonElement | undefined)?.focus();
    }
};
</script>

<template>
    <section class="sticky-top bg-white rounded">
        <div class="input-group">
            <span class="input-group-text">
                <Icon v="filter" />
            </span>
            <input
                ref="filterInput"
                v-model="filter"
                type="search"
                class="form-control border-primary"
                :placeholder="$t('crud.filterLong')"
            >
            <button
                v-if="filter"
                type="button"
                class="btn btn-outline-danger"
                :title="$t('crud.resetFilter')"
                @click="filter = ''; filterInput?.focus()"
            >
                <Icon v="times" />
            </button>
            <button
                v-if="submitButton"
                type="button"
                class="btn btn-success"
                @click="emit('submitClicked')"
            >
                <Icon v="plus-circle" />
                <T>nouns.submit.action</T>
            </button>
        </div>
        <div
            v-if="categories && categories.length > 0"
            ref="categoryList"
            class="d-flex flex-wrap mt-1 border border-primary rounded overflow-hidden"
        >
            <button
                v-for="category of categoriesWithAllCategory"
                :key="category.text"
                type="button"
                :class="[
                    'btn btn-sm btn-wrapped',
                    filterCategory === category.key ? 'btn-primary' : 'btn-outline-primary',
                    'flex-grow-1 d-flex justify-content-center align-items-center gap-1 rounded-0',
                ]"
                :tabindex="filterCategory === category.key ? 0 : -1"
                @click="filterCategory = category.key"
                @keydown="categoryButtonKeydown"
            >
                <Icon v-if="category.icon" :v="category.icon" />
                <Spelling :text="category.text" />
            </button>
        </div>
    </section>
</template>

<style lang="scss" scoped>
.btn-wrapped {
    margin-block-start: calc(-1 * var(--bs-btn-border-width));
    margin-inline-start: calc(-1 * var(--bs-btn-border-width));
    border-block-end: none;
    border-inline-end: none;
}
</style>
