package org.Models;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;

@SuppressWarnings("deprecation")
public class Grille extends Observable { // TODO: ?? implements Runnable {
    private boolean[][] grille;
    public int nbLignes;
    public int nbColonnes;

    private PieceCourante pieceCourante;
    private int pieceCouranteX;
    private int pieceCouranteY;
    private boolean enPause = false;

    public Grille(int nbLignes, int nbColonnes) {
        this.nbLignes = nbLignes;
        this.nbColonnes = nbColonnes;
        this.grille = new boolean[nbLignes][nbColonnes];
        initGrille();
    }

    public void initGrille() {
        for (int i = 0; i < nbLignes; i++) {
            for (int j = 0; j < nbColonnes; j++) {
                this.grille[i][j] = false;
            }
        }
    }

    public void setCase(int i, int j, boolean value) {
        if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
            this.grille[i][j] = value;
            setChanged();
            notifyObservers();
        }
    }

    public boolean getCase(int i, int j) {
        if (i >= 0 && i < nbLignes && j >= 0 && j < nbColonnes) {
            return this.grille[i][j];
        }
        return false;
    }

    public PieceCourante getPieceCourante() {
        return pieceCourante;
    }

    public void setPieceCourante(PieceCourante pieceCourante) {
        this.pieceCourante = pieceCourante;
        this.pieceCouranteX = 3;
        this.pieceCouranteY = 0;
        setChanged();
        notifyObservers();
    }

    public int getPieceCouranteX() {
        return pieceCouranteX;
    }

    public int getPieceCouranteY() {
        return pieceCouranteY;
    }

    public void deplacerPiece(Direction direction) {

        switch (direction) {
            case BAS:
                if (peuxBouger(direction)) {
                    deplacerPieceBas();
                }
                break;
            case GAUCHE:
                if (peuxBouger(direction)) {
                    deplacerPieceGauche();
                }
                break;
            case DROITE:
                if (peuxBouger(direction)) {
                    deplacerPieceDroite();
                }
                break;
            case TOUTENBAS:
                if (peuxBouger(direction)) {
                    deplacerPieceToutEnBas();
                }
            default:
                break;
        }
    }

    private void deplacerPieceBas() {
        pieceCouranteY++;

        setChanged();
        notifyObservers();
    }

    private void deplacerPieceGauche() {
        pieceCouranteX--;

        setChanged();
        notifyObservers();
    }

    private void deplacerPieceDroite() {
        pieceCouranteX++;

        setChanged();
        notifyObservers();
    }

    private void deplacerPieceToutEnBas() {
        while (peuxBouger(Direction.BAS)) {
            deplacerPieceBas();
        }
    }

    // TODO : ENLEVER ?
    // public int getMaxYPieceCouranteColoree(List<Point> motifPieceColoree) {
    // int maxY = 0;
    // for (Point caseColoree : motifPieceColoree) {
    // if (caseColoree.y > maxY) {
    // maxY = caseColoree.y;
    // }
    // }

    // return maxY;
    // }

    // public int getMaxXPieceCouranteColoree(List<Point> motifPieceColoree) {
    // int maxX = 0;
    // for (Point caseColoree : motifPieceColoree) {
    // if (caseColoree.x > maxX) {
    // maxX = caseColoree.x;
    // }
    // }

    // return maxX;
    // }

    public int getNbLignes() {
        return nbLignes;
    }

    public int getNbColonnes() {
        return nbColonnes;
    }

    public List<Point> motifPieceCouranteColoriee() {
        List<Point> casesColores = new ArrayList<>();

        boolean[][] motif = pieceCourante.getMotif();
        for (int i = 0; i < motif.length; i++) {
            for (int j = 0; j < motif[i].length; j++) {
                if (motif[i][j]) {
                    casesColores.add(new Point(pieceCouranteX + j, pieceCouranteY + i));
                }
            }
        }

        return casesColores;
    }

    public boolean peuxBouger(Direction direction) {
        int deltaX = 0;
        int deltaY = 0;

        switch (direction) {
            case GAUCHE:
                deltaX = -1;
                break;
            case DROITE:
                deltaX = 1;
                break;
            case BAS:
                deltaY = 1;
                break;
            case TOUTENBAS:
                break;
            default:
                break;
        }

        List<Point> motifPieceColoree = motifPieceCouranteColoriee();
        for (Point caseColoree : motifPieceColoree) {
            int newX = caseColoree.x + deltaX;
            int newY = caseColoree.y + deltaY;

            if (newX < 0 || newX >= nbColonnes || newY < 0 || newY >= nbLignes) {
                return false;
            }

            if (grille[newY][newX]) {
                return false;
            }
        }

        return true;
    }

    public boolean[][] getGrille() {
        return grille;
    }

    public void fixerPiece() {
        for (Point caseColoree : motifPieceCouranteColoriee()) {
            setCase(caseColoree.y, caseColoree.x, true);
        }
    }

    public boolean doitFixerPiece() {
        if (!peuxBouger(Direction.BAS)) {
            return true;
        }

        return false;
    }

    public void setEnPause(boolean enPause) {
        this.enPause = enPause;
    }

    public boolean estEnPause() {
        return enPause;
    }


}