import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import Playfield;
import Music;

/********************************************************
 * Jamming class contains the playfield and controls
 * the interface including mouse and keyboard events.
 * It also creates the animation sequences for the
 * playfield
 *********************************************************/
 public class Jamming extends Applet implements Runnable {
   Playfield play;
   int oldmousex, oldmousey;
   boolean hit;
   Image output;

   Thread animate;
   Music groove;

   // creates playfield and plays music
   public void init() {
     // get parameters from html document
     String filename = getParameter("background");
     String soundurl = getParameter("groove");
     AnimatedSprite screwlamp;
     AnimatedSprite desklamp;

     // start the music
     groove = new Music(this, soundurl);

     // create the playfield and animation sprites
     play = new Playfield
       (getImage(getDocumentBase(), filename), 2);
     screwlamp = createAnimatedScrewLamp();
     desklamp = createAnimatedDeskLamp();
     play.addSprite (0, screwlamp);
     play.addSprite (1, desklamp);

     // draw the scene
     renderPlayfield();
   }

   public void start() {
     animate = new Thread(this);
     animate.start();
   }

   public void stop() {
     animate = null;
   }

   public void run() {
     while (true) {
       try {
	 animate.sleep(200);
       } catch (InterruptedException e) {
       }
       // update the clock in the animations
       play.updateTick();
       renderPlayfield();
     }
   }

   public void renderPlayfield() {
     play.Draw();
     output = play.toImage();
     repaint();
   }

   public void paint(Graphics g) {
     g.drawImage(output, 0, 0, this);
   }

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

   // handles events when mouse is dragging
   public boolean mouseDrag(Event e, int getX, int getY) {
     // if a current drag...
     if (hit) {
       // move the sprite relative to old position
       play.moveRelSprite(getX-oldmousex, getY-oldmousey);
       renderPlayfield();
       // save coordinates for future use
       oldmousex = getX;
       oldmousey = getY;
     }
     return true;
   }

   // handles events when mouse is pressed
   public boolean mouseDown (Event e, int getX, int getY) {
     // if mouse pointer clicked over a sprite...
     if (play.hitSprite(getX, getY)) {
       showStatus("Hit a Sprite!");
       // save coordinates for future use
       oldmousex = getX;
       oldmousey = getY;
       hit = true;
     }
     else {
       showStatus("No hit.");
     }
     return true;
   }

   // handles events when mouse is released
   public boolean mouseUp (Event e, int getX, int getY) {
     // dragging ended
     hit = false;
     return true;
   }

   // handles events when a key is pressed
   public boolean keyDown (Event e, int key) {
     showStatus ("You pressed key " + (char) key);
     // set sprites to top left corner position
     if (key == (int) 'r') {
       play.resetSpritePositions();
     }

     // make desklamp head-nod
     if (key == (int) 'd') {
       play.changeTrack(1, 1);
     }

     // make screw lamp head-nod
     if (key == (int) 's') {
       play.changeTrack(0, 1);
     }

     // make desklamp bounce-head
     if (key == (int) 'b') {
       play.changeTrack(1, 0);
     }

     // make screw lamp slide
     if (key == (int) 'l') {
       play.changeTrack(0, 0);
     }
     renderPlayfield();
     return true;
   }

   // initializes an animated sprite and creates animation sequences
   public AnimatedSprite createAnimatedScrewLamp() {
     // initialize sprite and load first frame
     AnimatedSprite s = new
       AnimatedSprite(getImage(getDocumentBase(), "smallscrew1.gif"), 4);
     // load sequential frames
     s.addImage(1, getImage(getDocumentBase(), "smallscrew2.gif"));
     s.addImage(2, getImage(getDocumentBase(), "smallscrew3.gif"));
     s.addImage(3, getImage(getDocumentBase(), "smallscrew4.gif"));
     // move sprite off the screen
     s.moveRel(610, 0);

     // create track
     s.addState(0, 0, 1, -20, 2);
     s.addState(0, 1, 1, -10, -2);
     s.addState(0, 2, 1, -10, 2);
     s.addState(0, 3, 1, -10, -2);

     // create track
     s.addState(1, 0, 1, 0, 4);
     s.addState(1, 1, 1, 0, -4);

     s.setTrack(0);
     return s;
   }

   // initializes an animated sprite and creates animation sequences
   public AnimatedSprite createAnimatedDeskLamp() {
     // initialize sprite and load first frame
     AnimatedSprite s = new
       AnimatedSprite(getImage(getDocumentBase(), "smalldesk1.gif"), 6);
     // load sequential frames
     s.addImage(1, getImage(getDocumentBase(), "smalldesk2.gif"));
     s.addImage(2, getImage(getDocumentBase(), "smalldesk3.gif"));
     s.addImage(3, getImage(getDocumentBase(), "smalldesk4.gif"));
     s.addImage(4, getImage(getDocumentBase(), "smalldesk5.gif"));
     s.addImage(5, getImage(getDocumentBase(), "smalldesk6.gif"));

     // create track
     s.addState(0, 0, 1, 0, 0);
     s.addState(0, 1, 1, 0, 0);
     s.addState(0, 2, 1, 0, 0);
     s.addState(0, 2, 1, 0, 0);
     s.addState(0, 1, 1, 0, 0);
     s.addState(0, 0, 1, 0, 0);
     s.addState(0, 0, 1, 0, 0);
     s.addState(0, 1, 1, 0, 0);
     s.addState(0, 2, 1, 0, 0);
     s.addState(0, 3, 1, 0, 0);
     s.addState(0, 4, 1, 0, 0);
     s.addState(0, 5, 1, 0, 0);
     s.addState(0, 5, 1, 0, 0);
     s.addState(0, 4, 1, 0, 0);
     s.addState(0, 3, 1, 0, 0);
     s.addState(0, 2, 1, 0, 0);
     s.addState(0, 1, 1, 0, 0);
     s.addState(0, 0, 1, 0, 0);

     // create track
     s.addState(1, 0, 1, 0, 0);
     s.addState(1, 1, 1, 0, 0);

     s.setTrack(0);
     return s;
   }
 }




