package smart_gs.drawing_tool.drawing_mode;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;

import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Double;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;

import smart_gs.drawing_tool.ExLine2D;
import smart_gs.drawing_tool.LineSegEditorCanvas;
import smart_gs.drawing_tool.view.LineView;
import smart_gs.drawing_tool.view.RectangleView;
import smart_gs.drawing_tool.view.View;
import smart_gs.logical.LineSegmentForEdit;
import smart_gs.smleditor.swingui.LineSegEditor;
import smart_gs.swingui.GSMouseEvent;


public class LineSegEditorDrawRectangleModeForTouchPanel implements LineSegEditorMode {
	
	enum State {FIRST_CORNER, SECOND_CORNER, TO_FIX};
	
	private State state;
	private Point2D first=null;
	private Point2D second=null;
	private View firstVertical = null;
	private View firstHorizontal = null;
	private View secondVertical = null;
	private View secondHorizontal = null;
	private View rectangle = null;
	private LineSegEditor editor;
	private LineSegEditorCanvas canvas;
	private int height;
	private int width;
//	For touch panel
	private double rectangle_x=0, rectangle_y=0, rectangle_width=0, rectangle_height=0;
//	For mouse UI
	private Point2D start = null, end = null;
	double mouse_rect_x=-100, mouse_rect_y=0, mouse_rect_width=0, mouse_rect_height=0;


	public LineSegEditorDrawRectangleModeForTouchPanel(LineSegEditor editor) {
		this.editor = editor;
		this.canvas = editor.getLineSegEditorCanvas();
		this.height = canvas.getImageIcon().getImage().getHeight(null);
		this.width = canvas.getImageIcon().getImage().getWidth(null);
		this.state = State.FIRST_CORNER;
	}
	
	@Override
	public void cancel() {
		// TODO Auto-generated method stub

	}

	@Override
	public LineSegEditor getParentLinesegEditor() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public void mouseClicked(GSMouseEvent e, LineSegEditorCanvas canvas) {
		setCursor(canvas);
		
		if (e.getButton() != MouseEvent.BUTTON1) {
			return;
		}

		if (state == State.FIRST_CORNER) {
			if (first == null) {
				this.first = e.getPoint();
				this.state = State.SECOND_CORNER;
			} 
		} else if (state == State.SECOND_CORNER) {
			if(first != null) {
				this.second = e.getPoint();

				rectangle_x = Math.min(first.getX(), second.getX());
				rectangle_y = Math.min(first.getY(), second.getY());
				rectangle_width = Math.abs(first.getX()-second.getX());
				rectangle_height = Math.abs(first.getY()-second.getY());
				
				this.rectangle = new RectangleView(new Rectangle2D.Double(rectangle_x,rectangle_y,rectangle_width,rectangle_height));
				
				this.state = State.TO_FIX;
			}
		} else if (state == State.TO_FIX) {
			if (this.rectangle.contains(e.getPoint2D())) {
				List<Point2D> rectLines = createRectLines();
				this.canvas.addLineSegmentForEdit(new LineSegmentForEdit(this.editor, rectLines, this.editor.getSpread().getLineDirection()));
				this.editor.rewriteLineSegIndexes();
			} 
			initialize();
		}
		
		if (first != null) createFirstCoordinate(first);
		if (second != null) createSecondCoordinate(second);
		this.editor.invalidate();
		this.editor.validate();
		this.editor.repaint(); 
	}
	
	private List<Point2D> createRectLines() {
		List<Point2D> rectLines = new ArrayList<Point2D>();
		rectLines.add(new Point2D.Double(this.rectangle_x,this.rectangle_y));
		rectLines.add(new Point2D.Double(this.rectangle_x+this.rectangle_width,this.rectangle_y));
		rectLines.add(new Point2D.Double(this.rectangle_x+this.rectangle_width,this.rectangle_y+this.rectangle_height));
		rectLines.add(new Point2D.Double(this.rectangle_x,this.rectangle_y+this.rectangle_height));
		return rectLines;
	}
	
	private List<Point2D> createRectLinesForMouseUI() {
		List<Point2D> rectLines = new ArrayList<Point2D>();
		double rectangle_x, rectangle_y, rectangle_height, rectangle_width;
		rectangle_x = Math.min(start.getX(), end.getX());
		rectangle_y = Math.min(start.getY(), end.getY());
		rectangle_width = Math.abs(start.getX()-end.getX());
		rectangle_height = Math.abs(start.getY()-end.getY());
		rectLines.add(new Point2D.Double(rectangle_x,rectangle_y));
		rectLines.add(new Point2D.Double(rectangle_x+rectangle_width,rectangle_y));
		rectLines.add(new Point2D.Double(rectangle_x+rectangle_width,rectangle_y+rectangle_height));
		rectLines.add(new Point2D.Double(rectangle_x,rectangle_y+rectangle_height));
		return rectLines;
	}
	
	private void initialize() {
		this.first = null;
		this.second = null;
		this.firstVertical = null;
		this.firstHorizontal = null;
		this.secondVertical = null;
		this.secondHorizontal = null;
		this.state = State.FIRST_CORNER;
		this.rectangle = null;
		this.start = null;
		this.end = null;
		this.mouse_rect_x = -100;
	}
	

	private void createFirstCoordinate(Point2D point) {
		firstHorizontal = new LineView(new ExLine2D(new Point2D.Double(0,point.getY()),new Point2D.Double(this.width,point.getY())));
		firstVertical = new LineView(new ExLine2D(new Point2D.Double(point.getX(),0),new Point2D.Double(point.getX(),this.height)));
	}

	private void createSecondCoordinate(Point2D point) {
		secondHorizontal = new LineView(new ExLine2D(new Point2D.Double(0,point.getY()),new Point2D.Double(this.width,point.getY())));
		secondVertical = new LineView(new ExLine2D(new Point2D.Double(point.getX(),0),new Point2D.Double(point.getX(),this.height)));
	}

	@Override
	public void mouseDragged(GSMouseEvent e, LineSegEditorCanvas canvas) {
		if (start == null) return;
		Point2D current = e.getPoint2D();
		this.mouse_rect_x = Math.min(start.getX(), current.getX());
		this.mouse_rect_y = Math.min(start.getY(), current.getY());
		this.mouse_rect_width = Math.abs(start.getX()-current.getX());
		this.mouse_rect_height = Math.abs(start.getY()-current.getY());
	}

	@Override
	public void mouseEntered(GSMouseEvent e, LineSegEditorCanvas canvas) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(GSMouseEvent e, LineSegEditorCanvas canvas) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseMoved(GSMouseEvent e, LineSegEditorCanvas canvas) {

	}

	@Override
	public void mousePressed(GSMouseEvent e, LineSegEditorCanvas canvas) {
		this.start = e.getPoint2D();
	}

	@Override
	public void mouseReleased(GSMouseEvent e, LineSegEditorCanvas canvas) {
		this.end = e.getPoint2D();
		
		if (this.end.distance(this.start) < 100.0d) return;

		List<Point2D> rectLines = createRectLinesForMouseUI();
		this.canvas.addLineSegmentForEdit(new LineSegmentForEdit(this.editor, rectLines, this.editor.getSpread().getLineDirection()));
		this.editor.rewriteLineSegIndexes();

		initialize();

		this.editor.invalidate();
		this.editor.validate();
		this.editor.repaint(); 
	}

	@Override
	public void paint(Graphics g, LineSegEditorCanvas canvas) {
		double ratio = canvas.getLineSegEditorImageLabel().getRatio();
		double gapX = canvas.getLineSegEditorImageLabel().getGapWidth();
		double gapY = canvas.getLineSegEditorImageLabel().getGapHeight();

		if (this.firstHorizontal != null) {
			this.firstHorizontal.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		} 
		if (this.secondHorizontal != null) {
			this.secondHorizontal.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		} 
		if (this.firstVertical != null) {
			this.firstVertical.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		} 
		if (this.secondVertical != null) {
			this.secondVertical.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		} 
		
		if (this.firstHorizontal  == null && this.secondVertical == null && mouse_rect_x != -100) {
			LineView line;
			Point2D p1, p2;
			
			p1 = new Point2D.Double(this.mouse_rect_x,this.mouse_rect_y);
			p2 = new Point2D.Double(this.mouse_rect_x+this.mouse_rect_width,this.mouse_rect_y);	
			line = new LineView(new ExLine2D(p1,p2));
			line.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
			
			p1 = p2;
			p2 = new Point2D.Double(this.mouse_rect_x+this.mouse_rect_width,this.mouse_rect_y+this.mouse_rect_height);	
			line = new LineView(new ExLine2D(p1,p2));
			line.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
			
			p1 = p2;
			p2 = new Point2D.Double(this.mouse_rect_x,this.mouse_rect_y+this.mouse_rect_height);		
			line = new LineView(new ExLine2D(p1,p2));
			line.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
			
			p1 = p2;
			p2 = new Point2D.Double(this.mouse_rect_x,this.mouse_rect_y);	
			line = new LineView(new ExLine2D(p1,p2));
			line.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		}

		setCursor(canvas);
	}

	@Override
	public void setParentLinesegEditor() {
		// TODO Auto-generated method stub

	}
	
	public void setCursor(LineSegEditorCanvas canvas) {
		canvas.getLineSegEditorImageLabel().setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));		
	}
}
