import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GameWindow extends JFrame implements ActionListener {

	//public things that control the game
	final static public int WINDOW_WIDTH = 640; 	  //GameWindow Width
	final static public int WINDOW_HEIGHT = 480; 	  //GameWindow Height
	             public int SHIP_MOVE_SPEED = 1; 	  //Start speed in Pixels
	             public int SHIP_MAX_SPEED = 5; 	  //Max Apeed in Pixels
	final static public int SHIP_WIDTH = 60; 		  //WIDTH OF SHIP GRAPHIC
	final static public int SHIP_HEIGHT = 60; 		  //HEIGHT OF SHIP GRAPHIC
	final static public int OBSTACLE_WIDTH = 30;	  //WIDTH OF OBST GRAPHIC
	final static public int OBSTACLE_HEIGHT = 30;	  //HEIGHT OF OBST GRAPHIC
				 public int SHIP_DRAG = 2; 			  // not implemented
	final static public int FLY_FORWARD_OFFSET = 180; //height on window
													  //to constrain ship
	final static public int BACK_STRIP_HEIGHT = 50;   //how tall background strips are
	final static public int BACK_FLIP_SIZE = 25;      //how far till rotating strip array
	final static public int TIMER_INCREMENT = 50; 	  //how fast the game cycles in mls
	final static public int LASER_SPEED = 10; 		  //speed of lasers in mls

	//Layer Constants to determine what is foreground and background
	//the numbers themserlves are unimporant
	final static public int BACKGROUND = 1;
	final static public int LASER_LAYER = 2;
	final static public int SHIP_LAYER = 3;

	//internal class vars
	private Container pane;
	private GameLoop daGameLoop;
	private KeyboardMon daKeyMon;

	//managers for major game parts
	private BackgroundManager BackMgr;

	//public utilities for everyone's use
	public GameUtilities daGameUtils;

	//Buffer to hold keystrokes for processing
	//Slightly different from the standard
	//Swing processing model
	final public int keyBuffer[];

	//stuff to make this thing draw better -- should be simpler!
	public JPanel drawingArea;
	private Graphics2D offScreenBrush;
	private Graphics2D drawingBrush;
	private Image offScreen;

	//test image
	Image tester;
	JLabel testbox;

	//constructor
	public GameWindow () {

		super("Javaders");

		//add inner class to kill on close
		addWindowListener(new BasicWindowMonitor());

		//set the size of the JFrame to the specified values
		setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
		//turn off resizing the window
		setResizable(false);

		//get a handle to the pane to add stuff
		//and kill the Layout Manager
		Container pane = getContentPane();
		pane.setLayout(null);

		//create the key buffer to hold state of controls
		keyBuffer = new int [5];
		keyBuffer[0] = 0;
		keyBuffer[1] = 0;
		keyBuffer[2] = 0;
		keyBuffer[3] = 0;
	    keyBuffer[4] = 0;

		//setup utilities for dealing with images and whatnot
		daGameUtils = new GameUtilities();

		//setup main game loop
		daGameLoop = new GameLoop(this);

		//setup keyboard monitoring (controls)
		daKeyMon = new KeyboardMon(this);
		addKeyListener(daKeyMon);

		//establish background manager
		BackMgr = new BackgroundManager(this);

		//setup background
		BackMgr.SetupBackground();

		//drawing area and offscreen goo
		drawingArea = new GamePanel();
		drawingArea.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
		pane.add(drawingArea);
		drawingArea.setBounds(0,0,WINDOW_WIDTH, WINDOW_HEIGHT);
	}
	
	private class GamePanel extends JPanel {
		public void update(Graphics g){
			paint(g);
		}
		public void paint(Graphics g){
			//check for offScreen eating itself or first time through
			if (offScreen == null) {
				//initiallize drawing and all that crap
				System.out.println("Initializing Drawing Setup");
				offScreen = createImage(drawingArea.getSize().width, drawingArea.getSize().height);
				offScreenBrush=(Graphics2D)(offScreen.getGraphics());
				offScreenBrush.setRenderingHint(
				RenderingHints.KEY_RENDERING,
				RenderingHints.VALUE_RENDER_SPEED);
					offScreenBrush.setRenderingHint(
				RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_OFF);
			}
			
			g.drawImage(offScreen,0,0,null);
		}
	}

	//listen for unrouted messages and print them
	public void actionPerformed (ActionEvent ae) {
		//shouldn't get anything here !
		//this is a catch all to see if we are
		//not listening to something right
		System.out.println(ae);
	}

	//starts the timer that throws game events
	public void StartGame() {
		System.out.println("Starting Game");
		daGameLoop.start();
	}

	//stops the timer that throws game events
	public void StopGame() {
		System.out.println("Stopping Game");
		daGameLoop.stop();
		System.out.println("Game Events Halted");
	}

	//set the difficulty level
	public void SetDifficultyLevel(int x) {
		SHIP_MOVE_SPEED = SHIP_MOVE_SPEED + x; 	  			  //Start speed in Pixels
		SHIP_DRAG = SHIP_DRAG + x;

	}

	//MAIN RENDERING LOOP
	//called once perframe when game is
	//in 'playing' mode.
	public void AdvanceGameFrame() {
		RenderingLoop();
	}

	public void RenderingLoop () {
		if(offScreen == null) /* can't render with nowhere to draw */
			return;
		//System.out.println("GOT A GAME EVENT");

		//Inside main rendering loop
		BackMgr.UpdateBackground();

		drawingArea.repaint();
	}

	public Graphics2D GetOffScreenBrush() {
		return offScreenBrush;
	}

	public void addComponent(Component x, int whichLayer) {
		Integer LAYER = new Integer(whichLayer);
		pane.add(x, LAYER);
	}


	//INNER CLASS
	// based on Orielly Swing book sample class
	// documented all over the place.
	// this kills the frame when the
	// close button is pressed instead if
	// hiding it which is default.
	class BasicWindowMonitor extends WindowAdapter {
		public void windowClosing (WindowEvent e) {
			//System.out.println(e);
			exit(e.getWindow());
		}
		public void exit (Window w) {
			w.setVisible(false);
			w.dispose();
			System.exit(0);
		}
	}

}