package adecWatt.view;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import misc.DimensionDouble;
import misc.Log;

import adecWatt.model.Comp;
import adecWatt.model.Item;
import adecWatt.model.Segm;

@SuppressWarnings ("serial") abstract public class JItem extends JLabel {

    // ========================================
    protected ItemMouseAdapter itemMouseAdapter = new ItemMouseAdapter ();
    protected JWorkspaceView<?> jWorkspaceView;
    protected double currentThetaDegree;
    protected Point2D.Double currentPos;
    protected DimensionDouble currentSize; 
    protected double [] currentBounds = null;

    abstract public Item	getItem ();
    abstract public void	setItem (Item item);

    public JWorkspaceView<?>	getJWorkspaceView ()		{ return jWorkspaceView; }
    public Point2D.Double	getCurrentPos ()		{ return currentPos; }
    public DimensionDouble	getCurrentSize ()		{ return currentSize; }
    public double		getCurrentThetaDegree ()	{ return currentThetaDegree; }
    public double []		getCurrentBounds ()		{ return currentBounds; }

    // ========================================
    static public JItem getNewJItem (JWorkspaceView<?> jWorkspaceView, Item item) {
	if (item instanceof Comp)
	    return new JComp (jWorkspaceView, (Comp) item);
	if (item instanceof Segm)
	    return new JSegm (jWorkspaceView, (Segm) item);
	throw new IllegalArgumentException ("Bad item type ("+item+")!");
    }

    public JItem (JWorkspaceView<?> jWorkspaceView, Item item) {
	try {
	    this.jWorkspaceView = jWorkspaceView;
	    setItem (item);
	    setCurrentSize ();
	    updateIcon ();
	    addMouseListener (itemMouseAdapter);
	    addMouseMotionListener (itemMouseAdapter);
	} catch (Exception e) {
	    Log.keepLastException ("JItem ("+getItem ()+") :", e);
	}
    }

    // ========================================
    public class ItemMouseAdapter extends MouseAdapter {
	public void mouseClicked (MouseEvent e) {
	    jWorkspaceView.mouseClicked (SwingUtilities.convertMouseEvent (JItem.this, e, jWorkspaceView));
	}
	public void mousePressed (MouseEvent e) {
	    MouseEvent ec = SwingUtilities.convertMouseEvent (JItem.this, e, jWorkspaceView);
	    jWorkspaceView.mousePressed (ec);
	}
	public void mouseReleased (MouseEvent e) {
	    jWorkspaceView.mouseReleased (SwingUtilities.convertMouseEvent (JItem.this, e, jWorkspaceView));
	}
	public void mouseDragged (MouseEvent e) {
	    jWorkspaceView.mouseDragged (SwingUtilities.convertMouseEvent (JItem.this, e, jWorkspaceView));
	}
    };

    // ========================================
    public void setCurrentPos (Point2D.Double currentPos) {
	this.currentPos = currentPos;
	updateBounds ();
	updateLocation ();
    }
    public void setCurrentSize (DimensionDouble size) {
	currentSize = size;
	updateBounds ();
 	updateIcon ();
    }
    public void setCurrentThetaDegree (double currentThetaDegree) {
	this.currentThetaDegree = currentThetaDegree;
	updateBounds ();
	updateIcon ();
    }
    public void setCurrentSize (Point2D.Double pos, DimensionDouble size) {
	setCurrentGeo (pos, getItem ().getThetaDegree (), size);
    }
    public void setCurrentGeoDelta (Point2D.Double pos, double deltaTheta, DimensionDouble size) {
	setCurrentGeo (pos, Math.toDegrees (Math.toRadians (currentThetaDegree)+deltaTheta), size);
    }
    private void setCurrentGeo (Point2D.Double pos, double thetaDegree, DimensionDouble size) {
	currentPos = pos;
	currentSize = size;
	currentThetaDegree = thetaDegree;
	updateBounds ();
 	updateIcon ();
    }

    // ========================================
    public void setCurrentPos () {
	setCurrentPos (getItem ().getPos ());
    }
    public void setCurrentSize () {
	setCurrentSize (getItem ().getSize ());
    }
    public void setCurrentThetaDegree () {
	setCurrentThetaDegree (getItem ().getThetaDegree ());
    }
    public void setScale () {
	updateIcon ();
    }

    // ========================================
    public void updateLocation () {
	Point pos = jWorkspaceView.scaleModelToView (currentPos);
	pos.x -= getWidth ()/2;
	pos.y -= getHeight ()/2;
	setLocation (pos);
	jWorkspaceView.setLayer (this, jWorkspaceView.levelModelToView (getItem ().getLevel ()));
    }

    // ========================================
    public void cap (Point relPos) {
	Dimension size = getSize ();
	setCurrentThetaDegree (Math.toDegrees (Math.PI/2+Math.atan2 (relPos.y-size.height/2, relPos.x-size.width/2)));
    }

    public void rotation (MouseEvent e) {
	cap (e.getPoint ());
    }

    public void dragItem (DimensionDouble delta) {
	setCurrentPos (new Point2D.Double (currentPos.x+delta.width, currentPos.y+delta.height));
    }

    // ========================================
    public void updateIcon () {
	if (currentPos == null || currentSize == null)
	    return;
	double scale = jWorkspaceView.getScale ();
	Item item = getItem ();
	DimensionDouble size = Item.getRotSize (new DimensionDouble (currentSize.width*scale, currentSize.height*scale), currentThetaDegree);
	BufferedImage image = new BufferedImage (Math.max (1, (int) size.width), Math.max (1, (int) size.height), BufferedImage.TYPE_INT_ARGB);

	DimensionDouble currentRotSize = Item.getRotSize (currentSize, currentThetaDegree);
	Point2D.Double halfCurrentRotSize = new Point2D.Double (currentRotSize.width/2, currentRotSize.height/2);

	Graphics2D printGraphics = (Graphics2D) image.getGraphics ();
	printGraphics.scale (scale, scale);
	item.print (printGraphics, jWorkspaceView.getWorkspace (), halfCurrentRotSize, currentSize, currentThetaDegree);
	setIcon (new ImageIcon (image));
	setSize (getPreferredSize ());
	updateLocation ();
    }
    public void updateBounds () {
	if (currentPos == null || currentSize == null)
	    return;
	currentBounds = Item.getBounds (currentPos, currentSize, currentThetaDegree);
    }

    // ========================================
}
