import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.applet.*;
import java.util.Random;

/* Frogs.java 

   implements the lucas problem



*/


public class Froggy extends Applet {


    int bottomstrip = 100;


    int numFrogs = 3;
    int numToads = 3;

    int[][] tally = {{0,0},{0,0}};

    static int NOTHING = -1;
    static int FROG = 0;
    static int TOAD = 1;
    
    static int SLIDE = 0;
    static int HOP = 1;


    private Label numFrogsLabel;
    private Label numToadsLabel;
    private TextField numFrogsField;
    private TextField numToadsField;
    private Button againButton;

    private TextField fsField[][];

    private Label hopLabel;
    private Label slideLabel;
    private Label frogLabel;
    private Label toadLabel;

    
    public FrogCanvas frogCanvas;



    public void init() {

	GridBagLayout gridbag = new GridBagLayout();
	setLayout(gridbag);
        GridBagConstraints c = new GridBagConstraints();

	Label spaceLabel = new Label("");
	c.gridx = 0;
	c.gridy = 0;
	c.gridwidth = 1;
	c.gridheight = 1;
	c.anchor = GridBagConstraints.CENTER;

	c.fill = GridBagConstraints.HORIZONTAL;
	c.weighty = 0.5;

	gridbag.setConstraints(spaceLabel, c);
	add(spaceLabel);

	
	frogCanvas = new FrogCanvas(this, 500, 350);

	c.fill = GridBagConstraints.HORIZONTAL;
	c.gridwidth = 4;
	c.gridheight = 4;
	c.gridy=1;
	c.anchor = GridBagConstraints.CENTER;
	c.weighty = 1.0;

	gridbag.setConstraints(frogCanvas, c);
	add(frogCanvas);

	Label spacerLabel = new Label("");
	c.gridx = 5;
	c.gridy = 1;
	c.gridwidth = 1;
	c.gridheight = 1;
	c.anchor = GridBagConstraints.CENTER;

	c.fill = GridBagConstraints.HORIZONTAL;
	c.weighty = 0.5;

	gridbag.setConstraints(spacerLabel, c);
	add(spacerLabel);

	c.gridx = 5;
        c.gridy = 2;
	c.gridwidth = 1;
	c.gridheight = 1;
	c.anchor = GridBagConstraints.CENTER;

	c.fill = GridBagConstraints.HORIZONTAL;
	c.weighty = 0.5;
	numFrogsLabel = new Label("Number of Frogs: ");
	gridbag.setConstraints(numFrogsLabel, c);
	add(numFrogsLabel);

	c.gridx = 6;
	numFrogsField = new TextField(""+numFrogs);
	gridbag.setConstraints(numFrogsField, c);
	add(numFrogsField);

	c.gridx = 5;
	c.gridy = 3;
	c.anchor = GridBagConstraints.CENTER;
	numToadsLabel = new Label("Number of Toads: ");
	gridbag.setConstraints(numToadsLabel, c);
	add(numToadsLabel);


	c.gridx = 6;
	c.anchor = GridBagConstraints.CENTER;
	numToadsField = new TextField(""+numToads);
	gridbag.setConstraints(numToadsField, c);
	add(numToadsField);

	c.gridx = 5;
	c.gridy = 4;
	againButton = new Button("Play Again!");
	gridbag.setConstraints(againButton, c);
	add(againButton);
	

	c.weighty = 0.0;
	c.gridx = 0;
	c.gridy = 7;
	c.anchor = GridBagConstraints.EAST;
	slideLabel = new Label("Slides");
	gridbag.setConstraints(slideLabel, c);
	add(slideLabel);

	c.gridx = 0;
	c.gridy = 8;
	hopLabel = new Label("Hops");
	gridbag.setConstraints(hopLabel, c);
	add(hopLabel);

	c.gridx = 1;
	c.gridy = 6;
	c.anchor = GridBagConstraints.NORTH;
	frogLabel = new Label("Frogs");
	gridbag.setConstraints(frogLabel, c);
	add(frogLabel);

	c.gridx = 2;
	c.gridy = 6;
	c.anchor = GridBagConstraints.NORTH;
	toadLabel = new Label("Toads");
	gridbag.setConstraints(toadLabel, c);
	add(toadLabel);



	fsField = new TextField[2][2];
	for (int i = 0 ;i<2;i++){
	    for(int j = 0;j<2;j++) {
		fsField[i][j] = new TextField(""+tally[i][j]);
		fsField[i][j].setEditable(false);
	    }
	}


	c.gridx = 1;
	c.gridy = 7;
	c.anchor = GridBagConstraints.SOUTH;
	gridbag.setConstraints(fsField[0][0], c);
	add(fsField[0][0]);

	c.gridx = 1;
	c.gridy = 8;
	gridbag.setConstraints(fsField[1][0], c);
	add(fsField[1][0]);

	c.gridx = 2;
	c.gridy = 7;
	gridbag.setConstraints(fsField[0][1], c);
	add(fsField[0][1]);

	c.gridx = 2;
	c.gridy = 8;
	gridbag.setConstraints(fsField[1][1], c);
	add(fsField[1][1]);
	repaint();
    }



    // clicking on the buttons:


    public boolean action(Event e, Object arg) {
	   Object target = e.target;
	   
	   if (e.target == againButton) { 
	       int protoNumFrogs;
	       int protoNumToads;
	       try{
		   protoNumFrogs = Integer.parseInt(numFrogsField.getText());
		   protoNumToads = Integer.parseInt(numToadsField.getText());
		   if((protoNumFrogs>0) && (protoNumToads>0) && 
		      ((protoNumFrogs + protoNumToads)<=20)) {
		       numFrogs = protoNumFrogs;
		       numToads = protoNumToads;
		   }
		   frogCanvas.setValues();
		   for (int i=0;i<2;i++) {
		       for(int j=0;j<2;j++) {
			   fsField[i][j].setText(""+tally[i][j]);
		       }}
		   frogCanvas.repaint();

	       }
	       catch(Exception ef){}
	       return true;
	   }

        return false;
    }


    class Beastie {
	public int animal;
	public int whereatx;
	public int whereaty;
	Beastie(int frogtoad, int location) {
	    animal = frogtoad;
	    whereatx = location;
	    whereaty = 0;
	    }
    }
    class FrogCanvas extends Canvas implements MouseListener {

	int frogRow[];
	int height;
	int width;
	Container mama;
	boolean trueSizeKnown = false;
	Dimension minSize;
	Graphics offGraphics;
	Dimension offDimension;
	Image offImage;
	Graphics g;
	int extra = 5;
	int pieceMargin = 3;
	int margins = 20;
	int numJumpsDef = 5;
	boolean done = false;


	int starty;
	int spaceSize;
	Beastie floatFrog;

	int frogSize;

	FrogCanvas(Container parent, int w, int h) {
	    width = w;
	    height = h;

	    setValues();
	    
	    addMouseListener(this);
	    
	    mama = parent;

	    minSize = new Dimension(width, height);
	    setSize(width, height);
	    mama.validate();
	}

	public void paint(Graphics g) {
	    
	    update(g);

	}


	public synchronized void update (Graphics g) {
	    
	    Dimension d = getSize() ;
	    if ( (offGraphics == null)
		 || (d.width != offDimension.width)
		 || (d.height != offDimension.height) ) {
		offDimension = d;
		offImage = createImage(d.width, d.height);
		offGraphics = offImage.getGraphics();
	    }
	    
	    //Erase the previous image.
	    //	    offGraphics.setColor(getBackground());
	    offGraphics.setColor(Color.white);
	    offGraphics.fillRect(0, 0, d.width, d.height);
	    offGraphics.setColor(Color.black);

	    // paint the new image onto the off-screen canvas
	    drawBoard(offGraphics);

	    drawReptiles(offGraphics);

	    if(floatFrog !=null) {
		if(floatFrog.animal == FROG) {
		    drawFrog(offGraphics, floatFrog.whereatx, floatFrog.whereaty);
		}
		else{
		    drawToad(offGraphics,floatFrog.whereatx,floatFrog.whereaty);
		}
	    }
	    if(done) {
		Font font = g.getFont();
		int size = font.getSize();
		String name = font.getName();
		int style = font.getStyle();
		offGraphics.setFont(font = new Font(name,
					  style,
					  50));
		offGraphics.drawString("You did it!", 30, 60);
	    }


	    // paint to the screen
	    g.drawImage(offImage, 0, 0, null);

	}
	public void drawReptiles(Graphics g) {

	    int y = starty;
	    for(int i = 0;i<numFrogs+numToads+1;i++) {
		if(frogRow[i]==FROG) {
		    drawFrog(g, logical2real(i),y);
		}
		else if(frogRow[i]==TOAD) {
		    drawToad(g, logical2real(i),y);
		}
	    }
	}

	public void drawFrog(Graphics g, int x, int y) {
	    g.setColor(Color.red);
	    g.fillRect(x,y,frogSize-5,frogSize-5);
	    g.setColor(Color.black);
		
	}

	public void drawToad(Graphics g, int x, int y) {
	    g.setColor(Color.blue);
	    g.fillOval(x,y, frogSize-5, frogSize-5);
	    g.setColor(Color.black);
		
	}

	public void drawBoard(Graphics g) {

	    int padSize = 10;
	    g.setColor(Color.green) ;


		int x = margins;
		int y = starty+frogSize;
		for(int i = 0;i<numFrogs+numToads+1;i++) {

		    Polygon filledPolygon = new Polygon();
		    filledPolygon.addPoint(x, y);
		    filledPolygon.addPoint(x+padSize, y-padSize);
                    filledPolygon.addPoint(x+frogSize+padSize, y-padSize);
		    filledPolygon.addPoint(x+frogSize, y);

                    g.fillPolygon(filledPolygon); 

		    x+=spaceSize;
		}
		


	}


	public Dimension preferredSize() {
	    return minimumSize();
	}

	public synchronized Dimension minimumSize() {
	    return minSize;
	}
   

	public int logical2real(int x) {
	    return spaceSize*x+margins+pieceMargin+(int)(extra/2)+3;
	}

	
	private void setValues () {
	    int i;
	    
	    done = false;
	    for(i=0;i<2;i++) {
		for(int j=0;j<2;j++) {
		    tally[i][j]=0;
		}}
	    frogRow = new int[numFrogs + numToads+1];
	    for(i=0;i<numFrogs;i++) {
		frogRow[i]=FROG;
	    }
	    frogRow[i]=NOTHING;
	    i++;
	    for(int j = 0;j<numToads;j++) {
		frogRow[i+j] = TOAD;
	    }
	    
	    frogSize = (width-2*margins)/(numFrogs+numToads+1) - 2*(pieceMargin)-extra;
	    spaceSize = (int)((width -2*margins)/(numFrogs+numToads+1));
	    starty = height -150-frogSize/5;

	    floatFrog=null;
	}
	
	int isInPiece(int x, int y) {

	    int nstarty = starty+frogSize;
	    if((y < nstarty-spaceSize) || (y>nstarty)) {
		return -1;
	    }
	    if((x<margins) || (width-margins<x)) {
		return -1;
	    }
	    return (int)((x-margins)/spaceSize);
	}

	void increaseCount(int frog, int hopslide) {
	    tally[frog][hopslide]++;
	    fsField[hopslide][frog].setText(""+tally[frog][hopslide]);
	}

	boolean isDone() {
	    boolean doneyet= true;
	    int i;
	    for(i=0;i<numToads;i++) {
		if(frogRow[i]!=TOAD) {
		    if(doneyet == true) {
			doneyet = false;
		    }
		}
	    }
	    i++;
	    for(;i<numToads+1+numFrogs;i++) {
		if(frogRow[i]!=FROG) {
		    if(doneyet == true) {
			doneyet = false;
		    }
		}
	    }
	    return doneyet;
	}

	void movePiece(int frog) {
	    // only moving the piece if we can
	    
	    // if it is a frog, we must look to see if either there is
	    // a space 1 to the right or 2 to the right.
	    if (frogRow[frog]==FROG) {
		if((frog+1<numFrogs+numToads+1) && (frogRow[frog+1]==NOTHING)) {
		    AnimationThread frogThread = new AnimationThread("frogthread", frog, SLIDE);
		    increaseCount(FROG, SLIDE);
		    frogRow[frog]=NOTHING;
		    frogThread.run();
		    frogRow[frog+1]=FROG;

		}
		else if((frog+2<numFrogs+numToads+1) && (frogRow[frog+2]==NOTHING)) {
		    AnimationThread frogThread = new AnimationThread("frogthread", frog, HOP);
		    frogRow[frog]=NOTHING;
		    increaseCount(FROG, HOP);
		    frogThread.run();
		    frogRow[frog+2]=FROG;

		}
	    }
	    else if(frogRow[frog]==TOAD) {
		if((frog-1>=0) && (frogRow[frog-1]==NOTHING)) {
		    AnimationThread toadThread = new AnimationThread("toadthread", frog, SLIDE);
		    increaseCount(TOAD, SLIDE);
		    frogRow[frog]=NOTHING;
		    toadThread.run();
		    frogRow[frog-1]=TOAD;

		}
		else if((frog-2>=0) && (frogRow[frog-2]==NOTHING)) {
		    AnimationThread toadThread = new AnimationThread("toadthread", frog, HOP);
		    frogRow[frog]=NOTHING;
		    increaseCount(TOAD, HOP);
		    toadThread.run();
		    frogRow[frog-2]=TOAD;

		}
	    }
	    if(g == null) {
		g = getGraphics();
	    }
	    update(g);
	}


	public void mouseClicked(MouseEvent e) {
	    int whichPiece = isInPiece(e.getX(), e.getY());
	    if(whichPiece!=-1) {
		movePiece(whichPiece);
	    }
	    if(isDone()) {
		done = true; 
		if(g==null) {
		    g = getGraphics();
		}
		update(g);
	    }
	}

	public void mousePressed(MouseEvent e) {}

	public void mouseReleased(MouseEvent e) {}

	public void mouseExited(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public class AnimationThread extends Thread {
	    int animal;
	    int movement;
	    int type;
                  public AnimationThread(String str, int frogtoad, int hopslide) {
                      super(str);
		      animal = frogtoad;
		      movement = hopslide;
		      type = frogRow[frogtoad];
                  }
                  public void run() {
		      if(g == null) {
			  g = getGraphics();
		      }

		      int startx = logical2real(animal);
		      floatFrog = new Beastie(type, startx);
		      int endx = startx;
		      if(type == FROG) {
			  endx = logical2real(animal+movement+1);
		      }
		      else if(type == TOAD) {
			  endx = logical2real(animal-movement-1);
		      }
		      int numJumps =(numJumpsDef+movement*numJumpsDef)*(numFrogs+numToads+6)/(numFrogs+numToads);
		      int increment = (endx-startx)/numJumps;
                      for (int i = 0; i < numJumps; i++) {
			  floatFrog.whereatx= startx+i*increment;
			  int x = floatFrog.whereatx;
			  floatFrog.whereaty = starty-(int)(0.05*((startx-x)*(x-endx)));
			  //                          try {
			  //                              sleep((long)(20));
			  //                          } catch (InterruptedException e) {}
			  update(g);
                      }
		      floatFrog = null;
                  }
              }

    }

}

