import java.awt.*;
import primitives.frames.*;
import primitives.machines.*;
import primitives.geomtry.*;
import primitives.spaces.*;
public class FiveArmsProof extends Frames implements FramesListener,MachineListener{
	int currentFrame=0;
	int sign = 1;
	int arm = 0;
	NarmsMachineProof machine;
	NarmsMachine machine1;
	CircleSpace space;
	Coordinate center;
	Polygon polygon;
	Dimension d;
	Redrawer redrawer;
	public void init(){
		super.init();
		currentFrame=getParam("startFrame",0);
	}
	public void start(){
	
		d = frames[1].drawArea.getSize();
		machine = new NarmsMachineProof(frames[0].drawArea.getSize(),4+1,1.3);
		machine.testRun();
		machine.setChangeRate(0.01);
		machine1 = new NarmsMachine(frames[0].drawArea.getSize(),getParam("arms",4),1.3);
		center = new Coordinate(machine1.center.x,machine1.center.y);
		redrawer = new Redrawer(frames[0].drawArea.getSize(),machine1);
		int	result;
		do{
			result = machine1.moveCenterEx(-1,0);
		}while(result==-1);
		machine1.moveCenterEx(0.1,0);
		startThread();
		changeFrame(currentFrame);
	}
	public void stop(){
		super.stop();
		machine = null;
		machine1 = null;
		center = null;
		d = null;
		polygon = null;
		redrawer = null;
		space = null;
	}
	public void changeFrame(int index){
			run = false;
		currentFrame = index;
		try{
			if(t!=null)t.sleep(10);
		}catch(InterruptedException e){}
	//	t = null;
		switch(index){
		case 0:
			space = new CircleSpace(frames[0].drawArea.getSize(),0,Math.PI*2);
			space.setMachine(machine);
			frames[0].drawArea.setCurrentObject(machine);
			frames[1].drawArea.setCurrentObject(space);break;
		case 1:	
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,1);
			frames[0].drawArea.setCurrentObject(redrawer);
			frames[1].drawArea.setCurrentObject(space);
			if (machine1.bendStates[1]==-1)machine1.switchBend(1);
			if (machine1.bendStates[0]==-1)machine1.switchBend(0);
			break;
		case 2:
			if(machine1.bendStates[1]==-1)machine1.switchBend(1);
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,1);
			frames[1].drawArea.setCurrentObject(this);	
			polygon = ((MultiPolygons)space).polygons[1];
			polygon.translate(d.width-polygon.xpoints[0],0); break;
		case -2:
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,2);
			frames[0].drawArea.setCurrentObject(redrawer);
			frames[1].drawArea.setCurrentObject(space);
			break;
		case 3:
			if((machine1.bendStates[0]==1)&&(machine1.bendStates[1]==-1))machine1.switchBend(0);
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,1);
			frames[1].drawArea.setCurrentObject(this);	
			polygon = ((MultiPolygons)space).polygons[2];
			polygon.translate(0,d.height-polygon.ypoints[0]); break;
		case -3:
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,3);
			frames[0].drawArea.setCurrentObject(redrawer);
			frames[1].drawArea.setCurrentObject(space);
			break;
		case 4:
			space = new MultiPolygons(frames[1].drawArea.getSize(),4,1,machine1,1);
			frames[1].drawArea.setCurrentObject(this);	
			polygon = ((MultiPolygons)space).polygons[3];
			polygon.translate(polygon.xpoints[0]-d.width,d.width-polygon.xpoints[0]); break;
		case -4:
			space = new MultiPolygons(frames[1].drawArea.getSize(),getParam("arms",4),1,machine1,4);
			frames[0].drawArea.setCurrentObject(redrawer);
			frames[1].drawArea.setCurrentObject(space);
			break;
		case 5:	space = new MultiPolygons(frames[1].drawArea.getSize(),4,0,null,4);
			space.setMachine(machine);
			frames[0].drawArea.setCurrentObject(machine);
			frames[1].drawArea.setCurrentObject(space);break;
		case 6:space = new MultiPolygonDemo(frames[1].drawArea.getSize(),4,null,0);
			frames[0].drawArea.setCurrentObject(machine);
			frames[1].drawArea.setCurrentObject(space);
			space.setMachine(machine);break;
		case 7:space = new MultiPolygonDemo(frames[1].drawArea.getSize(),4,null,1);
			frames[0].drawArea.setCurrentObject(machine);
			frames[1].drawArea.setCurrentObject(space);
			space.setMachine(machine);break;
		}
		frames[1].drawArea.repaint(1);
	//	startThread();
		run = true;
	}
	public void changeFrames(){
	switch(currentFrame){
		case 0:runFrame0();break;
		case 1:runCommonFrame();break;
		case -2:runCommonFrame();break;
		case -3:runCommonFrame();break;
		case -4:runCommonFrame();break;
		case 5:runFrame0();break;
		case 7:runFrame0();break;
		default:frames[1].drawArea.repaint(); 
		}
	}

	void runFrame0(){
		int result=machine.rotateCenterEx(0,sign*0.01);
		if (result>-0){
			sign=sign*(-1);
			machine.rotateCenterEx(0,sign*0.01);
			machine.strechArm(result);
			machine.switchBend(result);
		}
		space.changeState(-Math.PI/2);
		frames[0].drawArea.repaint();
		frames[1].drawArea.repaint();

	}
	private void runCommonFrame(){
		int[] result = machine1.rotateCenterA(arm,-0.01);
		space.changeState();
		frames[0].drawArea.repaint();
		frames[1].drawArea.repaint();
		if(result[(arm-1+machine1.arms)%machine1.arms]==1){
			arm = (arm-1+machine1.arms)%machine1.arms;
			switch(currentFrame){
			case -2:if(arm==0)machine1.switchBend(arm);break;
			case -3:if((arm==1)&&(machine1.bendStates[0]==-1))machine1.switchBend(arm);
				else if((arm==0)&&(machine1.bendStates[0]==1))machine1.switchBend(0);break;
			case -4:if((arm==1)||((arm==0)&&(machine1.bendStates[1]==-1)))machine1.switchBend(arm);
			}
		}
	}

	public void redraw(Graphics g){
		Polygon[] p = ((MultiPolygons)space).polygons;
		switch(currentFrame){
		case 2:
		g.drawPolygon(p[0]);
		if(p[0].xpoints[0]<polygon.xpoints[0]) polygon.translate(-1,0);break;
		case 3:
		g.drawPolygon(p[0]);
		g.drawPolygon(p[1]);
		if(p[0].ypoints[0]<polygon.ypoints[0]) polygon.translate(0,-1);break;
		case 4:
			g.drawPolygon(p[0]);
			g.drawPolygon(p[1]);
			g.drawPolygon(p[2]);
		if(p[0].ypoints[0]<polygon.ypoints[0]) polygon.translate(1,-1);
		}
		g.drawPolygon(polygon);
		if((p[0].ypoints[0]==polygon.ypoints[0])&&(p[0].xpoints[0]==polygon.xpoints[0]))
		   changeFrame(-1*currentFrame);
	}
}
class Redrawer implements MachineListener{
	Dimension d;
	NarmsMachine m;
	Redrawer(Dimension d,NarmsMachine m){
		this.d = d;
		this.m = m;
	}
	final static String B="B";
	final static String C="C";
	final static String D="D";
	final static String U="U";
	static final String	F = "F";
	public void redraw(Graphics g){
		g.drawString(U,m.anchors[0].x-1,m.anchors[0].y-5);
		g.drawString(D,m.anchors[1].x+10,m.anchors[1].y);
		g.drawString(B,m.anchors[2].x,m.anchors[2].y-5);
		g.drawString(C,m.anchors[3].x-15,m.anchors[3].y+5);
		if (m.arms==5)g.drawString(F,m.anchors[4].x+10,m.anchors[4].y+5);
		m.redraw(g);
 	}
	public void finalize() throws Throwable{
		m = null;
		d = null;
	}
}


