import java.awt.*;
import java.util.Random;
import java.lang.Math;

public class week1 extends BufferedApplet
{
	int wid=0, hei=0,
		mx=0, my=0,
		dx=0, dy=0;
	long T0;
	static Random rnd = new Random();
	Pom pom = new Pom();
	Cat cat = new Cat();
	Catthink think = new Catthink();
	
	public void render(Graphics g) {
		if(T0 == 0) {
			wid = bounds().width;
			hei = bounds().height;
			T0 = System.currentTimeMillis();
			animating = true;
		}
		double t = (System.currentTimeMillis()-T0) / 1000.0;
		
		g.setColor(Color.white);
		g.fillRect(0, 0, wid, hei);
	
		think.think(cat, mx, my, t);
		cat.calc();
		cat.draw(g);
		
		pom.draw(g, mx, my, dx, dy);
		//System.out.println("drawn at "+Integer.toString(mx)+" "+Integer.toString(my));
	}
	class Pom {
		final int STRINGS = 238,
			COLORS = 4;
		final double SIZE = 50;
		double x[] = new double[STRINGS],
			y[] = new double[STRINGS];
		Color colors[] = new Color[COLORS];
		Pom() {
			for(int i = 0; i<STRINGS; ++i) {
				double th = rnd.nextDouble()*2.*Math.PI;		
				x[i] = Math.cos(th) + rnd.nextGaussian()/7.;
				y[i] = Math.sin(th) + rnd.nextGaussian()/7.;
			}
			colors[0] = new Color(0,0,0);
			colors[1] = new Color(42,0,200);
			colors[2] = new Color(252,201,0);
			colors[3] = new Color(0,127,128);
			
		}
		void draw(Graphics g, int cx, int cy, int dx, int dy) {
			for(int i = 0; i<STRINGS; ++i) {
				g.setColor(colors[i%COLORS]);
				// cheap inertia: draw string ends one mouse move behind
				g.drawLine(cx, cy, cx-dx+(int)(x[i]*SIZE), cy-dy+(int)(y[i]*SIZE));
			}
		}
	}
	class Catthink {
		final double AVG_BLINK_RATE = 15,
			AVG_BLINK_TIME = .5;
		double last_blink = -1., next_blink = -1., blinky = -1.;
		void think(Cat cat, int mx, int my, double t) {
			cat.ix = mx*1000/wid;
			cat.iy = (hei-my)*1000/hei;
			cat.id = (int)(-Math.cos(t/60.)*350.)+550;
			if(blinky>.0) {
				double dt = t - last_blink;
				if(dt>blinky) {
					blinky = -1.;
					cat.l = 800;
				}
				else cat.l = (int)(400.*Math.cos(2.*Math.PI*dt/blinky))+400;
			}
			else if(last_blink<0. || t>next_blink) {
				if(t>next_blink)
					blinky = rnd.nextGaussian()*AVG_BLINK_TIME/2.;
				next_blink = t+rnd.nextGaussian()*AVG_BLINK_RATE/2.;
				last_blink = t;
			}
			cat.r = mx*1000/wid;
		}
	};
	class Cat {
		// public interface 0..1000
		public int ix = 500, iy = 500, id = 250, l = 800, // iris x,y,diam, lids
			r = 500, // rotation
			s = 0, // snag
			t = 0; // tail
		
		// constants
		final int X = 200, Y = 250, // head center
			HEAD = 120, BODY = 180, // diams
			DHB = 110, // dist head body
			EIS = 20, EOS = 10, // ear dxs
			EAH = 40, // ear height
			EYH = 25, EYW = 25, // eye size (open)
			IRH = 20, IRW = 20; // iris size (open)
		final Rectangle BACKR = new Rectangle(X-BODY/4,Y+DHB-BODY/2,3*BODY/2,5*BODY/6),
			HEADR = new Rectangle(X-HEAD/2,Y-HEAD/2,HEAD,HEAD),
			BODYR = new Rectangle(X-BODY/2,Y+DHB-BODY/2,BODY,BODY);
		final Color EYECOLOR = new Color(198,253,12);
			
		// ... everything in between...
		int earx1_[] = new int[3],
			eary1_[] = new int[3],
			earx2_[] = new int[3],
			eary2_[] = new int[3];
		
		Rectangle eye1_ = new Rectangle(), 
			eye2_ = new Rectangle(),
			iris1_ = new Rectangle(),
			iris2_ = new Rectangle();
		
		Cat() {
			calc();
		}
		void calc() {
			final int earb = Y-HEAD/3,
				earo = (int)(Math.sin((r+500)/2000.*Math.PI)*HEAD/4.);
			earx1_[0] = X-earo-EOS; eary1_[0] = earb;
			earx1_[1] = X-earo;     eary1_[1] = earb-EAH;
			earx1_[2] = X-earo+EIS; eary1_[2] = earb;
			earx2_[0] = X+earo-EIS; eary2_[0] = earb;
			earx2_[1] = X+earo;     eary2_[1] = earb-EAH;
			earx2_[2] = X+earo+EOS; eary2_[2] = earb;
			
			final int eyey = Y - EYH/4,
				eyeh = EYH*l/1000;
			eye1_.y = eye2_.y = eyey - eyeh/2;
			eye1_.x = X - EYW/2 - HEAD/5 + (r-500)*HEAD/4000;
			eye2_.x = X - EYW/2 + HEAD/5 + (r-500)*HEAD/4000;
			eye1_.width = eye2_.width = EYW; 
			eye1_.height = eye2_.height = eyeh;
			
			final int irisw = IRW*id/1000;
			iris1_.x = eye1_.x + eye1_.width/2 + (ix-500)*EYW/1300 - irisw/2;
			iris2_.x = eye2_.x + eye2_.width/2 + (ix-500)*EYW/1300 - irisw/2;
			iris1_.y = iris2_.y = eyey - IRH/2 - (iy-500)*IRH/1000;
			iris1_.width = iris2_.width = irisw;
			iris1_.height = iris2_.height = IRH;
		}
		void draw(Graphics g) {
			g.setColor(Color.black);
			g.fillOval(BACKR.x,BACKR.y,BACKR.width,BACKR.height);
			g.fillOval(HEADR.x,HEADR.y,HEADR.width,HEADR.height);
			g.fillOval(BODYR.x,BODYR.y,BODYR.width,BODYR.height);
			g.fillPolygon(earx1_,eary1_,3);
			g.fillPolygon(earx2_,eary2_,3);
			g.setColor(EYECOLOR); 
			// not right but arcs seem diff
			g.fillOval(eye1_.x,eye1_.y,eye1_.width,eye1_.height);
			g.fillOval(eye2_.x,eye2_.y,eye2_.width,eye2_.height);
			g.setColor(Color.black);
			g.fillOval(iris1_.x,iris1_.y,iris1_.width,iris1_.height);
			g.fillOval(iris2_.x,iris2_.y,iris2_.width,iris2_.height);
		}
	}		
	
	public boolean mouseMove(Event e, int x, int y) {
		dx = x - mx;
		dy = y - my;
		mx = x;
		my = y;
		return true;
	}
}