package adecWatt.view;

import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import misc.Util;
import misc.DimensionDouble;

public class JItemHandler {

    // ========================================
    static public final ImageIcon handlerImage = Util.loadActionIcon ("handler");

    // ========================================
    public JWorkspaceView<?> jWorkspaceView;
    public JLabel jSelectionPane;
    public JItem jItem;
    public HandlerSet corners, sides;
    public boolean lineSelection;

    // ========================================
    public JItemHandler (JWorkspaceView<?> jWorkspaceView, JLabel jSelectionPane, JItem jItem, boolean lineSelection) {
	this.jWorkspaceView = jWorkspaceView;
	this.jSelectionPane = jSelectionPane;
	this.jItem = jItem;
	this.lineSelection = lineSelection;
	if (!lineSelection)
	    corners = new HandlerSet (true);
	sides = new HandlerSet (false);
    }
    public void setCurrentBounds (double[] bounds) {
	if (corners != null)
	    corners.setCurrentBounds (bounds);
	sides.setCurrentBounds (bounds);
    }

    Point mousePosOnItem;
    int selectedIndex;
    double oposedX, oposedY;
    DimensionDouble currentSize;
    double currentDiagonalLength;

    // ========================================
    class HandlerSet {
	public boolean cornerSelection;
	public double[] x = new double [4], y = new double [4];
	public JLabel[] handlers = new JLabel [4];

	public HandlerSet (boolean cornerSelection) {
	    this.cornerSelection = cornerSelection;
	    for (int i = 0; i < 4; i++) {
		if (i%2 != 0 && lineSelection)
		    continue;
		final JLabel handler = new JLabel (handlerImage);
		final int index = i;
		handlers [i] = handler;
		handler.setSize (8, 8);
		MouseAdapter mouseAdapter = new MouseAdapter () {
			// identique à JItem
			public void mousePressed (MouseEvent e) {
			    if (SwingUtilities.isRightMouseButton (e)) {
				// XXX ??? collectif ?
				new JItemPopup (jWorkspaceView, jItem.getItem (), SwingUtilities.convertPoint (handler, e.getPoint (), jWorkspaceView));
				return;
			    }
			    selectedIndex = index;
			    oposedX = x[(index+2)%4];
			    oposedY = y[(index+2)%4];
			    currentSize = jItem.getCurrentSize ();
			    currentDiagonalLength = Math.sqrt (currentSize.width*currentSize.width + currentSize.height*currentSize.height);
			    mousePosOnItem = e.getPoint ();
			}
			public void mouseDragged (MouseEvent e) {
			    if (jWorkspaceView.notEditable ())
				return;
			    dragHandler (e);
			    jWorkspaceView.updateSelectionLayer ();
			}
			public void mouseReleased (MouseEvent e) {
			    if (jWorkspaceView.notEditable ())
				return;
			    jWorkspaceView.storyRotResizeItem (jItem);
			}
		    };
		handler.addMouseListener (mouseAdapter);
		handler.addMouseMotionListener (mouseAdapter);
	    }
	}

	// ========================================
	public void setCurrentBounds (double[] bounds) {
	    if (cornerSelection)
		for (int i = 0, j = 1, k = 0; k < 4; i += 2, j += 2, k++) {
		    x[k] = bounds[i];
		    y[k] = bounds[j];
		}
	    else
		for (int i = 8, j = 9, k = 0; k < 4; i += 2, j += 2, k++) {
		    x[k] = bounds[i];
		    y[k] = bounds[j];
		}
	    double scale = jWorkspaceView.getScale ();
	    for (int k = 0; k < 4; k++) {
		JLabel handler = handlers [k];
		if (handler == null)
		    continue;
		handler.setLocation ((int) (x [k]*scale-4), (int) (y [k]*scale-4));
		jWorkspaceView.recordJLabel (handler);
	    }
	}

	// ========================================
	public void dragHandler (MouseEvent e) {
	    double scale = jWorkspaceView.getScale ();
	    Point newPos = e.getPoint ();
	    double newX = x[selectedIndex]+(newPos.x-mousePosOnItem.x)/scale;
	    double newY = y[selectedIndex]+(newPos.y-mousePosOnItem.y)/scale;
	    Point2D.Double closePos = new Point2D.Double (newX, newY);
	    jWorkspaceView.setSelectedBound (e.isControlDown () ? null : jWorkspaceView.getWorkspace ().getMagnetPoint (closePos, JWorkspaceView.onGrid (closePos), JWorkspaceView.closePixelsBounds/scale));
	    Point2D.Double newItemCenter = new Point2D.Double ((oposedX+closePos.x)/2, (oposedY+closePos.y)/2);

	    DimensionDouble newItemSize = null;
	    if (e.isShiftDown ()) {
		double currentTheta = Math.toRadians (jItem.getCurrentThetaDegree ());
		double[] reverse = new double [] {closePos.x-newItemCenter.x, closePos.y-newItemCenter.y};
		AffineTransform.getRotateInstance (-currentTheta).transform (reverse, 0, reverse, 0, 1);
		newItemSize = new DimensionDouble (Math.max (1/scale, Math.abs (reverse[0]*2)),
						   Math.max (1/scale, Math.abs (reverse[1]*2)));
		if (!cornerSelection) {
		    if (selectedIndex%2 == 0) {
			newItemSize.height = currentSize.height;
			reverse [1] = 0;
		    } else {
			newItemSize.width = currentSize.width;
			reverse [0] = 0;
		    }
		    AffineTransform.getRotateInstance (currentTheta).transform (reverse, 0, reverse, 0, 1);
		    newItemCenter.x = oposedX+reverse [0];
		    newItemCenter.y = oposedY+reverse [1];
		}
		jItem.setCurrentSize (newItemCenter, newItemSize);
		return;
	    }
	    if (cornerSelection) {
		double rate = Math.sqrt ((closePos.x-oposedX)*(closePos.x-oposedX) +
					 (closePos.y-oposedY)*(closePos.y-oposedY)) / currentDiagonalLength;
		newItemSize = new DimensionDouble (currentSize.width*rate, currentSize.height*rate);
	    } else {
		double length = Math.sqrt ((closePos.x-oposedX)*(closePos.x-oposedX) + (closePos.y-oposedY)*(closePos.y-oposedY));
		if (selectedIndex%2 == 0)
		    newItemSize = new DimensionDouble (length, currentSize.height);
		else
		    newItemSize = new DimensionDouble (currentSize.width, length);
	    }
	    double deltaTheta = Math.atan2 (closePos.y-oposedY, closePos.x-oposedX) -
		Math.atan2 (y[selectedIndex]-oposedY, x[selectedIndex]-oposedX);
	    jItem.setCurrentGeoDelta (newItemCenter, deltaTheta, newItemSize);
	}
    }

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