
/**This short class animates the polyhedron exchange display**/

public class Puzzler implements Runnable {
    PuzzleCanvas X;
    boolean halt;

    public Puzzler() {
	halt=true;
    }

    public Puzzler(PuzzleCanvas XX) {
	this.X=XX;
	halt=false;
    }

    public void run() {
	PuzzlePiece[] CURRENT=new PuzzlePiece[X.COUNT];
	for(int i=0;i<X.COUNT;++i) CURRENT[i]=new PuzzlePiece(X.P[i]);
	PuzzlePiece[] BEST=copy(CURRENT);
	int record=100;
	int option=0;

	while(halt==false) {
	    int[][][] RECORD=assembleRandomly(CURRENT,X.COUNT);
	    int[] t=PuzzlePiece.multiPoints(CURRENT,CURRENT.length);
	    if(t.length<record) {
		record=t.length;
		BEST=copy(CURRENT);
		sendPuzzle(BEST);
		X.RECORD=RECORD;
		if(record==0) halt=true;
	    }
	}
	halt=true;
    }



    public static PuzzlePiece[] copy(PuzzlePiece[] Q) {
	PuzzlePiece[] R=new PuzzlePiece[Q.length];
	for(int i=0;i<Q.length;++i) R[i]=new PuzzlePiece(Q[i]);
	return R;
    }

    public void sendPuzzle(PuzzlePiece[] Q) {
	for(int i=0;i<X.COUNT;++i) X.P[i]=new PuzzlePiece(Q[i]);
	X.repaint();
    }


    /**assembly routines*/

    public static int[][][] assembleRandomly(PuzzlePiece[] P,int COUNT) {
	int[][][] RECORD=new int[COUNT][2][3];
	int[] g={0};
	for(int i=1;i<COUNT;++i) {
	    int[][] index=assembleStep(g,P,COUNT);
	    RECORD[i]=index;
	    g=ListHelp.append(g,index[1][0]);
	}
	return RECORD;
    }
    

    public static int[][] assembleStep(int[] g0,PuzzlePiece[] P,int COUNT) {
	int n=g0.length;
	if(n==COUNT) return null;
	boolean test=false;
	int count=0;
	while(test==false) {
	    int[][] index=assembleStepRaw(g0,P,COUNT);
	    int[] g=g0;
	    if(index!=null) g=ListHelp.append(g0,index[1][0]);
	    if(g.length>n) return index;
	    ++count;
	    if(count>100) test=true;
	}
	return null;
    }

    public static int[][] assembleStepRaw(int[] g,PuzzlePiece[] P,int COUNT) {
	int r=(int)(g.length*Math.random());
	r=g[r];
	int[] side=randomEdge(P[r]);
	int s2=side[0];
	int s3=side[1];
	
	
	for(int i=0;i<COUNT;++i) {
	    boolean match=P[i].hasSide(side);
	    if((match==true)&&(ListHelp.onList(i,g)==false)) {
		int[][] index={{r,s2,s3},{i,s2,s3}};
   	        PuzzlePiece.align(P[r],P[i],index);
		return index;
	    }
	}
	return null;
    }

    public static int[] randomEdge(PuzzlePiece P) {
   	int l=P.sharp.length;
	int r2=(int)(l*Math.random());
	int r3=(r2+1)%l;
	int s2=P.sharp[r2];
	int s3=P.sharp[r3];
	int[] side={s2,s3};
	return side;
    }

    public static void guidedAssembly(PuzzlePiece[] P,int COUNT,int[][][] RECORD) {
	for(int i=1;i<COUNT;++i) {
	    int[][] index=RECORD[i];
	    int r=index[0][0];
	    int s=index[1][0];
	    PuzzlePiece.align(P[r],P[s],index);
	}
    }

    

    
}




   
