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.AffineTransform;
import java.awt.geom.Point2D;
import smart_gs.drawing_tool.ExLine2D;
import smart_gs.drawing_tool.LineSegEditorCanvas;
import smart_gs.drawing_tool.view.LineView;
import smart_gs.smleditor.swingui.LineSegEditor;
import smart_gs.swingui.GSMouseEvent;
import smart_gs.swingui.toolbar.action.LineSegEditorTiltImagePanel;
import smart_gs.util.GSLog;
import sml_editor.logical.LineDirection;

public class LineSegEditorTiltImagePanelLevelLineMode implements LineSegEditorMode {
	private GSLog log = GSLog.getInstance();
	private Point2D start=null;
	private Point2D end=null;
	private double degree;
	private LineView line;
	private LineSegEditor editor;
	private LineSegEditorTiltImagePanel panel;
	
	
	public LineSegEditor getEditor() {
		return this.editor;
	}

	public LineSegEditorTiltImagePanelLevelLineMode(LineSegEditor editor, LineSegEditorTiltImagePanel panel) {
		this.editor = editor;
		this.panel = panel;
		this.panel.saveOldDegree();
	}

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

		if (start == null) {
			if(e.getClickCount() == 1) {
				this.line = null;
				this.start = e.getPoint();
				this.end = this.start;
				return;
			} 
		} 
		
		if (start != null) {
			if(e.getClickCount() == 2) {
				this.end = e.getPoint();
				double x = start.getX() - end.getX();
				double y = start.getY() - end.getY();

				if (canvas.getSpread().getLineDirection() == LineDirection.HORIZONTAL) {
					if (x == 0.0) {
						log.error("Points are too closed.");
						start = null;
						end = null;
						return;
					} else {

						this.degree = Math.atan(y/x);
						
						if (Math.abs(degree)> 0.785d) {
							log.error("The level line cannot be tilted more than pi/4 radian (= 0.785 radian, = 45 degree) from the horizontal line.");
							start = null;
							end = null;
							return;
						}
					}
				}
				this.line = new LineView(new ExLine2D(start,end));
				this.panel.setDegree(degree);
				this.start = null;
				this.end = null;
			}
		}
		this.panel.repaint();
	}
	
	public void mouseMoved(GSMouseEvent e,LineSegEditorCanvas canvas) {
		setCursor(canvas);
		if (this.start == null) return;
		this.end = e.getPoint();
		double x = start.getX() - end.getX();
		double y = start.getY() - end.getY();
		if (canvas.getSpread().getLineDirection() == LineDirection.HORIZONTAL) {
			if (x == 0.0) {
				this.panel.setDegree(0.0);
				this.panel.repaint();
			} else {
				this.panel.setDegree(Math.atan(y/x));
				this.panel.validate();
				this.panel.repaint();
			}
		}
		setCursor(canvas);
	}

	@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.line != null) {
			this.line.enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		} else {
			if (this.start != null && this.end != null)
				new LineView(new ExLine2D(this.start,this.end)).enlargedView(ratio,gapX,gapY).draw((Graphics2D)g);
		}

		setCursor(canvas);
	}
	
	public void cancel() {
		// TODO Auto-generated method stub
		
	}
	
	public void mouseDragged(GSMouseEvent e, LineSegEditorCanvas canvas) {
		setCursor(canvas);		
	}
	
	public void mouseEntered(GSMouseEvent e, LineSegEditorCanvas canvas) {
		setCursor(canvas);		
	}
	
	public void mouseExited(GSMouseEvent e, LineSegEditorCanvas canvas) {
		setCursor(canvas);
		
	}
	
	public void mouseReleased(GSMouseEvent e, LineSegEditorCanvas canvas) {
		setCursor(canvas);		
	}
	
	public void setCursor(LineSegEditorCanvas canvas) {
		canvas.getLineSegEditorImageLabel().setCursor(new Cursor(Cursor.CROSSHAIR_CURSOR));		
	}

	public void giveLineSegEditor(LineSegEditor editor) {
		this.editor = editor;
	}

	public void resetLine() {
		this.line = null;
	}

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

	public void adjustLevelLine(double changeDegree) {
		Point2D start = line.getStartPoint();
		Point2D end = line.getEndPoint();
		AffineTransform transformation = AffineTransform.getRotateInstance(changeDegree,start.getX(),start.getY());
		Point2D startNew = new Point2D.Double();
		Point2D endNew = new Point2D.Double();
		transformation.transform(start,startNew);
		transformation.transform(end,endNew);
		line = new LineView(startNew,endNew);
	}
}
