package j3deditor.bin.editor;


import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JPanel;


/**
 * Hows the currently active view orientation
 * of the specified <code>Scene2D</code>.
 * 
 * @author Risto Seene
 */
public class Axes2D extends JPanel implements MouseListener{

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> shows texture coordinates. */
	public static final int TEX = 0;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from positive X axis. */
	public static final int POS_X = 1;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from positive Y axis. */
	public static final int POS_Y = 2;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from positive Z axis. */
	public static final int POS_Z = 3;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from negative X axis. */
	public static final int NEG_X = 4;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from negative Y axis. */
	public static final int NEG_Y = 5;

	/** <code>Scene2D</code> associated with this <code>Axes2D</code> views geometry from negative Z axis. */
	public static final int NEG_Z = 6;

	private int type;
	private int startX;
	private int startY;
	private int sizeX;
	private int sizeY;

	private Scene2D scene = null;


	/**
	 * Creates an instance of <code>Axes2D</code>
	 * of the specified type.
	 * 
	 * @param type
	 * 	<code>TEX</code>, <code>POS_X</code>, <code>POS_Y</code>
	 *        <code>POS_Z</code>, <code>NEG_X</code>, <code>NEG_Y</code>
	 *        <code>NEG_Z</code>
	 */
	public Axes2D(int type){
		this.type = type;
		updateSize();
		setOpaque(false);
	}

	/**
	 * Creates an instance of <code>Axes2D</code>
	 * which will be asoociated with the specified
	 * <code>Scene2D</code>.
	 * 
	 * @param scene
	 * 	<code>Scene2D</code>
	 */
	public Axes2D(Scene2D scene){
		this(scene.getViewPoint());
		this.scene = scene;
		addMouseListener(this);
	}

	/**
	 * Updates the size of the arrow according to
	 * the size of panel.
	 */
	private void updateSize(){
		if(getHeight() < getWidth()){
			sizeX = sizeY = (int)(0.8 * getHeight());
		} else {
			sizeX = sizeY = (int)(0.8 * getWidth());
		}
		startX = (getWidth() - sizeX) / 2;
		startY = (getHeight() - sizeY) / 2;
	}

	/**
	 * Draws an arrow to this panel.
	 * 
	 * @param g
	 * 	graphics
	 * @param orient
	 * 	0 - up,
	 *        1 - right,
	 *        2 - down,
	 *        3 - left
	 * @param name
	 * 	name of the axis
	 * @param color
	 * 	color of the arrow
	 * @param offset
	 * 	arrow offset
	 */
	private void drawArrow(Graphics2D g, int orient, String name, Color color, int offset){
		g.setColor(color);
		int[] x = new int[3];
		int[] y = new int[3];

		if(orient == 0 || orient == 2){
			g.fillRect(startX + (int)(sizeX / 2) + offset, startY + 1 + offset, 1, sizeY - 3);
			x[0] = startX + (int)(sizeX / 2) + offset;
			x[1] = x[0] - 2;
			x[2] = x[0] + 3;
			if(orient == 0){
				y[0] = startY + offset;
				y[1] = y[2] = y[0] + 8;
				g.fillPolygon(x, y, 3);
				g.drawString(name, x[0] + 6, y[0] + 6);
			} else {
				y[0] = startY + sizeY - 1 + offset;
				y[1] = y[2] = y[0] - 8;
				g.fillPolygon(x, y, 3);
				g.drawString(name, x[0] - 12, y[0] + 4);
			}
		} else if(orient == 1 || orient == 3){
			g.fillRect(startX + 1 + offset, startY + (int)(sizeY / 2) + offset, sizeX - 3, 1);
			y[0] = startY + (int)(sizeY / 2) + offset;
			y[1] = y[0] - 2;
			y[2] = y[0] + 3;
			if(orient == 1){
				x[0] = startX + sizeX - 1 + offset;
				x[1] = x[2] = x[0] - 8;
				g.fillPolygon(x, y, 3);
				g.drawString(name, x[0] - 6, y[0] + 14);
			} else {
				x[0] = startX + offset;
				x[1] = x[2] = x[0] + 8;
				g.fillPolygon(x, y, 3);
				g.drawString(name, x[0] - 2, y[0] - 4);
			}
		}
	}

	/**
	 * Overrided <code>paintComponent</code> method of <code>JPanel</code>.
	 * Draws the content of this panel.
	 * 
	 * @param graphics
	 * 	graphics
	 */
	public void paintComponent(Graphics graphics){
		Graphics2D g = (Graphics2D)graphics;
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		super.paintComponent(g);

		updateSize();

		if(type == 1){
			drawArrow(g, 3, "Z", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 0, "Y", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 3, "Z", Color.green, 0);
			drawArrow(g, 0, "Y", Color.blue, 0);
		} else if(type == 2){
			drawArrow(g, 1, "X", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 2, "Z", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 1, "X", Color.red, 0);
			drawArrow(g, 2, "Z", Color.green, 0);
		} else if(type == 3){
			drawArrow(g, 1, "X", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 0, "Y", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 1, "X", Color.red, 0);
			drawArrow(g, 0, "Y", Color.blue, 0);
		} else if(type == 4){
			drawArrow(g, 1, "Z", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 0, "Y", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 1, "Z", Color.green, 0);
			drawArrow(g, 0, "Y", Color.blue, 0);
		} else if(type == 5){
			drawArrow(g, 1, "X", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 0, "Z", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 1, "X", Color.red, 0);
			drawArrow(g, 0, "Z", Color.green, 0);
		} else if(type == 6){
			drawArrow(g, 3, "X", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 0, "Y", new Color(0, 0, 0, 128), 1);
			drawArrow(g, 3, "X", Color.red, 0);
			drawArrow(g, 0, "Y", Color.blue, 0);
		}
	}


	/**
	 * Flips the scene associated with this <code>Axes2D</code>.
	 * 
	 * @param e
	 * 	mouse event
	 */
	public void mousePressed(MouseEvent e){
		if(scene != null){
			scene.flip();
			type = scene.getViewPoint();
			repaint();
		}
	}

	/**
	 * Doesn't do anything.
	 * 
	 * @param e
	 * 	doesn't do anything
	 */
	public void mouseReleased(MouseEvent e){
	}

	/**
	 * Doesn't do anything.
	 * 
	 * @param e
	 * 	doesn't do anything
	 */
	public void mouseClicked(MouseEvent e){
	}

	/**
	 * Doesn't do anything.
	 * 
	 * @param e
	 *        doesn't do anything
	 */
	public void mouseEntered(MouseEvent e){
	}

	/**
	 * Doesn't do anything.
	 * 
	 * @param e
	 *        doesn't do anything
	 */
	public void mouseExited(MouseEvent e){
	}

}
