package SEMAbeans;

import javax.swing.JComponent;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Vector;

import sema.World;
import sema.Box;
import sema.Element;


/**
 * Bean used to display a {@link sema.World }.
 * It needs to be initialized with a World through the {@link #init(World world)} function.
 */
public class ZGCarteSEMA extends JComponent{  //composant graphique pour l'affichage du monde
    
    /**
     * Creates the bean.
     * It is created linked to an empty world, to prevent errors before the call to {@link #init(World world)}
     */
    public ZGCarteSEMA() {
	addMouseListener(new java.awt.event.MouseAdapter() {
	    public void mouseClicked(java.awt.event.MouseEvent evt) {
		requestFocusInWindow();
	    }
	});
    }
    
    
    
    //coordonnées du coin supérieur gauche de la zone d'affichage, en unités simulées
    private float cxu = 0f;
    private float cyu = 0f;
    
    private boolean highlightSelectedBox = false;
    
    /**
     * Sets whether the selected box has to be highlighted
     * @param b the value to set the highlightSelectedBox property to
     */
    public void setHighlightSelectedBox(boolean b){
	highlightSelectedBox = b;
    }
    
    /**
     * Sets the x-coordinate of the center of the view.
     * @param x x-coordinate (in simulated unit) of the center.
     */
    public void setCenterXu(float x){
	this.cxu=x;
    }
    /**
     * Returns the x-coordinate (in simulated unit) of the center of the view.
     * @return the x-coordinate (in simulated unit) of the center of the view.
     */
    public float getCenterXu(){
	return cxu;
    }
    /**
     * Sets the y-coordinate of the center of the view.
     * @param y y-coordinate (in simulated unit) of the center.
     */
    public void setCenterYu(float y){
	this.cyu=y;
    }
    /**
     *  Returns the y-coordinate (in simulated unit) of the center of the view.
     * @return the y-coordinate (in simulated unit) of the center of the view.
     */
    public float getCenterYu() {
	return cyu;
    }
    
    //données liées au monde
    private World world = new World();
    private float pixelsByBox = 10;
    private Element selectedElement;
    private Box selectedBox;
    
    /**
     * Sets the selected element.
     * @param selectedElement the selected element.
     */
    public void setSelectedElement(Element selectedElement){
	this.selectedElement = selectedElement ;
    }
    /**
     * Sets the selectedBox.
     * @param selectedBox the selectedBox.
     */
    public void setSelectedBox(Box selectedBox){
	this.selectedBox = selectedBox ;
    }
    
    /**
     * Inits the bean with a world.
     * @param world the world to display.
     */
    public void init(World world) { //initialisation des données liées au monde
	this.world = world;
	this.pixelsByBox = world.drawing.getPixelsByBox();
	this.selectedBox = null;
	this.selectedElement = null;
    }
    
    /**
     * Returns a preferred size depending on the world.
     * @see javax.swing.JComponent#getPreferredSize()
     * @return the preferred size (in pixels).
     */
    public Dimension getPreferredSize(){ // taille préférée de 10x10 cases.
	return new Dimension((int)(pixelsByBox*10),(int)(pixelsByBox*10));
    }
    
    /**
     * Returns the mminimum size depending on the world.
     * @see javax.swing.JComponent#getMinimumSize()
     * @return thre minimum size (in pixels).
     */
    public Dimension getMinimumSize(){
	return new Dimension((int)pixelsByBox,(int)pixelsByBox);
    }
    /**
     * Returns the width (in simulated unit) of the view.
     * @return the width (in simulated unit) of the view.
     */
    public float getWidthu(){
	return getWidth()/world.drawing.getPixelsByUnit();
    }
    /**
     * Returns the top left corner x-coordinate (in simulated unit).
     * @return the top left corner x-coordinate (in simulated unit).
     */
    public float getXu() {
	return cxu-getWidthu()/2;
    }
    
    /**
     * Returns the height (in simulated unit) of the view.
     * @return the height (in simulated unit) of the view.
     */
    public float getHeightu(){
	return getHeight()/world.drawing.getPixelsByUnit();
    }
    /**
     * Returns the top left corner x-coordinate (in simulated unit).
     * @return the top left corner x-coordinate (in simulated unit).
     */
    public float getYu() {
	return cyu-getHeightu()/2;
    }
    
    /**
     * Paints the map. Computes only visible boxes and their registered elements.
     * First, it erases previous graphics. Then, it correctly translate the screen
     * to synchronized the area to display and the drawing. Then, it computes the
     * boxes to draw and paints them. Finally, it paints the occupants of these boxes,
     * according to their drawin priority ({@link sema.Element#getDrawingPriority()}).
     * @param g the graphics context.
     * @see javax.swing.JComponent#paintComponent(Graphics  g)
     */
    protected void paintComponent(Graphics g){
	
	//initialisations
	float xu = getXu();
	float yu = getYu();
	float pbu = world.drawing.getPixelsByUnit();
	Graphics2D genv = (Graphics2D)g.create();
	
	//efface la zone de dessin de la carte
	genv.setColor(getBackground());
	genv.fillRect(0,0,getWidth(),getHeight());
	
	//on translate de manière appropriée la zone d'affichage
	genv.translate(-xu*pbu,-yu*pbu);
	
	if (world != null) { //si le modèle est initialisé
	    Vector boxToRefresh = world.map.getCoveringBoxes(xu, yu, getWidthu(),getHeightu()); //on détermine les cases à afficher

	    world.drawing.draw(genv, boxToRefresh);//et on les dessine!
	    world.draw();
	    //mise en évidence de la case et de l'élément sélectionnés
	    if (selectedElement!=null)
		selectedElement.highlight();
	    if(selectedBox != null && highlightSelectedBox)
		selectedBox.highlight();
	}
	
    }
    
}