import java.awt.Point;
import java.util.Vector;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.BasicStroke;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import java.awt.Dimension;
import javax.swing.event.ChangeListener;
import javax.swing.event.ChangeEvent;

import java.awt.image.BufferedImage;


/**
 * @author Milan Ruzicka
 *
 */

public class FeltTipPen extends Tool {
	public final boolean drawable = true;
	private static final long serialVersionUID = 12L; 
	
	public float width = 2.0f;
	public int alpha = 255;
	
	private long startTime;
	private long lastTime;
	private int lastX;
	private int lastY;
	
	final int xSize = 1024;
	final int ySize = 768;
	
	/**
	 * 
	 */	
	public FeltTipPen() {
		points = new Vector();
		colors = new Vector();
		time = new Vector();
		data = new Vector();
		
		colors.add(Color.blue);
		colors.add(Color.blue);
	}
	
	public FeltTipPen(Color c) {
		points = new Vector();
		colors = new Vector();
		time = new Vector();
		data = new Vector();
		
		Color cc = new Color(c.getRed(),c.getGreen(),c.getBlue(),alpha);
		colors.add(cc);
		colors.add(Color.blue);
	}

	/* (non-Javadoc)
	 * @see Tool#draw(java.awt.Image)
	 */
	@Override
	public void draw(Graphics g1) {
		Graphics2D g2 = (Graphics2D) g1;
		
		BufferedImage buf = new BufferedImage(xSize,ySize,BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = (Graphics2D)buf.getGraphics();
		Color cc = new Color(1f,1f,1f,0f);	
		for (int i=0; i<xSize; i++)
			for (int j=0; j<ySize;j++){
				buf.setRGB(i, j, cc.getRGB());
			}
				
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		  Stroke thindashed = new BasicStroke(width, // line width
			      /* cap style */BasicStroke.CAP_BUTT,
			      /* join style, miter limit */BasicStroke.JOIN_BEVEL, 1.0f);//,
			      /* the dash pattern *///new float[] { 8.0f, 3.0f, 2.0f, 3.0f },
			      /* the dash phase *///0.0f); /* on 8, off 3, on 2, off 3 */
		g.setStroke(thindashed);
		Color des = (Color) colors.get(0);
		Color col = new Color(des.getRed(), des.getGreen(), des.getBlue(), 255);
		float alf = des.getAlpha();
		g.setColor(col);

		computeSpeeds();
		
		
		for (int i=0; i < points.size()-1;i++) {
			thindashed = new BasicStroke(lineWidthBySpeed((Double)data.get(i+1) ), // line width
				      /* cap style */BasicStroke.CAP_ROUND,
				      /* join style, miter limit */BasicStroke.JOIN_BEVEL, 1.0f);//,
				      /* the dash pattern *///new float[] { 8.0f, 3.0f, 2.0f, 3.0f },
				      /* the dash phase *///0.0f); /* on 8, off 3, on 2, off 3 */
			g.setStroke(thindashed);
			g.drawLine(((Point)points.get(i)).x, ((Point)points.get(i)).y, ((Point)points.get(i+1)).x, ((Point)points.get(i+1)).y);
			
		}
		
		
		for (int i=0; i<xSize; i++)
			for (int j=0; j<ySize; j++){
				if (buf.getRGB(i, j)!=0){
				Color a = new Color(buf.getRGB(i, j), true);
				Color b = new Color(a.getRed(),a.getGreen(),a.getBlue(),Math.round((((float)(a.getAlpha()))*alf/255f)));
				buf.setRGB(i, j, b.getRGB());
				}
			}
		
		
        g2.drawImage(buf, 0, 0, null);
	}
	
	public float lineWidthBySpeed(double speed){
		float result = (float)(((double)width)*(1d+1d/(speed/200d+1d)));
		return result;
		
	}
	
	public void setColor(Color c){
		Color cc = new Color(c.getRed(),c.getGreen(),c.getBlue(),alpha);
		colors.set(0, cc);
	}
	
	public void drawPreview(Graphics g1) {
		Graphics2D g = (Graphics2D) g1;
	
		g.setColor(Color.GRAY);
		for (int i=0; i < points.size()-1;i++) {
			g.drawLine(((Point)points.get(i)).x, ((Point)points.get(i)).y, ((Point)points.get(i+1)).x, ((Point)points.get(i+1)).y);
		}
	}
	
	public JPanel settingPanel(){
		JPanel panel = new JPanel();
		
		panel.add(new JLabel("Set width"));
		
		JSlider widthSlider = new JSlider(JSlider.HORIZONTAL,0,100,Math.round(width*10f));
		widthSlider.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				width = (float)((JSlider)e.getSource()).getValue()/10f;
			}
		});
		widthSlider.setPreferredSize(new Dimension(50,20));
        panel.add(widthSlider);
        
        panel.add(new JLabel("Opacity"));
        
		JSlider alphaSlider = new JSlider(JSlider.HORIZONTAL,0,255,255);
		alphaSlider.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				alpha = (int)((JSlider)e.getSource()).getValue();
				setColor((Color)colors.get(0));
			}
		});
		alphaSlider.setPreferredSize(new Dimension(50,20));
        panel.add(alphaSlider);
        
        panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
		return panel;
		
	}
	
	public boolean isDrawable(){
		return true;
	}
	
	public void computeSpeeds(){
		data.clear();
		data.add(0d);
		for (int i=1; i<time.size();i++){
			double distance = Math.sqrt( Math.pow(((Point)points.get(i-1)).getX() - ((Point)points.get(i)).getX(),2) + Math.pow(((Point)points.get(i-1)).getY() - ((Point)points.get(i)).getY(),2));
			double dTime = (Long)time.get(i) - (Long)time.get(i-1);
			double speed = 1000 * distance / dTime; 	
			data.add(speed);
		}
	}
	
	public void addPoint(Point p) {
		points.add(p);
		
		long curTime = System.currentTimeMillis();
		time.add(curTime);
		
	}
	
	public void clearPoints() {
		points.removeAllElements();
		time.removeAllElements();
		data.removeAllElements();
	}

}