import java.awt.*;
import java.util.*;
import java.applet.*;
import java.lang.*;
import java.awt.event.*;


public class CG_hw_06 extends BufferedApplet implements ActionListener
{	


	int bezier[][] = new int [4][4];
	
	int points[][] = new int [1000][2];
	
	int pic[][] = new int[30][2];
	int newN[][] = new int[30][2];
	int love[][]=new int[30][2];
	int me[][]=new int [30][2];
	
	
	
	
	
	int radius[] = new int[1000];
	
   	final int NOTHING = 0;
   	final int MOVING = 1;
   	int mode = NOTHING;	
   	
   	int screenMode = 0;
   	
   	Button coolPic ;
   	
   	Button freeDraw;
   	 
   	
   	
   	int ax, bx, cx, dx;
   	int ay, by, cy, dy;
   	
	Graphics g;
	
	int i=0;
	int k=5;
	int temp=0;
	
	boolean draw = true;
	boolean insert = true;

	boolean moving = false;
	
	public void init()
	{
		setLayout(null);
		
		
		populateBezier();
		
		
		freeDraw = new Button("FreeDraw");
		freeDraw.setLocation(10,480);
		freeDraw.setSize(80,20);
		add(freeDraw);
		
		coolPic = new Button("CoolPic");
		coolPic.setLocation(100,480);
		coolPic.setSize(80,20);
		add(coolPic);
		
		coolPic.addActionListener(this);
		freeDraw.addActionListener(this);
		
		
		pic[0][0] = 450;
		pic[0][1] = 196;
		pic[1][0] = 491;
		pic[1][1] = 141;
		pic[2][0] = 506;
		pic[2][1] = 89;
		pic[3][0] = 483;
		pic[3][1] = 87;
		pic[4][0] = 467;
		pic[4][1] = 121;
		pic[5][0] = 440;
		pic[5][1] = 137;
		pic[6][0] = 433;
		pic[6][1] = 165;
		pic[7][0] = 410;
		pic[7][1] = 130;
		pic[8][0] = 385;
		pic[8][1] = 118;
		pic[9][0] = 388;
		pic[9][1] = 82;
		pic[10][0] = 353;
		pic[10][1] = 85;
		pic[11][0] = 369;
		pic[11][1] = 143;
		pic[12][0] = 419;
		pic[12][1] = 197;
		pic[13][0] = 419;
		pic[13][1] = 240;
		pic[14][0] = 411;
		pic[14][1] = 306;
		pic[15][0] = 435;
		pic[15][1] = 316;
		pic[16][0] = 452;
		pic[16][1] = 297;
		pic[17][0] = 448;
		pic[17][1] = 260;	
		pic[18][0] = 449;
		pic[18][1] = 200;	
		
		
		newN[0][0] = 409;
		newN[0][1] = 128;
		newN[1][0] = 438;
		newN[1][1] = 193;
		newN[2][0] = 452;
		newN[2][1] = 230;
		newN[3][0] = 403;
		newN[3][1] = 286;
		newN[4][0] = 444;
		newN[4][1] = 290;
		newN[5][0] = 455;
		newN[5][1] = 259;
		newN[6][0] = 465;
		newN[6][1] = 226;
		newN[7][0] = 486;
		newN[7][1] = 248;
		newN[8][0] = 503;
		newN[8][1] = 271;
		newN[9][0] = 543;
		newN[9][1] = 288;
		newN[10][0] = 529;
		newN[10][1] = 254;
		newN[11][0] = 526;
		newN[11][1] = 189;
		newN[12][0] = 550;
		newN[12][1] = 135;
		newN[13][0] = 517;
		newN[13][1] = 134;
		newN[14][0] = 504;
		newN[14][1] = 174;
		newN[15][0] = 505;
		newN[15][1] = 219;
		newN[16][0] = 487;
		newN[16][1] = 174;
		newN[17][0] = 454;
		newN[17][1] = 195;	
		newN[18][0] = 409;
		newN[18][1] = 128;	
		
		


		love[0][0] = 238;
		love[0][1] = 166;
		love[1][0] = 192;
		love[1][1] = 107;
		love[2][0] = 179;
		love[2][1] = 175;
		love[3][0] = 239;
		love[3][1] = 249;
		love[4][0] = 277;
		love[4][1] = 192;
		love[5][0] = 300;
		love[5][1] = 101;
		love[6][0] = 238;
		love[6][1] = 166;
	
	
		me[0][0] = 103;
		me[0][1] = 127;
		me[1][0] = 12;
		me[1][1] = 132;
		me[2][0] = 37;
		me[2][1] = 23;
		me[3][0] = 101;
		me[3][1] = 18;
		me[4][0] = 106;
		me[4][1] = 137;
		me[5][0] = 127;
		me[5][1] = 258;
		me[6][0] = 36;
		me[6][1] = 183;
		
				
			
		
	}


	
	public void render(Graphics t) 
	{
		
		g=t;
		
		if(screenMode == 0)
		{
		
		g.setColor(Color.white);
      	g.fillRect(0,0,600,500);
      	
      	
		
		g.setColor(Color.black);
		
		g.drawRect(0,0,600,500);
	
		if(damage)		
		{
			

			for(int k=0;k<i;k++)
			{
				g.setColor(Color.black);
				
				
				drawThing(g,points[k][0],points[k][1],radius[k]);
				if( ((k%3)!=0) || k!=0)
				{
					g.setColor(Color.pink);
					g.drawLine(points[k-1][0],points[k-1][1],points[k][0],points[k][1]);

					
				}
				
				if((k%3)==0 && k!=0)
				{
					
					convertX(points[k-3][0], points[k-2][0], points[k-1][0], points[k][0]);
					convertY(points[k-3][1], points[k-2][1], points[k-1][1], points[k][1]);
				
					g.setColor(Color.blue);
					drawCurve(g,0.05);
					
				}
				
			}
		}
				
		}
		else if(screenMode == 1)
		{
			g.setColor(Color.white);
      		g.fillRect(0,0,600,500);
      		g.setColor(Color.black);
		
			g.drawRect(0,0,600,500);
			
			for(int k=0;k<19;k++)
			{
				g.setColor(Color.black);
				
				if((k%3)==0 && k!=0)
				{
					
					convertX(pic[k-3][0], pic[k-2][0], pic[k-1][0], pic[k][0]);
					convertY(pic[k-3][1]-15, pic[k-2][1]-15, pic[k-1][1]-15, pic[k][1]-15);
				
					g.setColor(Color.black);
					drawCurve(g,0.05);
					
				}
				
			}
			
			
			
			for(int k=0;k<19;k++)
			{
				g.setColor(Color.black);
				

				
				if((k%3)==0 && k!=0)
				{
					
					convertX(newN[k-3][0]-45, newN[k-2][0]-45, newN[k-1][0]-45, newN[k][0]-45);
					convertY(newN[k-3][1], newN[k-2][1], newN[k-1][1], newN[k][1]);
				
					g.setColor(Color.black);
					drawCurve(g,0.05);
					
				}
				
			}	
			
			
			for(int k=0;k<7;k++)
			{
				g.setColor(Color.black);
				
				if((k%3)==0 && k!=0)
				{
					
					convertX(love[k-3][0], love[k-2][0], love[k-1][0], love[k][0]);
					convertY(love[k-3][1]+10, love[k-2][1]+10, love[k-1][1]+10, love[k][1]+10);
				
					g.setColor(Color.red);
					drawCurve(g,0.05);
					
				}
				
			}
			
			for(int k=0;k<7;k++)
			{
				g.setColor(Color.black);
				

				
				if((k%3)==0 && k!=0)
				{
					
					convertX(me[k-3][0], me[k-2][0], me[k-1][0], me[k][0]);
					convertY(me[k-3][1]+80, me[k-2][1]+80, me[k-1][1]+80, me[k][1]+80);
				
					g.setColor(Color.black);
					drawCurve(g,0.05);
					
				}
				
			}		
      	
      	}
		
		animating = true;
	}
	
	public void populateBezier()
	{
		
		bezier[0][0] = -1;
		bezier[0][1] =  3;
		bezier[0][2] = -3;
		bezier[0][3] =  1;
		bezier[1][0] =  3;
		bezier[1][1] = -6;
		bezier[1][2] =  3;
		bezier[1][3] =  0;
		bezier[2][0] = -3;
		bezier[2][1] =  3;
		bezier[2][2] =  0;
		bezier[2][3] =  0;
		bezier[3][0] =  1;
		bezier[3][1] =  0;
		bezier[3][2] =  0;
		bezier[3][3] =  0;
	}
	
	
	public void convertX(int Ax, int Bx, int Cx, int Dx)
	{
		ax = bezier[0][0]*Ax + bezier[0][1]*Bx + bezier[0][2]*Cx + bezier[0][3]*Dx;
		bx = bezier[1][0]*Ax + bezier[1][1]*Bx + bezier[1][2]*Cx + bezier[1][3]*Dx;
		cx = bezier[2][0]*Ax + bezier[2][1]*Bx + bezier[2][2]*Cx + bezier[2][3]*Dx;
		dx = bezier[3][0]*Ax + bezier[3][1]*Bx + bezier[3][2]*Cx + bezier[3][3]*Dx;
		
	}
	
	public void convertY(int Ay, int By, int Cy, int Dy)
	{
		ay = bezier[0][0]*Ay + bezier[0][1]*By + bezier[0][2]*Cy + bezier[0][3]*Dy;
		by = bezier[1][0]*Ay + bezier[1][1]*By + bezier[1][2]*Cy + bezier[1][3]*Dy;
		cy = bezier[2][0]*Ay + bezier[2][1]*By + bezier[2][2]*Cy + bezier[2][3]*Dy;
		dy = bezier[3][0]*Ay + bezier[3][1]*By + bezier[3][2]*Cy + bezier[3][3]*Dy;
		
	}
	
	public double X(double t)
	{
		return (ax*t*t*t  +  bx*t*t  +  cx*t  +  dx);
		
	}

	public double Y(double t)
	{
		return (ay*t*t*t  +  by*t*t  +  cy*t  +  dy);
		
	}	
	
	
	public void drawCurve(Graphics g, double e)
	{

		for (double t = 0 ; t < 1 ; t += e)
		{
			int temp1[]={(int)X(t),(int)X(t+e)};
			int temp2[]={(int)Y(t),(int)Y(t+e)};
      	//	g.drawLine((int)X(t), (int)Y(t), (int)X(t+e), (int)Y(t+e));
      		g.drawPolygon(temp1, temp2,2);
      	}
   	}

	
   	public void drawThing(Graphics g, int x, int y, int radius)
   	{

         g.fillOval(x - radius, y - radius, radius*2, radius*2);
      
	}

	public boolean mouseDown(Event e, int x, int y)
	{
		mode = NOTHING;
		insert = true;
		draw = true;
		
		
		
		for(int j=0;j<i;j++)
		{
			
			int dxA = x - points[j][0];
         	int dyA = y - points[j][1];
         	int r = (int)Math.sqrt(dxA * dxA + dyA * dyA);
         	
	
			if(r<radius[j])
			{
				insert = false;
				mode = MOVING;
				temp = j;

        	}
			
				
				
		}
		

		if(insert == true)
		{
			
			points[i][0]=x;
			points[i][1]=y;
			
			
			if((i%3) == 0)
				radius[i]=7;
			else
				radius[i]=4;
		
			i++;
		}

		return true;

	}
	
	public boolean mouseUp(Event e)
	{
		
		
		return true;
	}
	
	public boolean mouseDrag(Event e, int x, int y)
	{
	
		switch (mode) 
		{
      		case NOTHING:
	 			break;
      		case MOVING:
        	 	points[temp][0] = x;
         		points[temp][1] = y;
	 			break;
	 	}
		
		return true;
	}
	
	
	public void actionPerformed(ActionEvent e)
	{
		String label = (String)e.getActionCommand();
		
	
		if(label == "CoolPic")
		{
			screenMode=1;
			
		}
		else if(label == "FreeDraw")
		{
			screenMode=0;
			
			
		}
		
		
		
		
	}
}