import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.math.*;


public class SearchCanvas extends ScaleCanvas implements MouseListener, MouseMotionListener {
    Manager M;
    int[][] ORDER=new int[8][0];
    int[] BLOCK=new int[8];

     public SearchCanvas() {
	 addMouseListener(this);
	 addMouseMotionListener(this);
	 ORDER=makeInitialOrder();
	 for(int i=0;i<8;++i) BLOCK[i]=0;
	 BLOCK[3]=1;
	 BLOCK[6]=1;
     }


   public void paint(Graphics g2) {
      Graphics2D g=(Graphics2D) g2;
      g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
      drawBG(g);
      drawLocalTypes(g);
      makeInitialOrder();
   }


    public int[][] makeInitialOrder() {
	int[][] n=new int[8][0];
	
	n[0]=consecutive(0,1);
	n[1]=consecutive(2,7);
	n[2]=consecutive(8,19);
	n[3]=consecutive(20,21);
	
	n[4]=consecutive(22,31);
	
	n[5]=consecutive(32,35);
	n[6]=consecutive(36,37);
	
        n[7]=consecutive(38,39);
	return n;
    }
    
    public void drawBG(Graphics2D g) {
	g.setColor(new Color(100,120,140));
      g.fillRect(0,0,getWidth(),getHeight()); 
    }


    /**drawing the pictures*/
    public void drawLocalTypes(Graphics2D g) {

	int[] lim1={0,4,5,7};
	int[] lim2={4,5,7,8};

	for(int q=0;q<4;++q) {

	    
	    for(int i=lim1[q];i<lim2[q];++i) {
	    int j=i-lim1[q];	
      	   int k=ORDER[i][0];
	   int[] m=TreeSearch.solution(k);
	   renderLocal(g,m,new Complex(50+80*j,50+80*q),35,BLOCK[i]);
	}
	}
    }

    public void toggleBlocked(Point X) {
	int index=-1;
	Complex w=new Complex(X.x,X.y);


	int[] lim1={0,4,5,7};
	int[] lim2={4,5,7,8};

	for(int q=0;q<4;++q) {
	    for(int i=lim1[q];i<lim2[q];++i) {
		int j=i-lim1[q];
	        Complex z=new Complex(50+80*j,50+80*q);
	        double d=Complex.dist(w,z);
	        if(d<30) index=i;
	    }
	}
	if(index==-1) return;
	BLOCK[index]=1-BLOCK[index];
    }




    
		    

    public static void renderLocal(Graphics2D g,int[] m,Complex z,double r,int b) {
	Color[] COL={Color.white,Color.black};
	Color[] COL2={new Color(255,80,0),new Color(140,0,0)};
	int L=m.length;
	
	for(int i=0;i<L;++i) {
	    Complex[] Z={new Complex(0,0),unity(L,i),unity(L,i+1)};
	    for(int j=0;j<3;++j) {
		Z[j]=Complex.plus(z,Z[j].scale(r));
	    }
	    PolygonWrapper P=new PolygonWrapper(3,Z);
	    Path2D.Double p=P.toPath();

	    Color C=COL[m[i]];
	    if(b==1) C=COL2[m[i]];
	    
	    g.setColor(C);
	    g.fill(p);
	    g.setColor(new Color(50,100,255));
	    g.draw(p);
	}

    }


    public static Complex unity(int n,int k) {
	double t=2*Math.PI*k/n;
	double c=Math.cos(t);
	double s=Math.sin(t);
	return new Complex(c,s);
    }



    /**order changing routines*/


    public static int[] permute(int[] a,int[] p) {
	int n=a.length;
	int[] b=new int[n];
	for(int i=0;i<n;++i) b[i]=a[p[i]];
	return b;
    }

    public static int[] permuteRandomly(int[] a) {
	int n=a.length;
	int[] p=ListHelp.randomPermutation(n);
	return permute(a,p);
    }

    public static int[][] permuteRandomly(int[][] a) {
	int[][] b=new int[a.length][0];
	for(int i=0;i<a.length;++i) b[i]=permuteRandomly(a[i]);
	return b;
    }
    
    
    public static int[] consecutive(int a,int b) {
	int[] list=new int[b-a+1];
	for(int i=a;i<=b;++i) list[i-a]=i;
	return list;
    }

    public int[] getOrder() {
	return ListHelp.flatten(ORDER);
    }

    public int[] getOrderRandom() {
	int[][] a=permuteRandomly(ORDER);
	for(int i=0;i<a.length;++i) {
	    if(BLOCK[i]==1) {
		for(int j=0;j<a[i].length;++j) a[i][j]=99;
	    }
	}
	int[] b=ListHelp.flatten(a);
	return b;
    }

    public int[] getBlocked() {
	int[] list=new int[40];
	int count=0;
	for(int i=0;i<8;++i) {
	    if(BLOCK[i]==1) {
		for(int j=0;j<ORDER[i].length;++j) {
		    list[count]=ORDER[i][j];
		    ++count;
		}
	    }
	}
	return ListHelp.trim(list,count);
    }




    
    
    public void mouseClicked(MouseEvent e) {
        MouseData J=MouseData.process(e);
	toggleBlocked(J.X);
	ORDER=permuteRandomly(ORDER);
	repaint();
    }
    
    
    public void mousePressed(MouseEvent e) {}
     public void mouseReleased(MouseEvent e) {}
     public void mouseEntered(MouseEvent e) {}
     public void mouseExited(MouseEvent e) {}   
     public void mouseMoved(MouseEvent e) {}    
    public void mouseDragged(MouseEvent e) {}
    

}

    
