<script setup>
import { onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData';

const { t } = useI18n();

const props = defineProps({
    dataKey: {
        type: String,
        required: true,
    },
    autoLoad: {
        type: Boolean,
        default: false,
    },
    data: {
        type: Array,
        default: null,
    },
    url: {
        type: String,
        default: '',
    },
    filter: {
        type: Object,
        default: null,
    },
    where: {
        type: Object,
        default: null,
    },
    order: {
        type: [String, Array],
        default: '',
    },
    limit: {
        type: Number,
        default: 10,
    },
    userParams: {
        type: Object,
        default: null,
    },
    offset: {
        type: Number,
        default: 0,
    },
    skeleton: {
        type: Boolean,
        default: true,
    },
    exprBuilder: {
        type: Function,
        default: null,
    },
    disableInfiniteScroll: {
        type: Boolean,
        default: false,
    },
});

const emit = defineEmits(['onFetch', 'onPaginate']);
defineExpose({ fetch });
const isLoading = ref(false);
const pagination = ref({
    sortBy: props.order,
    rowsPerPage: props.limit,
    page: 1,
});

const arrayData = useArrayData(props.dataKey, {
    url: props.url,
    filter: props.filter,
    where: props.where,
    limit: props.limit,
    order: props.order,
    userParams: props.userParams,
    exprBuilder: props.exprBuilder,
});
const store = arrayData.store;

onMounted(() => {
    if (props.autoLoad) fetch();
});

watch(
    () => props.data,
    () => {
        store.data = props.data;
    }
);

async function fetch() {
    await arrayData.fetch({ append: false });
    if (!arrayData.hasMoreData.value) {
        isLoading.value = false;
    }
    emit('onFetch', store.data);
}

async function paginate() {
    const { page, rowsPerPage, sortBy, descending } = pagination.value;

    if (!props.url) return;

    isLoading.value = true;
    await arrayData.loadMore();

    if (!arrayData.hasMoreData.value) {
        if (store.userParamsChanged) arrayData.hasMoreData.value = true;
        store.userParamsChanged = false;
        isLoading.value = false;
        return;
    }

    pagination.value.rowsNumber = store.data.length;
    pagination.value.page = page;
    pagination.value.rowsPerPage = rowsPerPage;
    pagination.value.sortBy = sortBy;
    pagination.value.descending = descending;

    isLoading.value = false;

    emit('onFetch', store.data);
    emit('onPaginate');
}

async function onLoad(index, done) {
    if (!store.data) {
        return done();
    }

    if (store.data.length === 0 || !props.url) return done(false);

    pagination.value.page = pagination.value.page + 1;

    await paginate();
    let isDone = false;
    if (store.userParamsChanged) isDone = !arrayData.hasMoreData.value;
    done(isDone);
}
</script>

<template>
    <div class="full-width">
        <div
            v-if="!props.autoLoad && !store.data && !isLoading"
            class="info-row q-pa-md text-center"
        >
            <h5>
                {{ t('No data to display') }}
            </h5>
        </div>
        <div
            v-if="props.skeleton && props.autoLoad && !store.data"
            class="card-list q-gutter-y-md"
        >
            <QCard class="card" v-for="$index in props.limit" :key="$index">
                <QItem v-ripple class="q-pa-none items-start cursor-pointer q-hoverable">
                    <QItemSection class="q-pa-md">
                        <QSkeleton type="rect" class="q-mb-md" square />
                        <QSkeleton type="text" square />
                        <QSkeleton type="text" class="q-mb-md" square />
                        <QSkeleton type="text" square />
                        <QSkeleton type="text" square />
                    </QItemSection>
                    <QSeparator vertical />
                    <QCardActions vertical class="justify-between">
                        <QSkeleton type="circle" class="q-mb-md" size="40px" />
                        <QSkeleton type="circle" class="q-mb-md" size="40px" />
                        <QSkeleton type="circle" class="q-mb-md" size="40px" />
                    </QCardActions>
                </QItem>
            </QCard>
        </div>
    </div>
    <QInfiniteScroll
        v-if="store.data"
        @load="onLoad"
        :offset="offset"
        :disable="disableInfiniteScroll || !arrayData.hasMoreData.value"
        class="full-width"
        v-bind="$attrs"
    >
        <slot name="body" :rows="store.data"></slot>
        <div v-if="isLoading" class="info-row q-pa-md text-center">
            <QSpinner color="orange" size="md" />
        </div>
    </QInfiniteScroll>
</template>

<style lang="scss" scoped>
.info-row {
    width: 100%;

    h5 {
        margin: 0;
    }
}
</style>

<i18n>
es:
    No data to display: Sin datos que mostrar
    No results found: No se han encontrado resultados
</i18n>
