package fr.iutfbleau.sae.mhuffman;

/**
 * 
 * Représente un nœud de l'arbre de Huffman.
 *
 * Un nœud peut être :
 * - une feuille : il contient une valeur (symbole de 0 à 255) et sa fréquence
 * - un nœud interne : il n'a pas de valeur mais possède deux enfants et une fréquence
 *   correspondant à la somme des fréquences de ces enfants
 *
 * Cette classe sert uniquement de structure pour construire l'arbre de Huffman,
 * utilisé ensuite pour générer les codes dans la compression.
 */
public class HuffmanNode {

    /** Valeur du symbole pour une feuille. Vaut -1 pour un nœud interne. */
    private int value;

    /** Fréquence associée au symbole ou somme des fréquences pour les nœuds internes. */
    private int frequence;

    /** Fils gauche du nœud. Null si le nœud est une feuille. */
    private HuffmanNode left;

    /** Fils droit du nœud. Null si le nœud est une feuille. */
    private HuffmanNode right;

    /**
     * Constructeur d'un nœud feuille.
     *
     * @param value symbole représenté (entre 0 et 255)
     * @param frequence fréquence d'apparition du symbole
     */
    public HuffmanNode(int value, int frequence) {
        if (value < 0 || value > 255) {
            throw new IllegalArgumentException("Le symbole doit être entre 0 et 255.");
        }
        if (frequence < 0) {
            throw new IllegalArgumentException("La fréquence ne peut pas être négative.");
        }
        this.value = value;
        this.frequence = frequence;
        this.left = null;
        this.right = null;
    }

    /**
     * Constructeur d'un nœud interne (créé lors de la fusion de deux sous-arbres).
     *
     * @param left fils gauche
     * @param right fils droit
     */
    public HuffmanNode(HuffmanNode left, HuffmanNode right) {
        if (left == null || right == null) {
            throw new IllegalArgumentException("Les deux enfants doivent être non nuls.");
        }
        this.value = -1; // Valeur spéciale indiquant que c'est un nœud interne
        this.left = left;
        this.right = right;
        this.frequence = left.frequence + right.frequence;
    }

    /**
     * Indique si le nœud est une feuille.
     *
     * @return true si le nœud est une feuille, false sinon
     */
    public boolean isLeaf() {
        return this.left == null && this.right == null;
    }

    /**
     * Renvoie la fréquence associée à ce nœud.
     *
     * @return fréquence du symbole ou somme des fréquences
     */
    public int getFrequence() {
        return this.frequence;
    }

    /**
     * Renvoie le fils gauche.
     *
     * @return fils gauche ou null si feuille
     */
    public HuffmanNode getLeft() {
        return this.left;
    }

    /**
     * Renvoie le fils droit.
     *
     * @return fils droit ou null si feuille
     */
    public HuffmanNode getRight() {
        return this.right;
    }

    /**
     * Renvoie la valeur du symbole représenté.
     *
     * @return valeur du symbole (0 à 255)
     * @throws IllegalStateException si le nœud n'est pas une feuille
     */
    public int getValue() {
        if (!this.isLeaf()) {
            throw new IllegalStateException("Seules les feuilles ont une valeur de symbole.");
        }
        return this.value;
    }

    /**
     * Représentation textuelle du nœud. Utile en phase de débogage.
     */
    @Override
    public String toString() {
        if (this.isLeaf()) {
            return "Feuille(valeur=" + this.value + ", freq=" + this.frequence + ")";
        }
        return "Noeud(freq=" + this.frequence + ")";
    }
}
