package sudoku;

import java.util.ArrayList;
import java.util.List;

public class Multidoku {
    private List<Sudoku> sudokus;
    private List<SudokuPlacement> placements = new ArrayList<>();
    private List<List<Case>> casesPartagees;
    private List<Contrainte> contraintesPartagees;

    // Pour cet exemple, nous allons associer à chaque sudoku un offset [offsetY,
    // offsetX].
    // Par exemple, le premier sudoku est affiché à (0,0) et le second à (ligne,
    // colonne) donnée.

    public Multidoku() {
        this.sudokus = new ArrayList<>();
        this.casesPartagees = new ArrayList<>();
        this.contraintesPartagees = new ArrayList<>();
    }

    public void ajouterSudoku(Sudoku sudoku, int offsetLigne, int offsetColonne) {
        placements.add(new SudokuPlacement(sudoku, offsetLigne, offsetColonne));
    }

    // Méthode d’affichage combiné
    public String toStringCombined() {
        // 1. Déterminer la taille globale de l’affichage
        int maxLigne = 0, maxColonne = 0;
        for (SudokuPlacement sp : placements) {
            int taille = sp.getSudoku().getGrille().getTaille();
            maxLigne = Math.max(maxLigne, sp.getOffsetLigne() + taille);
            maxColonne = Math.max(maxColonne, sp.getOffsetColonne() + taille);
        }

        // 2. Créer une matrice globale et l'initialiser (ici avec "-" pour une case
        // vide)
        String[][] global = new String[maxLigne][maxColonne];
        for (int i = 0; i < maxLigne; i++) {
            for (int j = 0; j < maxColonne; j++) {
                global[i][j] = " "; // ou " " selon votre choix
            }
        }

        // 3. Pour chaque sudoku, placer l’affichage de ses cases dans la grille globale
        for (SudokuPlacement sp : placements) {
            Grille grille = sp.getSudoku().getGrille();
            int taille = grille.getTaille();
            for (int i = 0; i < taille; i++) {
                for (int j = 0; j < taille; j++) {
                    // Calcul des coordonnées globales
                    int globalLigne = sp.getOffsetLigne() + i;
                    int globalColonne = sp.getOffsetColonne() + j;
                    // Ici, on récupère la représentation de la case via toString (possiblement avec
                    // la couleur)
                    global[globalLigne][globalColonne] = grille.getCase(i, j).toString();
                }
            }
        }

        // 4. Construire la chaîne finale d’affichage ligne par ligne
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < maxLigne; i++) {
            for (int j = 0; j < maxColonne; j++) {
                sb.append(global[i][j]).append(" ");
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    public void ajouterCasesPartagees(List<Case> cases) {
        casesPartagees.add(new ArrayList<>(cases));
        ajouterContraintePartagee(new ContrainteCasePartagee(cases));
    }

    public void ajouterContraintePartagee(Contrainte contrainte) {
        contraintesPartagees.add(contrainte);
    }

    public boolean verifierContraintesPartagees() {
        return contraintesPartagees.stream()
                .allMatch(c -> c.estRespectee(null, null)); // Adaptation nécessaire selon votre logique
    }

    // Classe interne pour la contrainte de cases partagées
    public static class ContrainteCasePartagee implements Contrainte {
        private List<Case> casesLiees;

        public ContrainteCasePartagee(List<Case> cases) {
            this.casesLiees = new ArrayList<>(cases);
        }

        @Override
        public boolean estRespectee(Grille grille, Case caseActuelle) {
            Symbole reference = null;
            for (Case c : casesLiees) {
                if (c.getSymbole() != null) {
                    if (reference == null) {
                        reference = c.getSymbole();
                    } else if (!c.getSymbole().equals(reference)) {
                        return false;
                    }
                }
            }
            return true;
        }
    }

    public List<Sudoku> getSudokus() {
        return sudokus;
    }

    public List<List<Case>> getCasesPartagees() {
        return casesPartagees;
    }
}
