/*
 *
 */

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.net.*;
import java.applet.*;
import java.lang.Object;
import java.lang.Object.*;

/**
 */
public
class knobeln extends Applet implements MouseListener {
    /**
     * Dubble Buffering
     */
     private Image dbImage;
     private Graphics dbg;

    /**
     * TEMP
     */
    int text;

    /**
     * Zustandsvariablen
     */
    boolean autofit = false;
    int status = 0;
    String myString = "541032540213523014504231521430512304510423";
    static final int SPIEL = 0;
    static final int EDIT = 1;
    int zustand = SPIEL;

    /**
     * Farben definieren (Grau für leer)
     */
    Color Farbe[] = {Color.blue, Color.yellow, Color.orange, Color.red, Color.green, Color.white,Color.gray};

    /**
     * Spielteile 
     */
    int Teil[][] = { {5,4,1,0,3,2},
                     {5,4,0,2,1,3},
                     {5,2,3,0,1,4},
                     {5,0,4,2,3,1},
                     {5,2,1,4,3,0},
                     {5,1,2,3,0,4},
                     {5,1,0,4,2,3},
                     {6,6,6,6,6,6} };

    /**
     * Teile im Spiel
     * nbenutzteTeile ist wie ein Rundenzähler
     */
    int benutzteTeile[] = {0,0,0,0,0,0,0};
    int nbenutzteTeile = 0;
    int istbenutzt[] = {0,0,0,0,0,0,0};

    /**
     * Wichtige Punkte des Spielfeldes
     */
    int tw; // Halbe Teilweite eines Spielfeldteils
    int th; // Höhe eines Spielfeldteils
    int midx=230; //Mittelfunkt des Spielfeldes x
    int midy=230; //Mittelpunkt des Spielfeldes y
    int midpx[]={0,0,0,0,0,0,0};  //mittelpunkte x-Koordinaten
    int midpy[]={0,0,0,0,0,0,0};  //und y-Koordinaten

    /**
     * Initialize the applet. Resize and load images.
     */
    public void init() {
	myinit();
	addMouseListener(this);
    }

    public void myinit() {
	nbenutzteTeile = 0; // Rundenzähler
	autofit = false;

	for (int i=0;i<7;i++) {
	  istbenutzt[i]=0;
	}

	// Größen des Applets auslesen
	//int x = (int) (getSize().width);
	//int y = (int) (getSize().height);

	tw = (int)(280/9); //halbe Teilweite
        th = (int)(320/6);  //Teilhoehe
	midpx[0]=midx; midpy[0]=midy;
	midpx[1]=midx; midpy[1]=midy+2*th+2;
	midpx[2]=midx+3*tw+2; midpy[2]=midy+th+1;
	midpx[3]=midx+3*tw+2; midpy[3]=midy-th-1;
	midpx[4]=midx; midpy[4]=midy-2*th-2;
	midpx[5]=midx-3*tw-2; midpy[5]=midy-th-1;
	midpx[6]=midx-3*tw-2; midpy[6]=midy+th+1;
	
    }

    public void destroy() {
        removeMouseListener(this);
    }

    /**
     * Spielkarten durch Webseite definieren bzw. ausgeben
     */
    public void setString(String aString) {
	if (aString.length() < 42) {
	  status = 4; // String ist zu kurz oder Fehlerhaft
	  setString(myString);
        } else {
	  status = 0;
	  int tmp;
	  for (int i=0; i<7; i++) {
	    for (int j=0; j<6; j++) {
	      tmp = Integer.valueOf( aString.substring(i*6+j,i*6+j+1) ).intValue();
	      if ((0 <= tmp) && (tmp < 6)) {
	        Teil[i][j]=tmp;
	      } else {
	        status = 4; // String zu kurz oder Fehlerhaft
	        break;
	      }
	    }
	  }
        }
	myinit();
	repaint();
    }
    public String getString() {
	String astring = "";
	for (int i=0;i<7;i++) { //Schleife über die Teile
	  for (int j=0; j<6;j++) { //Schleife über die Farben
	    astring += Teil[i][j];
	  }
	}
	return astring;
    }

    /**
     * Testen ob alle Teile richtig liegen
     */
    public boolean testfit() {
	if (nbenutzteTeile<2) {return true;}
	if (Teil[benutzteTeile[0]][3]!=Teil[benutzteTeile[1]][0]) {return false;}
	if (nbenutzteTeile<3) {return true;}
	if (Teil[benutzteTeile[0]][2]!=Teil[benutzteTeile[2]][5]) {return false;}
	if (Teil[benutzteTeile[1]][1]!=Teil[benutzteTeile[2]][4]) {return false;}
	if (nbenutzteTeile<4) {text=22;return true;}
	if (Teil[benutzteTeile[0]][1]!=Teil[benutzteTeile[3]][4]) {return false;}
	if (Teil[benutzteTeile[2]][0]!=Teil[benutzteTeile[3]][3]) {return false;}
	if (nbenutzteTeile<5) {return true;}
	if (Teil[benutzteTeile[0]][0]!=Teil[benutzteTeile[4]][3]) {return false;}
	if (Teil[benutzteTeile[3]][5]!=Teil[benutzteTeile[4]][2]) {return false;}
	if (nbenutzteTeile<6) {return true;}
	if (Teil[benutzteTeile[0]][5]!=Teil[benutzteTeile[5]][2]) {return false;}
	if (Teil[benutzteTeile[4]][4]!=Teil[benutzteTeile[5]][1]) {return false;}
	if (nbenutzteTeile<7) {return true;}
	if (Teil[benutzteTeile[0]][4]!=Teil[benutzteTeile[6]][1]) {return false;}
	if (Teil[benutzteTeile[5]][3]!=Teil[benutzteTeile[6]][0]) {return false;}
	if (Teil[benutzteTeile[1]][5]!=Teil[benutzteTeile[6]][2]) {return false;}
	return true;
    }

    /**
     * beliebiges Sechseck zeichnen
     */
    public void paintsechseck(int mpx, int mpy, int tw, int th, Color col, Graphics g) {
	Polygon zpoly = new Polygon();
        zpoly.addPoint(mpx-tw,mpy-th);
        zpoly.addPoint(mpx+tw,mpy-th);
	zpoly.addPoint(mpx+2*tw,mpy);
	zpoly.addPoint(mpx+tw,mpy+th);
	zpoly.addPoint(mpx-tw,mpy+th);
	zpoly.addPoint(mpx-2*tw,mpy);
        g.setColor(col);
	g.fillPolygon(zpoly);
    }

    /**
     * beliebiges sechseckiges Teil zeichnen
     */
    public void paintteil(int mpx, int mpy, int tw, int th, int teilnr, Graphics g) {
	Polygon zpoly = new Polygon();
        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx-tw,mpy-th);
        zpoly.addPoint(mpx+tw,mpy-th);
        g.setColor(Farbe[Teil[teilnr][0]]);
	g.fillPolygon(zpoly);
        zpoly.reset();

        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx+tw,mpy-th);
        zpoly.addPoint(mpx+2*tw,mpy);
        g.setColor(Farbe[Teil[teilnr][1]]);
	g.fillPolygon(zpoly);
        zpoly.reset();

        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx+2*tw,mpy);
        zpoly.addPoint(mpx+tw,mpy+th);
        g.setColor(Farbe[Teil[teilnr][2]]);
	g.fillPolygon(zpoly);
        zpoly.reset();

        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx+tw,mpy+th);
        zpoly.addPoint(mpx-tw,mpy+th);
        g.setColor(Farbe[Teil[teilnr][3]]);
	g.fillPolygon(zpoly);
        zpoly.reset();

        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx-tw,mpy+th);
        zpoly.addPoint(mpx-2*tw,mpy);
        g.setColor(Farbe[Teil[teilnr][4]]);
	g.fillPolygon(zpoly);
        zpoly.reset();

        zpoly.addPoint(mpx,mpy);
        zpoly.addPoint(mpx-tw,mpy-th);
        zpoly.addPoint(mpx-2*tw,mpy);
        g.setColor(Farbe[Teil[teilnr][5]]);
	g.fillPolygon(zpoly);
    }

    /**
     * Seckseck im Spielfeld zeichnen
     */
    public void paintteil(int pos, int teil, Graphics g) {
	paintteil(midpx[pos],midpy[pos],tw,th,teil,g);
    }

    /**
     * Drehe letztes Teil
     */
    public void dreheletztesteil() {
	if (nbenutzteTeile > 0) {
	  int aktTeil = benutzteTeile[nbenutzteTeile-1];
	  int temp = Teil[aktTeil][0];
	  for (int i=0;i<5;i++) {
	    Teil[aktTeil][i]=Teil[aktTeil][i+1];
	  }
	  Teil[aktTeil][5]=temp;
	}
    }

    /**
     * Paint it.
     */
    public void paint(Graphics g) {
	Dimension d = getSize();
	g.setColor(Color.black);
	g.fillRect(60,60,340,340);
        g.setColor(Color.orange);
        g.fill3DRect(75, 20, 60, 20, true);  //RESTART
        g.fill3DRect(155,20, 60, 20, true);  //Wiegen
	g.fill3DRect(235,20, 60, 20, !autofit);  //Autofit
	g.fill3DRect(315,20, 60, 20, (zustand!=EDIT)); //Edit
        g.setColor(Color.black);
        g.drawString("RESTART", 77, 38);
        g.drawString("Testen", 157, 38);
	if (autofit) {
	  g.drawString("Autofit:on", 237, 38);
	} else {
	  g.drawString("Autofit:off", 237, 38);
	}
	if (zustand==EDIT) {
	  g.drawString("Edit:on", 317, 38);
	} else {
	  g.drawString("Edit:off", 317, 38);
	}

	g.setColor(Color.red);
  	if (status == 1) {
          g.drawString("Teile liegen richtig", 60,80);
        } else if (status == 2) {
          g.drawString("Teile liegen falsch", 60,80);
	} else if (status == 3) {
	  g.drawString("Dieses Teil passt nicht", 60,80);
	} else if (status == 4) {
	  g.drawString("String fehlerhaft", 60,80);
        } else {
          //g.drawString(""+Teil[benutzteTeile[1]][1]+" "+Teil[benutzteTeile[2]][4]+" - "+text+"nr: "+nbenutzteTeile,60,80);
	}

	if (zustand==SPIEL) {
	  //nächstes zu belegendes Feld zeichnen
	  if (nbenutzteTeile < 7) {
            paintsechseck(midpx[nbenutzteTeile],midpy[nbenutzteTeile],tw+1,th+1,Color.red,g);
	  }
	  for (int i=0;i<nbenutzteTeile;i++) { //Feldzeichnen 
            paintteil(i,benutzteTeile[i],g);
	  }
	  for (int i=nbenutzteTeile;i<7;i++) { //leere Felder
	    paintteil(i,7,g);
	  }
	
	  for (int i=0;i<7;i++) { // Teile am Rand zeichnen
            int mtw = (int)(120/9); //teilWeite
            int mth = (int)(136/6); //teilHoehe
	    paintsechseck(30,30+55*i,mtw+1,mth+1,Color.gray,g);
  	    if (istbenutzt[i]==0) {
	      paintteil(30,30+55*i,mtw,mth,i,g);
	    } 
	  }
	} else if (zustand==EDIT) {
	  //Farbauswahl zeichnen
	  for (int i=0;i<6;i++) {
	    g.setColor(Farbe[i]);
	    g.fillRect(85+50*i,85,40,20);
	  }
	  //Aktuelles Teil zeichnen
	  paintteil(230,230,2*tw,2*th,benutzteTeile[0],g);
	  for (int i=0;i<7;i++) { // Teile am Rand zeichnen
            int mtw = (int)(120/9); //teilWeite
            int mth = (int)(136/6); //teilHoehe
	    paintsechseck(30,30+55*i,mtw+1,mth+1,Color.gray,g);
	    if (i != benutzteTeile[0]) {
	      paintteil(30,30+55*i,mtw,mth,i,g);
	    }
	  }
	  Polygon zpoly = new Polygon();
	  zpoly.addPoint(230,230);
	  zpoly.addPoint(230+2*tw+2,230-2*th-2);
	  zpoly.addPoint(230-2*tw-2,230-2*th-2);
	  g.setColor(Color.red);
	  g.drawPolygon(zpoly);

	}
    }

    /** Update - Method, implements double buffering */
    public void update (Graphics g)
    {
    // initialize buffer
    if (dbImage == null)
    {
    dbImage = createImage (this.getSize().width, this.getSize().height);
    dbg = dbImage.getGraphics ();
    
    }
    
    // clear screen in background
    dbg.setColor (getBackground ());
    dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
    
    // draw elements in background
    dbg.setColor (getForeground());
    paint (dbg);
    
    // draw image on the screen
    g.drawImage (dbImage, 0, 0, this);
    
    }
    
    /**
     * The user has clicked in the applet. Figure out where
     * and see if a legal move is possible. If it is a legal
     * move, respond with a legal move (if possible).
     */
    public void mouseReleased(MouseEvent e) {
	int x = e.getX();
	int y = e.getY();

	if (zustand==SPIEL) {
	  if ((x < 50) && (y < 400) && (e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
	    status = 0;
	    int clickedteil = (int) (y-5)/55;
	    if (istbenutzt[clickedteil]==1) {
	      //Teil liegt auf dem Spielfeld
	      istbenutzt[benutzteTeile[nbenutzteTeile-1]]=0;
	      nbenutzteTeile--;
	    } else {
	      //Teil wird auf das Spielfeld gelegt
	      if (autofit) {
	        istbenutzt[clickedteil]=1;
	        benutzteTeile[nbenutzteTeile]=clickedteil;
	        nbenutzteTeile++;
	        for (int i=0;i<6;i++) {
	          if (testfit()) {break;}
		  dreheletztesteil();
	        }
	        if (!testfit()) {
	          status = 3;
                  //Teil zurücklegen
	          istbenutzt[benutzteTeile[nbenutzteTeile-1]]=0;
	          nbenutzteTeile--;
	        } 
	      } else {
	        istbenutzt[clickedteil]=1;
	        benutzteTeile[nbenutzteTeile]=clickedteil;
	        nbenutzteTeile++;
	      }	
	    }
	    repaint();
	  } else if (((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK) && (!autofit || nbenutzteTeile==1)) {
	    status = 0;
	    dreheletztesteil();
	    text = 17;
	    repaint();
          } else if ((x > 235) && (x < 285) && (y > 20) && (y < 40)) {
	    // Autofit ein und aus schalten
	    if (autofit) {
	      autofit = false;
	    } else {
	      if (testfit()) {
	        autofit = true;
              } else {
	        status = 2; //aktuelle Teile passen schon nicht
	      }
	    }
	    repaint();
	  } else if ((x > 155) && (x < 215) && (y > 20) && (y < 40)) {
	    // Testen
            if (testfit()) {
              status = 1;
            } else {
	      status = 2;
	    }
            repaint();
	  } else if ((x > 315) && (x < 375) && (y > 20) && (y < 40)) {
	    // Edit modus einschalten
	    zustand=EDIT;
	    status=0;
	    nbenutzteTeile=1;
	    repaint();
	  } else if ((x > 75) && (x < 135) && (y > 20) && (y < 40)) {
	    // Restart
            status=0;
	    myinit();
            repaint();
          }
	} else if (zustand==EDIT) {
	  if ((x < 50) && (y < 400) && (e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
	    int clickedteil = (int) (y-5)/55;
	    benutzteTeile[0]=clickedteil;
	    repaint();
	  } else if ((x < 375) && (x > 85) && (y > 85) && (y < 105) && (e.getModifiers() & InputEvent.BUTTON1_MASK) == InputEvent.BUTTON1_MASK) {
	    //Farbe setzen
	    if (x < 125) { Teil[benutzteTeile[0]][0]=0; }
	    else if ( (x < 175) && (x > 135) ) { Teil[benutzteTeile[0]][0]=1; }
	    else if ( (x < 225) && (x > 185) ) { Teil[benutzteTeile[0]][0]=2; }
	    else if ( (x < 275) && (x > 235) ) { Teil[benutzteTeile[0]][0]=3; }
	    else if ( (x < 325) && (x > 285) ) { Teil[benutzteTeile[0]][0]=4; }
	    else if ( (x < 375) && (x > 335) ) { Teil[benutzteTeile[0]][0]=5; }
	    repaint();
	  } else if (((e.getModifiers() & InputEvent.BUTTON3_MASK) == InputEvent.BUTTON3_MASK)) {
	    dreheletztesteil();
	    repaint();
	  } else if ((x > 315) && (x < 375) && (y > 20) && (y < 40)) {
	    // Edit modus ausschalten
	    zustand=SPIEL;
	    status=0;
	    myinit();
	    repaint();
	  }
	}
    }

    public void mousePressed(MouseEvent e) {
    }

    public void mouseClicked(MouseEvent e) {
    }

    public void mouseEntered(MouseEvent e) {
    }

    public void mouseExited(MouseEvent e) {
    }

    public String getAppletInfo() {
	return "Ein neuer Versuch";
    }
}

