/*
 * Queue - A Queueing system that can be used to handle labs in higher education
 * Copyright (C) 2016-2024  Delft University of Technology
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */
let actRequestFreqChart;
let actStatusFreqChart;
let actAssignmentFreqChart;
let actRoomFreqChart;
let actLabFreqChart;
let actLabTimeChart;

function drawRequestFreqChart(canvas) {
    return function (freqs) {
        const buckets = freqs.buckets;

        const center = (buckets[1] - buckets[0]) / 2;
        const labels = buckets.map(function (x) {
            return x + center;
        });
        labels.pop();

        if (actRequestFreqChart != null) {
            actRequestFreqChart.data.labels = labels.map(function (x) {
                return new Date(2000, 1, 1, Math.floor(x / 3600), (x % 3600) / 60, x % 60);
            });
            actRequestFreqChart.data.datasets[0].data = freqs.created;
            actRequestFreqChart.data.datasets[1].data = freqs.handled;
            actRequestFreqChart.data.datasets[2].data = freqs.open;
            actRequestFreqChart.update();
        } else {
            actRequestFreqChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: labels.map(function (x) {
                        return new Date(2000, 1, 1, Math.floor(x / 3600), (x % 3600) / 60, x % 60);
                    }),
                    datasets: [
                        {
                            label: "Requests created",
                            data: freqs.created,
                            backgroundColor: getColorForStatus("TOTAL"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                        {
                            label: "Requests handled",
                            data: freqs.handled,
                            backgroundColor: getColorForStatus("PROCESSED"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                        {
                            label: "Requests open",
                            data: freqs.open,
                            backgroundColor: getColorForStatus("PENDING"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    scales: {
                        y: {
                            ticks: {
                                beginAtZero: true,
                            },
                        },
                        x: {
                            offset: "true",
                            type: "time",
                            distribution: "timeseries",
                            ticks: {
                                source: "labels",
                                min: buckets[0],
                                max: buckets[buckets.size - 1],
                            },
                            time: {
                                unit: "minute",
                                displayFormats: {
                                    minute: "H:mm",
                                },
                            },
                        },
                    },
                },
            });
        }
    };
}

function drawStatusFreqChart(canvas) {
    return function (data) {
        if (actStatusFreqChart != null) {
            actStatusFreqChart.data.datasets[0].data = [data.pending, data.processing, data.approved, data.rejected, data.notFound, data.revoked];
            actStatusFreqChart.update();
        } else {
            actStatusFreqChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: ["Pending", "Processing", "Approved", "Rejected", "Not found", "Revoked"],
                    datasets: [
                        {
                            data: [data["pending"], data["processing"], data["approved"], data["rejected"], data["not_found"], data["revoked"]],
                            backgroundColor: [
                                getColorForStatus("PENDING"),
                                getColorForStatus("PROCESSING"),
                                getColorForStatus("APPROVED"),
                                getColorForStatus("REJECTED"),
                                getColorForStatus("NOT_FOUND"),
                                getColorForStatus("REVOKED"),
                            ],
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    plugins: {
                        legend: {
                            display: false,
                        },
                    },
                    scales: {
                        y: {
                            ticks: {
                                beginAtZero: true,
                            },
                        },
                        x: {
                            offset: "true",
                        },
                    },
                },
            });
        }
    };
}

function drawRoomFreqChart(canvas) {
    return function (freqs) {
        const keys = Object.keys(freqs);
        const values = keys.map(function (k) {
            return freqs[k];
        });

        if (actRoomFreqChart != null) {
            actRoomFreqChart.data.datasets[0].data = values;
            actRoomFreqChart.data.labels = keys;
            actRoomFreqChart.update();
        } else {
            actRoomFreqChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: keys,
                    datasets: [
                        {
                            data: values,
                            backgroundColor: Array.from({ length: keys.length }, () => getArbitraryColorForGraph()),
                            borderColor: Array(keys.length).fill(getBorderColor()),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    plugins: {
                        legend: {
                            display: false,
                        },
                    },
                    scales: {
                        x: {
                            ticks: {
                                autoSkip: false,
                            },
                        },
                        y: {
                            ticks: {
                                beginAtZero: true,
                            },
                        },
                    },
                },
            });
        }
    };
}

/**
 * Updates the assigment frequency chart with new incoming data, creates chart if it doesn't exist.
 *
 * @param canvas The canvas element to create/edit the chart on
 * @returns {(function(*))|*} A functinon that updates/creates the chart based on given data.
 */
function updateAssignmentFrequencyChart(canvas) {
    return data => {
        const assignmentNames = data.map(assignment => assignment["assignmentName"]);
        const assignmentSubmissionCounts = data.map(assignment => assignment["requestCounts"]["submissionCount"]);
        const assignmentQuestionCounts = data.map(assignment => assignment["requestCounts"]["questionCount"]);
        if (actAssignmentFreqChart) {
            actAssignmentFreqChart.data.labels = assignmentNames;
            actAssignmentFreqChart.data.datasets[0].data = assignmentSubmissionCounts;
            actAssignmentFreqChart.data.datasets[1].data = assignmentQuestionCounts;
            actAssignmentFreqChart.update();
        } else {
            actAssignmentFreqChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: assignmentNames,
                    datasets: [
                        {
                            label: "Submission",
                            backgroundColor: getColorForStatus("SUBMISSION"),
                            data: assignmentSubmissionCounts,
                            borderColor: "get",
                            borderWidth: 1,
                        },
                        {
                            label: "Question",
                            backgroundColor: getColorForStatus("QUESTION"),
                            data: assignmentQuestionCounts,
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    plugins: {
                        legend: {
                            position: "bottom",
                        },
                    },
                    scales: {
                        x: {
                            ticks: {
                                autoSkip: false,
                            },
                        },
                        y: {
                            ticks: {
                                min: 0,
                                stepSize: 1,
                                beginAtZero: true,
                            },
                        },
                    },
                    animation: {
                        duration: 0,
                    },
                },
            });
        }
    };
}

/**
 * Updates the lab frequency chart with new incoming data, creates chart if it doesn't exist.
 *
 * @param canvas The canvas element to create/edit the chart on
 * @returns {(function(*))|*} A function that updates/creates the chart based on given data.
 */
function updateLabFreqChart(canvas) {
    return data => {
        const labels = [];
        const questionCounts = [];
        const submissionCounts = [];

        Object.entries(data).forEach(([labName, requestCounts]) => {
            labels.push(labName);
            questionCounts.push(requestCounts.questionCount);
            submissionCounts.push(requestCounts.submissionCount);
        });

        if (actLabFreqChart != null) {
            actLabFreqChart.data.labels = labels;
            actLabFreqChart.data.datasets[0].data = questionCounts;
            actLabFreqChart.data.datasets[1].data = submissionCounts;
            actLabFreqChart.update();
        } else {
            actLabFreqChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: labels,
                    datasets: [
                        {
                            label: "Question",
                            data: questionCounts,
                            backgroundColor: getColorForStatus("QUESTION"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                        {
                            label: "Submission",
                            data: submissionCounts,
                            backgroundColor: getColorForStatus("SUBMISSION"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    plugins: {
                        legend: {
                            position: "bottom",
                        },
                    },
                    scales: {
                        x: {
                            ticks: {
                                autoSkip: false,
                            },
                        },
                        y: {
                            ticks: {
                                min: 0,
                                stepSize: 1,
                                beginAtZero: true,
                            },
                        },
                    },
                    animation: {
                        duration: 0,
                    },
                },
            });
        }
    };
}

function updateLabTimeChart(canvas) {
    return data => {
        const labels = [];
        const avgWaitTimes = [];
        const avgProcessingTimes = [];

        Object.entries(data).forEach(([labName, labStatusDto]) => {
            labels.push(labName);
            avgWaitTimes.push(labStatusDto.avgWaitingTime);
            avgProcessingTimes.push(labStatusDto.avgProcessingTime);
        });

        if (actLabTimeChart != null) {
            actLabTimeChart.data.labels = labels;
            actLabTimeChart.data.datasets[0].data = avgWaitTimes;
            actLabTimeChart.data.datasets[1].data = avgProcessingTimes;
            actLabTimeChart.update();
        } else {
            actLabTimeChart = new Chart(canvas, {
                type: "bar",
                data: {
                    labels: labels,
                    datasets: [
                        {
                            label: "Average Wait Time",
                            data: avgWaitTimes,
                            backgroundColor: getColorForStatus("PENDING"),
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                        {
                            label: "Average Processing Time",
                            data: avgProcessingTimes,
                            backgroundColor: getColorForStatus("TOTAL"), // consistency among other graphs even though status is different
                            borderColor: getBorderColor(),
                            borderWidth: 1,
                        },
                    ],
                },
                options: {
                    plugins: {
                        legend: {
                            position: "bottom",
                        },
                    },
                    scales: {
                        x: {
                            ticks: {
                                autoSkip: false,
                            },
                        },
                        y: {
                            title: {
                                text: "Minutes",
                                display: true,
                            },
                            ticks: {
                                min: 0,
                                stepSize: 1,
                                beginAtZero: true,
                            },
                        },
                    },
                    animation: {
                        duration: 0,
                    },
                },
            });
        }
    };
}
