package tools;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.Serializable;

import main.ChronoPanel;

import signals.Signals;

public class Arrow implements Serializable{
	
	private static final long serialVersionUID = 1L;
	
	private ChronoPanel chrono;
	private Signals fromSignal,toSignal;
	private int fromIndex,toIndex;
	
	private int x0,y0,x1,y1;
	private int l = 9;
	private double offsetAngle = Math.PI/5;
	public boolean selected=false;
	
	private boolean drawStart=false,drawEnd=false,complete=false;
	
	public Arrow(ChronoPanel chrono){
		this.chrono=chrono;
		this.fromIndex=1;
		this.toIndex=1;
		fromSignal=chrono.signals.get(0);
		drawStart=true;
	}
	
	public void setStart(Signals s,int xMouse){
		drawStart=true;
		fromSignal=s;
		this.fromIndex=Math.max(1,(int)((float)(xMouse-Signals.leftSpace+(float)s.widthUnit/4)*2/(float)s.widthUnit));
		if (s.clkToQdelay) this.fromIndex=Math.max(1,(int)((float)(xMouse-Signals.leftSpace+s.widthUnit/2+(float)s.widthUnit/4)*2/(float)s.widthUnit));
	}
	
	public void setEnd(Signals s,int xMouse){
		drawStart=false;
		drawEnd=true;
		toSignal=s;
		this.toIndex=Math.max(1,(int)((float)(xMouse-Signals.leftSpace+(float)s.widthUnit/4)*2/(float)s.widthUnit));
		if (s.clkToQdelay) this.toIndex=Math.max(1,(int)((float)(xMouse-Signals.leftSpace+s.widthUnit/2+(float)s.widthUnit/4)*2/(float)s.widthUnit));
	}
	
	public void done(){
		drawEnd=false;
		complete=true;
	}
	
	public void draw(Graphics g){
		
		if (drawStart){
			updatePositions(true,false);
			g.setColor(Color.BLACK);
			g.fillOval(x0-2, y0-2, 5, 5);
		}
		if (drawEnd){
			updatePositions(false,true);
			g.setColor(Color.BLACK);
			g.fillOval(x1-2, y1-2, 5, 5);
		}
		if (drawEnd || complete){
			if (complete)updatePositions(true,true);
			Graphics2D g2 = (Graphics2D)g;
			if (!drawEnd && selected) g2.setStroke(new BasicStroke(3f));
			else g2.setStroke(new BasicStroke(1f));
			
			g.setColor(new Color(80,80,80));
			g.drawLine(x0, y0, x1, y1);
			double alpha = -Math.PI/2;
			if (x1!=x0) alpha = Math.atan((float)(y1-y0)/(float)(x1-x0));
			if (x1<x0) alpha=alpha+Math.PI;
			g.drawLine(x1, y1, (int)(x1-l*Math.cos(alpha+offsetAngle)), (int)(y1-l*Math.sin(alpha+offsetAngle)));
			g.drawLine(x1, y1, (int)(x1-l*Math.cos(alpha-offsetAngle)), (int)(y1-l*Math.sin(alpha-offsetAngle)));
		}
	}
	
	
	public void updatePositions(boolean start, boolean end){
		if (start){
			x0 = Signals.leftSpace+fromIndex*fromSignal.widthUnit/2;
			if (fromSignal.clkToQdelay) x0-=fromSignal.widthUnit/2;
			y0 = chrono.getPosFromId(fromSignal.id)*(Signals.heightUnit+Signals.Yspace)+Signals.Yspace;
			
			if (fromIndex%2!=0){
				if (fromSignal.wave[fromIndex/2]==0) y0+=Signals.heightUnit;
			}
			else{
				if (fromSignal.wave[(int)(fromIndex/2)-1]!=fromSignal.wave[(int)(fromIndex/2)]){
					y0+=Signals.heightUnit/2;
				}
				else{
					if (fromSignal.wave[fromIndex/2]==0) y0+=Signals.heightUnit;
				}
			}
		}
		if (end){
			x1 = Signals.leftSpace+toIndex*toSignal.widthUnit/2;
			if (toSignal.clkToQdelay) x1-=toSignal.widthUnit/2;
			y1 = chrono.getPosFromId(toSignal.id)*(Signals.heightUnit+Signals.Yspace)+Signals.Yspace;
			
			if (toIndex%2!=0){
				if (toSignal.wave[toIndex/2]==0) y1+=Signals.heightUnit;
			}
			else{
				if (toSignal.wave[(int)(toIndex/2)-1]!=toSignal.wave[(int)(toIndex/2)]){
					y1+=Signals.heightUnit/2;
				}
				else{
					if (toSignal.wave[toIndex/2]==0) y1+=Signals.heightUnit;
				}
			}
		}
	}
	
	public int getDistance(int xMouse, int yMouse){
		// y = ax + b;
		float a = (float)(y1-y0)/(float)(x1-x0);
		float b = y0 - a*x0;
		int distance = (int)(Math.abs(a * xMouse - yMouse + b) / Math.sqrt(1+a*a));
		if ((xMouse<x0-2 && xMouse<x1-2) || (xMouse>x0+2 && xMouse>x1+2)) distance=1000;
		return distance;
	}
}
