package chronoDivers;

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

import chrono.ChronoPanel;
import signals.Signals;

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