package linea;

import java.awt.Color;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class GestionnaireNiveau {

	public static final int FRAMES_PAR_NIVEAU = 25 * 10; // 10 secondes

	private final List<Niveau> niveaux = new ArrayList<>();
	private int indexNiveau = 0;
	private int framesDepuisDebut = 0;
	private int framesDansNiveau = 0;

	private static final int DUREE_FADE = 25 * 3; // 3 secondes

	private static final String URL_BDD = "jdbc:sqlite:linea_bdd.db";

	public GestionnaireNiveau() {
		try {
			Class.forName("org.sqlite.JDBC");
		} catch (ClassNotFoundException e) {
			System.err.println("[BDD] Impossible de charger le driver SQLite.");
			e.printStackTrace();
		}
		chargerNiveaux();
	}

	private void chargerNiveaux() {
		String sql = "SELECT * FROM niveaux ORDER BY numero ASC";

		try (Connection conn = DriverManager.getConnection(URL_BDD);
			 Statement stmt = conn.createStatement();
			 ResultSet rs = stmt.executeQuery(sql)) {

			while (rs.next()) {
				int numero = rs.getInt("numero");
				int r = rs.getInt("couleur_r");
				int g = rs.getInt("couleur_g");
				int b = rs.getInt("couleur_b");
				double vitesse = rs.getDouble("vitesse_scroll");
				double freq = rs.getDouble("noise_frequence");
				double rayon = rs.getDouble("rayon_cercle");
				double haut = rs.getDouble("limite_haut");
				double bas = rs.getDouble("limite_bas");

				niveaux.add(new Niveau(numero, new Color(r, g, b), vitesse, freq, rayon, haut, bas));
			}

		} catch (SQLException e) {
			System.err.println("[BDD] Erreur lors du chargement des niveaux.");
			e.printStackTrace();
		}

		if (niveaux.isEmpty()) {
			niveaux.add(new Niveau(1, new Color(112, 158, 251), 8, 1.0/80.0, 70, 100, 500));
		}
	}

	private boolean niveauVientDeChanger = false;

	public void mettreAJour() {
		framesDepuisDebut++;
		framesDansNiveau++;

		if (framesDansNiveau >= FRAMES_PAR_NIVEAU && indexNiveau < niveaux.size() - 1) {
			indexNiveau++;
			framesDansNiveau = 0;
			niveauVientDeChanger = true;
		}
	}

	public boolean aChangéDeNiveau() {
		if (niveauVientDeChanger) {
			niveauVientDeChanger = false;
			return true;
		}
		return false;
	}

	public Niveau getNiveauActuel() {
		return niveaux.get(indexNiveau);
	}

	public int getNumeroNiveau() {
		return niveaux.get(indexNiveau).numero;
	}

	public Color getCouleurFondInterpolee() {
		if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) {
			Color de = niveaux.get(indexNiveau - 1).couleurFond;
			Color vers = niveaux.get(indexNiveau).couleurFond;
			double t = (double) framesDansNiveau / DUREE_FADE;
			return interpolerCouleur(de, vers, t);
		}
		return niveaux.get(indexNiveau).couleurFond;
	}

	public double getVitesseScroll() {
		if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) {
			double de = niveaux.get(indexNiveau - 1).vitesseScroll;
			double vers = niveaux.get(indexNiveau).vitesseScroll;
			double t = (double) framesDansNiveau / DUREE_FADE;
			return de + (vers - de) * t;
		}
		return niveaux.get(indexNiveau).vitesseScroll;
	}

	public double getNoiseFrequence() {
		if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) {
			double de = niveaux.get(indexNiveau - 1).noiseFrequence;
			double vers = niveaux.get(indexNiveau).noiseFrequence;
			double t = (double) framesDansNiveau / DUREE_FADE;
			return de + (vers - de) * t;
		}
		return niveaux.get(indexNiveau).noiseFrequence;
	}

	public double getRayonCercle() {
		if (framesDansNiveau < DUREE_FADE && indexNiveau > 0) {
			double de = niveaux.get(indexNiveau - 1).rayonCercle;
			double vers = niveaux.get(indexNiveau).rayonCercle;
			double t = (double) framesDansNiveau / DUREE_FADE;
			return de + (vers - de) * t;
		}
		return niveaux.get(indexNiveau).rayonCercle;
	}

	public double getLimiteHaut() {
		return niveaux.get(indexNiveau).limiteHaut;
	}

	public double getLimiteBas() {
		return niveaux.get(indexNiveau).limiteBas;
	}

	public void reinitialiser() {
		indexNiveau = 0;
		framesDepuisDebut = 0;
		framesDansNiveau = 0;
	}

	private static Color interpolerCouleur(Color de, Color vers, double t) {
		int r = (int) (de.getRed() + (vers.getRed() - de.getRed()) * t);
		int g = (int) (de.getGreen() + (vers.getGreen() - de.getGreen()) * t);
		int b = (int) (de.getBlue() + (vers.getBlue() - de.getBlue()) * t);
		return new Color(
			Math.max(0, Math.min(255, r)),
			Math.max(0, Math.min(255, g)),
			Math.max(0, Math.min(255, b))
		);
	}
}
