<script setup lang="ts">
import type { ChartData } from 'chart.js';
import { computed, ref } from 'vue';
import { Bar } from 'vue-chartjs';
import { colors, gridColor, gridColorBold } from '@/types/graphs';
import type { Iteration } from '@/types/perceptron';
import Toggle from './ui/toggle/Toggle.vue';
import { usePage } from '@inertiajs/vue3';

const props = defineProps<{
    iterations: Iteration[];
}>();

const page = usePage();

const epochErrorOnly = ref<boolean>(false);

/**
 * Datasets of the iterations with the form { label: `Exemple ${exampleIndex}`, data: [error for iteration 1, error for iteration 2, ...] }
 */
const datasets = computed<
    ChartData<'bar', (number | [number, number] | null)[]>[]
>(() => {
    const datasets: ChartData<'bar', (number | [number, number] | null)[]>[] =
        [];
    const epochAverageError: number[] = [];

    const backgroundColors = colors;

    const exampleCountPerEpoch: Record<number, number> = {};

    props.iterations.forEach((iteration) => {
        if (!epochErrorOnly.value) {
            const exampleLabel = `Exemple ${iteration.exampleIndex}`;
            let dataset = datasets.find((d) => d.label === exampleLabel);
            if (!dataset) {
                dataset = {
                    label: exampleLabel,
                    data: [],
                    order: 1,
                    backgroundColor:
                        backgroundColors[
                            iteration.exampleIndex % backgroundColors.length
                        ],
                };
                datasets.push(dataset);
            }
            dataset.data.push(iteration.error);
        }

        exampleCountPerEpoch[iteration.epoch] = (exampleCountPerEpoch[iteration.epoch] || 0) + 1;

        // Epoch error
        epochAverageError[iteration.epoch] =
            (epochAverageError[iteration.epoch] || 0) +
            iteration.error ** 2 / 2;
    });

    // Sort dataset by label (Exemple 0, Exemple 1, ...)
    datasets.sort((a, b) => {
        const aIndex = parseInt(a.label.split(' ')[1]);
        const bIndex = parseInt(b.label.split(' ')[1]);
        return aIndex - bIndex;
    });

    // Epoch error
    const epochErrorDataset = {
        type: 'line',
        label: "Erreur quadratique moyenne de l'époque",
        data: [],
        backgroundColor: '#fff',
        borderColor: '#fff',
        order: 0,
        tension: 0.3,
    };

    epochAverageError.forEach((error, index) => {
        const exampleCount = exampleCountPerEpoch[index] || 1; // Avoid division by zero
        epochErrorDataset.data.push(error / exampleCount);
    });

    datasets.push(epochErrorDataset);

    return datasets;
});
</script>

<template>
    <Bar
        class="bg-primary dark:bg-transparent!"
        :options="{
            responsive: true,
            maintainAspectRatio: true,
            plugins: {
                title: {
                    display: true,
                    text: 'Nombre d\'erreurs par epoch',
                },
            },
            scales: {
                x: {
                    stacked: true,
                    min: 0,
                },
                y: {
                    stacked: true,
                    beginAtZero: true,
                    grid: {
                        color: function (context) {
                            if (context.tick.value == 0) {
                                return gridColorBold;
                            }

                            return gridColor;
                        },
                    },
                },
            },
        }"
        :data="{
            labels: props.iterations.reduce((labels, iteration) => {
                if (!labels.includes(`Époch ${iteration.epoch}`)) {
                    labels.push(`Époch ${iteration.epoch}`);
                }
                return labels;
            }, [] as string[]),
            datasets: datasets,
        }"
    />
    <div class="flex items-center gap-3">
        <Toggle v-model="epochErrorOnly" class="cursor-pointer" variant="outline" id="epoch-error-only"
            >Afficher uniquement l'erreur quadratique moyenne de l'époque</Toggle
        >
    </div>
</template>
