import {scorePrint, virtualScore} from "./Tools.js";

export function scoreToString(score) {
    if (score === null || score === undefined || score.length === 0)
        return ""

    if (Array.isArray(score[0]))
        return score.map(o => scorePrint(o.at(0)) + "-" + scorePrint(o.at(1))).join("  |  ")
    else
        return score.sort((a, b) => a.n_round - b.n_round).map(o => scorePrint(o.s1) + "-" + scorePrint(o.s2)).join("  |  ")
}

export function scoreToString2(match, cards = []) {
    if (!match || match.scores === null || match.scores === undefined || match.scores.length === 0)
        return ""

    if (Array.isArray(match.scores[0]))
        return match.scores.map(o => scorePrint(o.at(0)) + "-" + scorePrint(o.at(1))).join("  |  ")
    else {
        return match.scores.sort((a, b) => a.n_round - b.n_round).map(o =>
            scorePrint(virtualScore(match.c1, o, match, cards)) + "-" + scorePrint(virtualScore(match.c2, o, match, cards))).join("  |  ")
    }
}

export function createMatch(category, matchs, groups) {
    const combs_2 = {}
    for (const group of groups) {
        if (!combs_2.hasOwnProperty(group.poule))
            combs_2[group.poule] = []
        if (!combs_2[group.poule].includes(group.id))
            combs_2[group.poule].push(group.id)
    }

    const ord = new Map()
    const newMatch = []
    const matchPouleToUpdate = new Map()

    let groupeNumber = 0
    const numberOfGroup = Object.keys(combs_2).length

    for (const [k, combs_1] of Object.entries(combs_2)) {
        let matchsList = calcPoule(combs_1.length, category.liceName.split(";").length)

        let indexMatch = 0;
        const combs = new Array(combs_1.length).fill(0);

        // Trouver le premier match valide
        while (indexMatch < matchs.length && (!combs_1.includes(matchs[indexMatch].c1) || !combs_1.includes(matchs[indexMatch].c2))) {
            indexMatch++;
        }

        // Attribution aléatoire des combattants
        for (const set of matchsList) {
            if (indexMatch < matchs.length) {
                if (!combs.includes(matchs[indexMatch].c1)) {
                    if (combs[set[0] - 1] === 0)
                        combs[set[0] - 1] = matchs[indexMatch].c1
                    else if (combs[set[1] - 1] === 0)
                        combs[set[1] - 1] = matchs[indexMatch].c1

                    if (combs.includes(matchs[indexMatch].c1)) {
                        const index = combs_1.indexOf(matchs[indexMatch].c1)
                        if (index !== -1)
                            combs_1.splice(index, 1)
                    }
                }

                if (!combs.includes(matchs[indexMatch].c2)) {
                    if (combs[set[0] - 1] === 0)
                        combs[set[0] - 1] = matchs[indexMatch].c2
                    else if (combs[set[1] - 1] === 0)
                        combs[set[1] - 1] = matchs[indexMatch].c2

                    if (combs.includes(matchs[indexMatch].c2)) {
                        const index = combs_1.indexOf(matchs[indexMatch].c2)
                        if (index !== -1)
                            combs_1.splice(index, 1)
                    }
                }
                // Passer aux matchs suivants si nécessaire
                while (indexMatch < matchs.length &&
                ((combs.includes(matchs[indexMatch].c1) && combs.includes(matchs[indexMatch].c2)) ||
                    !combs_1.includes(matchs[indexMatch].c1) || !combs_1.includes(matchs[indexMatch].c2))) {
                    indexMatch++
                }
            }

            // Remplir les places vides avec des combattants restants
            if (combs[set[0] - 1] === 0) {
                if (combs_1.length > 0) {
                    const index = Math.floor(Math.random() * combs_1.length)
                    combs[set[0] - 1] = combs_1[index]
                    combs_1.splice(index, 1)
                }
            }
            if (combs[set[1] - 1] === 0) {
                if (combs_1.length > 0) {
                    const index = Math.floor(Math.random() * combs_1.length)
                    combs[set[1] - 1] = combs_1[index]
                    combs_1.splice(index, 1)
                }
            }

            if (combs_1.length === 0)
                break
        }

        // Créer les nouveaux matchs
        for (let i = 0; i < matchsList.length; i++) {
            const set = matchsList[i]
            const matchExistant = matchs.find(
                (match) =>
                    (match.c1 === combs[set[0] - 1] && match.c2 === combs[set[1] - 1]) ||
                    (match.c1 === combs[set[1] - 1] && match.c2 === combs[set[0] - 1]))

            if (matchExistant) {
                ord.set(matchExistant.id, i * numberOfGroup + groupeNumber)
                if (matchExistant.poule !== k)
                    matchPouleToUpdate.set(matchExistant.id, k)
                matchs = matchs.filter((match) => match.id !== matchExistant.id)
                continue
            }

            newMatch.push({
                categorie: category.id,
                categorie_ord: i * numberOfGroup + groupeNumber,
                poule: k,
                c1: combs[set[0] - 1],
                c2: combs[set[1] - 1],
            })
        }
        groupeNumber++
    }

    // Mise à jour des ordres et des groupes
    const lenToAdd = matchs.length
    newMatch.forEach((match) => {
        match.categorie_ord += lenToAdd
    })

    ord.forEach((value, key) => {
        ord.set(key, value + lenToAdd)
    })

    for (let i = 0; i < matchs.length; i++) {
        ord.set(matchs[i].id, i)
        matchPouleToUpdate.set(matchs[i].id, '-')
    }

    return {newMatch, matchOrderToUpdate: ord, matchPouleToUpdate}
}

const tt_ronde_opti = new Map()
tt_ronde_opti.set(2, [[1, 2]])
tt_ronde_opti.set(3, [[2, 3], [1, 3], [1, 2]])
tt_ronde_opti.set(4, [[1, 4], [2, 3], [1, 3], [2, 4], [3, 4], [1, 2]])
tt_ronde_opti.set(5, [[1, 2], [3, 4], [5, 1], [2, 3], [5, 4], [1, 3], [2, 5], [4, 1], [3, 5], [4, 2]])
tt_ronde_opti.set(6, [[1, 2], [4, 5], [2, 3], [5, 6], [3, 1], [6, 4], [2, 5], [1, 4], [5, 3], [1, 6], [4, 2], [3, 6], [5, 1], [3, 4], [6, 2]])
tt_ronde_opti.set(7, [[1, 4], [2, 5], [3, 6], [7, 1], [5, 4], [2, 3], [6, 7], [5, 1], [4, 3], [6, 2], [5, 7], [3, 1], [4, 6], [7, 2], [3, 5], [1, 6],
    [2, 4], [7, 3], [6, 5], [1, 2], [4, 7]])
tt_ronde_opti.set(8, [[2, 3], [1, 5], [7, 4], [6, 8], [1, 2], [3, 4], [5, 6], [8, 7], [4, 1], [5, 2], [8, 3], [6, 7], [4, 2], [8, 1], [7, 5], [3, 6],
    [2, 8], [5, 4], [6, 1], [3, 7], [4, 8], [2, 6], [3, 5], [1, 7], [4, 6], [8, 5], [7, 2], [1, 3]])
tt_ronde_opti.set(9, [[1, 9], [2, 8], [3, 7], [4, 6], [1, 5], [2, 9], [8, 3], [7, 4], [6, 5], [1, 2], [9, 3], [8, 4], [7, 5], [6, 1], [3, 2], [9, 4],
    [5, 8], [7, 6], [3, 1], [2, 4], [5, 9], [8, 6], [7, 1], [4, 3], [5, 2], [6, 9], [8, 7], [4, 1], [5, 3], [6, 2], [9, 7], [1, 8], [4, 5], [3, 6],
    [5, 7], [9, 8]])
tt_ronde_opti.set(10, [[1, 4], [6, 9], [2, 5], [7, 10], [3, 1], [8, 6], [4, 5], [9, 10], [2, 3], [7, 8], [5, 1], [10, 6], [4, 2], [9, 7], [5, 3],
    [10, 8], [1, 2], [6, 7], [3, 4], [8, 9], [5, 10], [1, 6], [2, 7], [3, 8], [4, 9], [6, 5], [10, 2], [8, 1], [7, 4], [9, 3], [2, 6]
    , [5, 8], [4, 10], [1, 9], [3, 7], [8, 2], [6, 4], [9, 5], [10, 3], [7, 1], [4, 8], [2, 9], [3, 6], [5, 7], [1, 10]])
tt_ronde_opti.set(11, [[1, 2], [7, 8], [4, 5], [10, 11], [2, 3], [8, 9], [5, 6], [3, 1], [9, 7], [6, 4], [2, 5], [8, 11], [1, 4], [7, 10], [5, 3],
    [11, 9], [1, 6], [4, 2], [10, 8], [3, 6], [5, 1], [11, 7], [3, 4], [9, 10], [6, 2], [1, 7], [3, 9], [10, 4], [8, 2], [5, 11], [1, 8], [9, 2],
    [3, 10], [4, 11], [6, 7], [9, 1], [2, 10], [11, 3], [7, 5], [6, 8], [10, 1], [11, 2], [4, 7], [8, 5], [6, 9], [11, 1], [7, 3], [4, 8], [9, 5],
    [6, 10], [2, 7], [8, 3], [4, 9], [10, 5], [6, 11]])

function calcPoule(n_comb, n_lice) {
    if (n_comb === 1)
        throw new Error("Le nombre de combattants doit être supérieur à 1.")
    if (n_comb / 2 < n_lice)
        n_lice = Math.floor(n_comb / 2)

    if (n_lice === 1 && n_comb <= 11) {
        return [...tt_ronde_opti.get(n_comb)]
    } else {
        return rutsch(n_comb)
    }
}

function rutsch(n_comb) {
    const out = []
    let virt_n_comb = n_comb
    if (n_comb % 2 === 1) virt_n_comb++

    // Initialisation du tableau temporaire
    const tmp = Array.from({length: virt_n_comb / 2}, () => [0, 0])
    for (let i = 0; i < virt_n_comb / 2; i++) {
        tmp[i][0] = i + 1
        tmp[i][1] = virt_n_comb - i
        out.push([...tmp[i]])
    }

    // Boucle pour les rondes
    for (let ronde = 1; ronde < virt_n_comb - 1; ronde++) {
        // Déplacement des éléments
        const old_val = tmp[virt_n_comb / 2 - 1][0]
        for (let i = virt_n_comb / 2 - 1; i > 0; i--) {
            tmp[i][0] = tmp[i - 1][0]
        }
        tmp[0][0] = tmp[0][1]
        for (let i = 0; i < virt_n_comb / 2 - 1; i++) {
            tmp[i][1] = tmp[i + 1][1]
        }
        tmp[virt_n_comb / 2 - 1][1] = old_val

        // Échange des clés si nécessaire
        if (tmp[1][0] === virt_n_comb) {
            tmp[1][0] = tmp[0][0]
            tmp[0][0] = tmp[0][1]
            tmp[0][1] = virt_n_comb
        }

        // Ajout des paires à la sortie
        for (let i = 0; i < virt_n_comb / 2; i++) {
            out.push([...tmp[i]])
        }
    }

    // Filtrer les paires dont les valeurs dépassent n_comb
    return out.filter(pair => pair[0] <= n_comb && pair[1] <= n_comb)
}
