import java.awt.Point;
import java.util.Vector;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.geom.GeneralPath;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;
import java.lang.Math;

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

/**
 * @author Milan Ruzicka
 *
 */

public class Pencil extends Tool {
	public final boolean drawable = true;
	final int xSize = 1024;
	final int ySize = 768;
	
	public float width = 2.0f;
	public float hardness = 0.8f;
	
	private static final long serialVersionUID = 11L; 
	
	/**
	 * 
	 */	
	public Pencil() {
		points = new Vector();
		colors = new Vector();
		
		colors.add(Color.DARK_GRAY);
		colors.add(Color.blue);
	}
	
	public Pencil(Color c) {
		points = new Vector();
		colors = new Vector();
		
		colors.add(c);
		colors.add(Color.blue);
	}

	/* (non-Javadoc)
	 * @see Tool#draw(java.awt.Image)
	 */
	@Override
	public void draw(Graphics g2) {
		
		BufferedImage buf = new BufferedImage(xSize,ySize,BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = (Graphics2D)buf.getGraphics();
		g.setColor(new Color(1.0f,1.0f,1.0f,0.0f));
		g.fillRect(0, 0, xSize, ySize);
		
		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);

		  
		 		
		g.setColor((Color) colors.get(0));
		GeneralPath gp = new GeneralPath();
		for (int i=0; i < points.size()-1;i++) {
			
			gp.append(new Line2D.Float((Point)points.get(i),(Point)points.get(i+1)), true);
		}
		g.draw(gp);
		
		BufferedImage noise = new BufferedImage(xSize,ySize,BufferedImage.TYPE_INT_ARGB);
		for (int i=0; i<xSize; i++)
			for (int j=0; j<ySize; j++){
				
				if (buf.getRGB(i, j) != 0) {
					
					int tmp = buf.getRGB(i, j);
					Color c = new Color(tmp,true);
					
					int R = c.getRed();
					int G = c.getGreen();
					int B = c.getBlue();
					float rate =(float)Math.random() * hardness +(1f - hardness);
					int A = Math.round(((float)c.getAlpha())* rate );

				    Color c2 = new Color(R,G,B,A);
				    buf.setRGB(i, j, c2.getRGB());
					
				}
			}
		
		float cent = 0.9f;
		float sur = (1f-cent ) / 24f;


		ConvolveOp Op = new ConvolveOp(new Kernel(5,5,new float[] {
			sur, sur, sur, sur, sur,
			sur, sur, sur, sur, sur,
			sur, sur, cent, sur, sur,
			sur, sur, sur, sur, sur,
			sur, sur, sur, sur, sur
		}));
		buf = Op.filter(buf, null);
		
		g2.drawImage(buf, 0, 0, null);
		
	}
	
	public void setColor(Color c){
		colors.set(0, new Color(c.getRed(),c.getGreen(),c.getBlue(),255));
	}
	
	public void drawPreview(Graphics g1) {
		Graphics2D g = (Graphics2D) g1;
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
		  Stroke thindashed = new BasicStroke(2.0f, // 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.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,50,800,200);
		widthSlider.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				width = (float)((JSlider)e.getSource()).getValue()/100f;
			}
		});
		widthSlider.setPreferredSize(new Dimension(50,20));
        panel.add(widthSlider);
        
        
		panel.add(new JLabel("Hardness"));
		
		JSlider hardSlider = new JSlider(JSlider.HORIZONTAL,50,100,80);
		hardSlider.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent e){
				hardness = (float)((JSlider)e.getSource()).getValue()/100f;
			}
		});
		hardSlider.setPreferredSize(new Dimension(50,20));
        panel.add(hardSlider);

        
        
        panel.setLayout(new BoxLayout(panel,BoxLayout.Y_AXIS));
        
		return panel;
	}
	
	public boolean isDrawable(){
		return true;
	}

}