/* Generated by Together */

import java.io.*;
import java.util.Vector;
import java.awt.Dimension;
import java.awt.image.ImageObserver;
import javax.swing.*;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Iterator;

/**
 * This class provides methods for the main frame to get the components of the
 * game.  When a MainFrame is created, it is passed one of these.  Basically,
 * by using different GameSetup instances, the game can take on many different
 * forms with the same "standard" mechanism around it.
 *
 * Students will be given this class and the various interfaces in code format.
 * My implmentations of all the other classes will only be distributed in compiled,
 * .jar format.  Over the course of the semester, the students will modify the
 * methods of this class and write their own implementations of the basic
 * interfaces to provide the behavior of the game.
 *
 * DO NOT modify the signatures of the methods provided here.  You can add
 * other methods to this class, but don't change the ones that are present
 * or your code is likely to stop working inside the framework.
 */
public class GameSetup {
    /**
     * This method should be called in your main before you create your MainFrame.
     * It should initialize all of your variables that are related to the general
     * state of the game.
     */
    public static void constructVariables() {
        // Set this to whatever works well for your game.
        Location.setPartialsInWhole(5);

        Vector vect;
        /*
        // Load in the map.
        // You can uncomment this code when you want to have your game load a map
        // that you made with the ScreenEditor.
		try {
			vect=ScreenEditor.readScreenVector("BasicMap.bin");
	        firstScreen=(Screen)vect.get(0);
        } catch(IOException e) {
			firstScreen=new BasicScreen();
        } catch(ClassNotFoundException e) {
			firstScreen=new BasicScreen();
        }
        */

        // This builds a screen using the default constructor.  I put it in the
        // vector so that it works with the code below that was written for the
        // loading.
        vect=new Vector();
        firstScreen=new BasicScreen();
        vect.add(firstScreen);

        // Setup basic variables.
        localPlayer=new BasicPlayer(new Location(firstScreen,10,10));
        firstScreen.addEntity(localPlayer);

        // Set up the original queue and add all entities.
        priorityQueue=new ListBasedPriorityQueue();
        for(int i=0; i<vect.size(); i++) {
            Screen scr=(Screen)vect.get(i);
            for(Iterator iter=scr.createEntityIterator(); iter.hasNext(); ) {
                GameEntity ge=(GameEntity)iter.next();
				priorityQueue.add(ge);
            }
        }
    }

    /**
     * This method is called in the constructor of a main frame so that the
     * GameSetup class will be able to communicate with the frame that the
     * game is being played in.
     * @param mf The MainFrame object the game is being played in.
     */
    public static void setMainFrame(MainFrame mf) {
        mainFrame=mf;
    }

    /**
     * Returns the instance of your Player subclass that should be used in this game.
     */
    public static Player getLocalPlayer() {
        return localPlayer;
    }

    /**
     * Return the priority queue that you are using for the game.  You will write
     * two of these during the semester.
     */
    public static PriorityQueue getPriorityQueue() {
        return priorityQueue;
    }

    /**
     * Tells the display class is this game has a scrolling background.  I have
     * not done that much testing on the scrolling backgrounds.  They should work,
     * but there are no promises.  Debugging for you will probably be easier if
     * you can see the whole screen anyway.
     * @return This value tells the program how many squares across it should draw around the player.  Return -1 for no scrolling.
     */
    public static int getScrolling() {
        return -1;
    }

    /**
     * This method tells the display class if the images in the game should be
     * scaled.  If you turn this off your window will be fixed to a given size
     * and the user won't be able to scale it.  You will have to make
     * sure that all your blocks use the same image size.  The drawing program
     * assumes that the size of the 0,0 block should be used for all.  The reason
     * you would want this option off is if you want to draw an entity that is
     * larger than a single block.  Doing so will complicate your life though so
     * I recommend that this return true unless you have a very compelling reason
     * to do otherwise.
     * @return Whether images should be scaled for this game.
     */
    public static boolean getScaling() {
        return true;
    }

    /**
     * If this returns true, the drawing routine will use an optimization of
     * drawing the images for all the blocks once to a large image and just
     * putting up that image as long as the player hasn't changed screens.  This
     * can be significantly faster.  However, if it is true, it means that changes
     * to blocks won't normally be drawn so you can't have animated blocks, or
     * moving blocks, or blocks that disappear (doors).  This flag is checked
     * at every step so you could have it return true most of the time, but return
     * false when some event has occured that should require the blocks to be
     * redrawn.
     * @return Whether or not the framework should double-buffer the blocks as a background image.
     */
    public static boolean useDrawOptimization() {
        return true;
    }

    /**
     * This function returns a JMenuBar object that will be added to the main
     * display window.  All of the functions that you want the menus to be able
     * to doo will need to be connected from here.
     */
    public static JMenuBar getMenuBar() {
        JMenuBar menuBar=new JMenuBar();
        JMenu fileMenu=new JMenu("File");
        JMenuItem startItem=new JMenuItem("Start Game");
        startItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { startGame(); }
        });
        fileMenu.add(startItem);
        JMenuItem item=new JMenuItem("Exit");
        item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { System.exit(0); }
        });
        fileMenu.add(item);
        menuBar.add(fileMenu);
        return menuBar;
    }

    /**
     * This function will automatically be called when the player begins to return
     * something other than GAME_RUNNING.
     */
    public static void stopGame() {
        if(getLocalPlayer().gameStatus()==Player.GAME_SUCCESS) {
            JOptionPane.showMessageDialog(mainFrame,"You won the game!","Congratulations!",JOptionPane.OK_OPTION);
        } else if(getLocalPlayer().gameStatus()==Player.PLAYER_DEAD) {
            JOptionPane.showMessageDialog(mainFrame,"Sorry, you lost.","Oops",JOptionPane.OK_OPTION);
        }
    }

    /**
     * This method is called from the event handler for the start option on the
     * menu.  It can be replaced if you want to use different menu options.  You
     * will add other similar functions for all the menu options that you add.
     */
    private static void startGame() {
        mainFrame.getDisplay().requestFocus();
        mainFrame.getTimer().start();
    }

    private static Player localPlayer=null;
	private static PriorityQueue priorityQueue=null;
    private static Screen firstScreen;
    private static MainFrame mainFrame;
}