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

public class Solver implements Runnable {
    Manager M;
    boolean halt;
    int[] PERMUTE1;
    int[] PERMUTE2;

    public Solver() {
	halt=true;
    }

    public Solver(Manager MM) {
	this.M=MM;
	halt=false;
    }

    public void run() {
	clearMessage();

	if(M.S.E.PERFECT==false) {
	    sendFail(0);
	    halt=true;
	    return;
	}

	M.S.E.SOLVED=false;
	int[][] F=M.S.E.flower;
	int N=M.S.E.triangles.length;
	int[][] LIST=initial();
	int CURRENT=39;
	int[] blocked=M.C.SEA.getBlocked();


	while(halt==false) {
	    
	    if(CURRENT==-1) {
		sendFail(2);
		halt=true;
		return;
	    }
	    
	    int[] S=LIST[CURRENT];
	    sendToPic(S);
	    int t=F.length-S.length;
            sendMessage(CURRENT,t);

	    int quality=TreeSearch.isGood(F,N,S,blocked);
	    
	    if(quality==2) {
     	       int[] T=TreeSearch.assignVariables(F,N,S);
	       sendData(T);
	       M.S.E.SOLVED=true;
	       halt=true;
	    }

	    if(quality==1) {
		   LIST=augment(LIST,CURRENT);
		   CURRENT=CURRENT+39;
	    }

	    if(quality==0) --CURRENT;
	    M.repaint();
	}
    }

    public int[][] initial() {
 	int[] x=M.C.SEA.getOrderRandom();
	int[][] a=new int[40][1];
	for(int i=0;i<40;++i) a[i][0]=x[39-i];
	return a;
    }
    
    public int[][] augment(int[][] LIST,int CURRENT) {
	int[] x=M.C.SEA.getOrderRandom();
	int n=LIST.length;
	int[][] LIST2=new int[n+39][0];
	for(int i=0;i<CURRENT;++i) LIST2[i]=ListHelp.copy(LIST[i]);
	for(int i=0;i<40;++i) LIST2[CURRENT+i]=ListHelp.append(LIST[CURRENT],x[39-i]);
	return LIST2;
    }

    /**This exports variou data to other components*/
    public void sendFail(int t) {
	clearMessage();
	if(t==0) M.C.STR[0]="triangulation not valid";
	if(t==1) M.C.STR[0]="solution uses blocked pics";
	if(t==2) M.C.STR[0]="solution not found";
	M.repaint();
    }
    
    
    public void clearMessage() {
	for(int i=0;i<5;++i) M.C.STR[i]="";
    }
    
    public void sendToPic(int[] S) {
	int[][] F=M.S.E.flower;
	int n=S.length;
	if(ListHelp.onList(99,S)==true) return;
	for(int i=n-1;i>=0;--i) {
	    if(S[i]!=-1) {
	       int[] s=TreeSearch.solution(S[i]);
	       try{for(int j=0;j<s.length;++j) M.S.E.solution[F[i][j]]=s[j];}
	       catch(Exception e) {}
	    }
	}
	M.repaint();
    }


    public void sendData(int[] T) {
	int[] count={0,0};
	int n=M.S.E.flower.length;
	int[] S=new int[n];
       	for(int i=0;i<T.length;++i) {
	    if(T[i]==-1) return;
	    ++count[T[i]];
	}
	for(int i=0;i<n;++i) {
	    int[] a=M.S.E.flower[i];
	    int[] b=new int[a.length];
            for(int j=0;j<a.length;++j) {
		b[j]=T[a[j]];
	    }
            S[i]=TreeSearch.recognizeLocal(b);
	}
	M.S.E.local=new int[n];
	for(int i=0;i<n;++i) M.S.E.local[i]=S[i];

	Integer C0=Integer.valueOf(count[0]);
	Integer C1=Integer.valueOf(count[1]);
	M.C.STR[0]="solved. colors: "+C0.toString()+" "+C1.toString();

 	int[] stats=ShapeRecognizer.statsMonochrome(M.S.E);
	Integer[] ST=new Integer[3];
	for(int i=0;i<3;++i) ST[i]=Integer.valueOf(stats[i]);
	M.C.STR[1]="monochrome edges "+ST[0].toString();
	M.C.STR[2]="monochrome pieces "+ST[1].toString();
	M.C.STR[3]="freedom "+ST[2].toString();

	
	M.C.repaint();
    }

    public void sendMessage(int CURRENT,int t) {
	Integer c=Integer.valueOf(CURRENT);
	Integer T=Integer.valueOf(t);
	M.C.STR[0]="working "+c.toString()+" "+T.toString();
	M.C.repaint();
    }
}




