import Playfield;
import java.awt.*;
import java.awt.image.*;
import java.applet.*;
import java.util.*;
//*****************************************************************

/* This class basically puts everything together and runs
   the program. It controls the mouse inputs, and the drawing
   of the playground, and the updating of the sprites. 
   */

public class SpriteRun extends Applet implements Runnable
{
  long time; // This variable is needed to check for garbage collection
  Playfield playfield;
  AnimatedSprite sprites[];
  Image output;
  Thread animate;
  int numberSprites;  // stores the number of sprites
  int spriteMove;  // which sprite is to be moved
  int mode;  // check transparency or move state
  private Button moveButton;   // move button
  private Button checkButton; // transparency button
  private Choice spriteChoice; // sprite choice menu
  //*****************************************************************
  
  public void init()
  {
    time = 0;
    /*** initialize buttons */
    moveButton = new Button("Move");
    checkButton = new Button("Hit a sprite!");
    // coloring the buttons
    moveButton.setForeground(Color.black);
    moveButton.setBackground(Color.lightGray);
    checkButton.setForeground(Color.black);
    checkButton.setBackground(Color.lightGray);
    // add to the applet
    this.add(moveButton);
    this.add(checkButton);
    spriteMove = 1;
    mode = 1;
    // ** initialize choices
    spriteChoice = new Choice();
    // getting the background image
    playfield = new Playfield((getImage(getDocumentBase(), 
					getParameter("back_image"))), 2);
    
    int numS = Integer.parseInt(getParameter("numberSprites"));
    numberSprites = numS;    
    String filename;
    int i;  
    int s;
    int numF;
    int x1;
    int y1;
    sprites = new AnimatedSprite[numS];
    
    /* The way the HTML file is set up, is that there is a field 
       for each sprite in a specific order. The first component is 
       the actual file name, the second is the number of frames,
       the third and fourth represent the initial location of the sprite.
       The 5th indicates the number of states.
       The 6th, 7th, 8th, 9th represent the frame number, number of ticks,
       dx, and dy resectively. This is done for all the states.
       Please note: a non-animated sprite is one with 1 frame, 1 state, and
       dx =0, dy=0
       */
    
    for (s=1; s<=numS; s++)
      {
	// adding a choice to the Choice pulldown menu
	spriteChoice.addItem("Sprite "+String.valueOf(s));
	String stuff = getParameter("states"+String.valueOf(s)+"_info");
	StringTokenizer tk  = new StringTokenizer(stuff, ",");
	filename = tk.nextToken();
	numF = Integer.parseInt(tk.nextToken());
	x1 = Integer.parseInt(tk.nextToken());
	y1 = Integer.parseInt(tk.nextToken());
        sprites[s-1] = new AnimatedSprite(getImage(getDocumentBase(), 
						   filename), numF, x1, y1);
	int num = Integer.parseInt(tk.nextToken());
	// set Track according to the number of States
	sprites[s-1].setTrack(num);
	for (i=0; i<num; i++)
	  {
	    // grab all the state positions
	    int pos1 = Integer.parseInt(tk.nextToken());
	    int pos2 = Integer.parseInt(tk.nextToken());
	    int pos3 = Integer.parseInt(tk.nextToken());
	    int pos4 = Integer.parseInt(tk.nextToken());
	    sprites[s-1].addState(i,pos1,pos2,pos3,pos4);
	  }
      }
    // add each sprite to the playfield
    for (s=0; s<numS; s++)
      {
	playfield.addSprite(s,sprites[s]);
      }
    renderPlayfield();
    //add the choice menu to the applet
    this.add(spriteChoice);
  }
  //****************************************************************
  public boolean action(Event e, Object arg)
  {
    /* If the "Move" button is pressed, the mode is assigned the value of 1.
       If the "Hit Sprite?" button is pressed, the mode is assigned the 
       value of 2. The value of spriteMove depends on the sprite chosen
       by the user in the spriteChoice pulldown menu. */
    int s;
    if (e.target == moveButton)
      {
	mode=1;
	getAppletContext().showStatus("                         ");
      }
    if (e.target == checkButton)
      mode=2;
    if (e.target == spriteChoice)
      spriteMove = Integer.parseInt(arg.toString().substring(7));
    return true;
  }
  //*****************************************************************
  public void start()
  {
    animate = new Thread(this);
    animate.start();
  }
  //*****************************************************************
  public void stop()
  {
    animate=null;
  }
  //*****************************************************************
  public void run()
  {
    while(true)
      {
	try
	  {
	    animate.sleep(100);
	  } catch(InterruptedException e) {
          }
	  renderPlayfield();
      }
  }
  //*****************************************************************
  public void renderPlayfield()
  {
    long timeNow = System.currentTimeMillis();
    if ((timeNow - time) > 10000)
      {
	System.gc();
	time = System.currentTimeMillis();
      }
    // Draw the playfield onto its raster 
    playfield.Draw();
    output = playfield.toImage();
    int s;
    // Change the states of the sprite
    for (s=0; s<numberSprites; s++)
      {
	sprites[s].nextState();
      }
    repaint();
  }
  //*****************************************************************
  public void paint(Graphics g)
  {
    g.drawImage(output,0,0,this);
  }
  //*****************************************************************
  public void update(Graphics g)
  {
    paint(g);
  }
  //*****************************************************************
  public boolean mouseDown(Event e, int x, int y)
  {
    /* if the mouse is clicked and depending on the "mode" 
       certain things happen.
       If the mode = 1, the left corner of the chosen sprite
       is moved to (x,y)
       If the mode = 2, the user is notified of whether or not
       he "hit" the sprite. That is, hit the sprite at a non-transparent
       pixel. */
    
    if (mode == 1)
      {
	sprites[spriteMove-1].setX(x);
	sprites[spriteMove-1].setY(y);
      }
    if (mode == 2)
      {
	int s;
	int tempX;
	int tempY;
	boolean transparent = true;
	for (s=0; s<numberSprites; s++)
	  {
	    tempX = sprites[s].getX();
	    tempY = sprites[s].getY();
	    if ((x>=tempX) && (x < (tempX + sprites[s].getFrameWidth()))
		&& (y>=tempY) && (y < (tempY + sprites[s].getHeight())))
	      {
		int pix = sprites[s].getFramePixel((x-sprites[s].getX()),
						   (y-sprites[s].getY()));
		int alfa = (pix >> 24) & 0xff;
		if (alfa != 0)
		  
		  transparent = false;
	      }
	  }
	if (transparent == false) 
	  getAppletContext().showStatus("Ouch it hit me!!           ");
	else getAppletContext().showStatus("You missed!                  ");
	
      }
    renderPlayfield();
    return true;
  }
  }







