package fr.iutfbleau.sae;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;

/**
 * Panneau personnalise pour afficher l'image.
 * Utilise le double buffering pour un affichage fluide.
 * Gere le deplacement de l'image avec la souris.
 */
public class ViewerImagePanel extends JPanel implements MouseListener, MouseMotionListener {

    // l'image que j'affiche dans le panneau
    private BufferedImage image;

    // je stocke le decalage horizontal de l'image pour le deplacement
    private int offsetX = 0;
    // je stocke le decalage vertical de l'image pour le deplacement
    private int offsetY = 0;

    // je garde la derniere position X de la souris pour calculer le deplacement
    private int lastX;
    // je garde la derniere position Y de la souris pour calculer le deplacement
    private int lastY;

    /**
     * Constructeur du panneau.
     * Active le double buffering et ajoute les ecouteurs de souris.
     */
    public ViewerImagePanel() {
        // j'active le double buffering pour eviter le clignotement
        this.setDoubleBuffered(true);
        // je mets un fond noir pour que ca soit plus joli
        this.setBackground(Color.BLACK);
        // j'ajoute les ecouteurs pour detecter les clics et les mouvements de souris
        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    /**
     * Definit l'image a afficher et reinitialise le decalage.
     *
     * @param img l'image a afficher
     */
    public void setImage(BufferedImage img) {
        this.image = img;
        // je reinitialise le decalage quand je charge une nouvelle image
        this.offsetX = 0;
        this.offsetY = 0;
        // je demande un reaffichage
        repaint();
    }

    /**
     * Methode de dessin du panneau.
     * Dessine l'image avec le decalage actuel ou la centre si elle est plus petite.
     *
     * @param g le contexte graphique
     */
    @Override
    protected void paintComponent(Graphics g) {
        // j'appelle le paintComponent parent pour nettoyer le panneau
        super.paintComponent(g);

        // si j'ai pas d'image je fais rien
        if (image == null) return;

        // je recupere la taille actuelle du panneau
        int panelW = getWidth();
        int panelH = getHeight();

        // je recupere la taille de l'image
        int imgW = image.getWidth();
        int imgH = image.getHeight();

        // je pars du decalage actuel pour le dessin
        int drawX = offsetX;
        int drawY = offsetY;

        // si l'image est plus petite que le panneau je la centre automatiquement
        if (imgW < panelW) drawX = (panelW - imgW) / 2;
        if (imgH < panelH) drawY = (panelH - imgH) / 2;

        // je dessine l'image a la position calculee
        g.drawImage(image, drawX, drawY, null);
    }

    /**
     * Detecte quand l'utilisateur appuie sur le bouton de la souris.
     * Je sauvegarde la position pour calculer le deplacement ensuite.
     *
     * @param e l'evenement souris
     */
    @Override
    public void mousePressed(MouseEvent e) {
        // je memorise la position de depart du clic
        lastX = e.getX();
        lastY = e.getY();
    }

    /**
     * Detecte quand l'utilisateur fait glisser la souris.
     * Je calcule le deplacement et je mets a jour l'affichage.
     *
     * @param e l'evenement souris
     */
    @Override
    public void mouseDragged(MouseEvent e) {
        // je calcule la difference entre la position actuelle et la derniere
        // et j'ajoute ca au decalage de l'image
        offsetX += e.getX() - lastX;
        offsetY += e.getY() - lastY;

        // je mets a jour la derniere position connue
        lastX = e.getX();
        lastY = e.getY();

        // je redemande un affichage pour voir le deplacement
        repaint();
    }

    // les methodes suivantes sont obligatoires mais j'en ai pas besoin
    @Override public void mouseReleased(MouseEvent e) {}
    @Override public void mouseClicked(MouseEvent e) {}
    @Override public void mouseEntered(MouseEvent e) {}
    @Override public void mouseExited(MouseEvent e) {}
    @Override public void mouseMoved(MouseEvent e) {}
}
