// Yura Mamyrin, Group D

package risk.ui.FlashGUI;

import risk.engine.AboutDialog;
import risk.engine.Risk;
import risk.engine.RiskFileFilter;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.MouseInputListener;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.KeyListener;
import java.awt.event.KeyEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.image.BufferedImage;

/**
 * <p> Main Menu for FlashGUI </p>
 * @author Yura Mamyrin <yura@yura.net>
 * @author Christian Weiske <cweiske@cweiske.de>
 */

public class MainMenu extends JPanel implements MouseInputListener, KeyListener
{

	private final static String version = "1.0.3.4";
	private final static String product = "Flash GUI for RISK";

	private BufferedImage MenuImage;
	private BufferedImage Server;
	private Risk myrisk;

	private boolean serverRunning;

	private JoinDialog joinDialog;

	private final static int BUTTON_NEW		= 1;
	private final static int BUTTON_SERVER		= 2;
	private final static int BUTTON_LOADGAME	= 3;
	private final static int BUTTON_HELP		= 4;
	private final static int BUTTON_JOIN		= 5;
	private final static int BUTTON_EXIT		= 6;
	private final static int BUTTON_ABOUT		= 7;

	private JLabel loading;

	/**
	 * Creates a new MainMenu
	 * @param r the risk main program
	 */
	public MainMenu(Risk r,Frame gui) {

		myrisk = r;

		new FlashRiskAdapter(this, myrisk);

		try {
			MenuImage = ImageIO.read( this.getClass().getResource("menu.jpg") );
			Server = MenuImage.getSubimage(400, 490, 60, 60);
		} catch (Exception e) { }

		Dimension menuSize = new Dimension(400,550);

		addMouseListener(this);
		addMouseMotionListener(this);
		setPreferredSize(menuSize);
		setMinimumSize(menuSize);
		setMaximumSize(menuSize);

		//key control

		highlightButton=0;
		serverRunning = false;

		gui.setFocusTraversalKeysEnabled( false);
		gui.addKeyListener( this );

		setLayout(null);

		loading = new JLabel( "LOADING",new javax.swing.ImageIcon( this.getClass().getResource("earth.gif") ),JLabel.CENTER );
		loading.setBounds(152,409,95,95);
		loading.setHorizontalTextPosition(JLabel.CENTER);
		loading.setFont( new java.awt.Font("Arial", java.awt.Font.BOLD, 18) );
		loading.setVisible(false);
		loading.setForeground( Color.BLACK );
		add(loading);

	}

	/**
	 * Checks the server's state
	 * @param s The server's state
	 */
	public void setServerRunning(boolean s) {

		serverRunning = s;
		repaint();

	}

	public void hideJoinDialog(boolean a) {

		if (!a) {
			joinDialog.exitForm();
			joinDialog = null;
		}

		addMouseListener(this);
		addMouseMotionListener(this);

		loading.setVisible(false);

		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));

	}


		/**
		 * Paints the panel
		 * @param g The graphics
		 */
	public void paintComponent(Graphics g) {

			g.drawImage( MenuImage ,0 ,0 ,400 ,550 ,0 ,0 ,400 ,550 ,this );



			if (highlightButton==1) {
				g.drawImage( MenuImage ,57 ,219 ,187 ,269	,400 ,0 ,530 ,50 ,this );
			}
			else if (highlightButton==2) {
				g.drawImage( MenuImage ,212 ,219 ,342 ,269	,400 ,50 ,530 ,100 ,this );
			}
			else if (highlightButton==3) {
				g.drawImage( MenuImage ,57 ,279 ,187 ,329	,400 ,100 ,530 ,150 ,this );
			}
			else if (highlightButton==4) {
				g.drawImage( MenuImage ,212 ,279 ,342 ,329	,400 ,150 ,530 ,200 ,this );
			}
			else if (highlightButton==5) {
				g.drawImage( MenuImage ,57 ,339 ,187 ,389	,400 ,200 ,530 ,250 ,this );
			}
			else if (highlightButton==6) {
				g.drawImage( MenuImage ,212 ,339 ,342 ,389	,400 ,250 ,530 ,300 ,this );
			}
			else if (highlightButton==7) {
				g.drawImage( MenuImage ,145 ,401 ,255 ,511	,400 ,300 ,510 ,410 ,this );
			}


			else if (button==1) {
				g.drawImage( MenuImage ,57 ,219 ,187 ,269	,530 ,0 ,660 ,50 ,this );
			}
			else if (button==2) {
				g.drawImage( MenuImage ,212 ,219 ,342 ,269	,530 ,50 ,660 ,100 ,this );
			}
			else if (button==3) {
				g.drawImage( MenuImage ,57 ,279 ,187 ,329	,530 ,100 ,660 ,150 ,this );
			}
			else if (button==4) {
				g.drawImage( MenuImage ,212 ,279 ,342 ,329	,530 ,150 ,660 ,200 ,this );
			}
			else if (button==5) {
				g.drawImage( MenuImage ,57 ,339 ,187 ,389	,530 ,200 ,660 ,250 ,this );
			}
			else if (button==6) {
				g.drawImage( MenuImage ,212 ,339 ,342 ,389	,530 ,250 ,660 ,300 ,this );
			}
			else if (button==7) {
				g.drawImage( MenuImage ,145 ,401 ,255 ,511	,530 ,300 ,640 ,410 ,this );
			}

			Graphics2D g2 = (Graphics2D)g;

			g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

			FontRenderContext frc = g2.getFontRenderContext();
			Font font = g2.getFont();
			g2.setColor( Color.black );
			TextLayout tl;

			java.util.ResourceBundle resBundle = risk.engine.translation.TranslationBundle.getBundle();

			/* This adds underlines to the strings, but it doesn't look good and is too much effort for that
			java.text.AttributedString as = new java.text.AttributedString(resBundle.getString( "mainmenu.newgame"));
			as.addAttribute(java.awt.font.TextAttribute.UNDERLINE, java.awt.font.TextAttribute.UNDERLINE_ON, 0,1);
			as.addAttribute(java.awt.font.TextAttribute.FONT, font);
			tl = new TextLayout( as.getIterator(), frc);
			*/
			
			tl = new TextLayout( resBundle.getString( "mainmenu.newgame") , font, frc);
			tl.draw( g2, (float) (122-tl.getBounds().getWidth()/2), (float)247 );

			if (serverRunning) {
				tl = new TextLayout( resBundle.getString( "mainmenu.stopserver") , font, frc);
				tl.draw( g2, (float) (277-tl.getBounds().getWidth()/2), (float)247 );

				g.drawImage( Server, 340, 490, this );

			}
			else {
				tl = new TextLayout( resBundle.getString( "mainmenu.startserver") , font, frc);
				tl.draw( g2, (float) (277-tl.getBounds().getWidth()/2), (float)247 );
			}

			tl = new TextLayout( resBundle.getString( "mainmenu.loadgame"), font, frc);
			tl.draw( g2, (float) (122-tl.getBounds().getWidth()/2), (float)309 );

			tl = new TextLayout( resBundle.getString( "mainmenu.help") , font, frc);
			tl.draw( g2, (float) (277-tl.getBounds().getWidth()/2), (float)309 );

			tl = new TextLayout( resBundle.getString( "mainmenu.joingame") , font, frc);
			tl.draw( g2, (float) (122-tl.getBounds().getWidth()/2), (float)369 );

			tl = new TextLayout( resBundle.getString( "mainmenu.quit") , font, frc);
			tl.draw( g2, (float) (277-tl.getBounds().getWidth()/2), (float)369 );

			font = new java.awt.Font("Arial", java.awt.Font.BOLD, 24);

			tl = new TextLayout( resBundle.getString( "mainmenu.about") , font, frc);
			tl.draw( g2, (float) (200-tl.getBounds().getWidth()/2), (float)465 );

	}


	private int button;
	private int currentButton;
	private int pressedButton;
	private int highlightButton;

	//**********************************************************************
	//                     MouseListener Interface
	//**********************************************************************

	public void mouseClicked(MouseEvent e) {
	}

	public void mouseEntered(MouseEvent e) {
	}

	public void mouseExited(MouseEvent e) {
	}

	/**
	 * Works out what to do when the move has been presed
	 * @param e A mouse event
	 */
	public void mousePressed(MouseEvent e) {

		highlightButton = 0;
		currentButton=insideButton(e.getX(),e.getY());

		if (currentButton != 0) {
			pressedButton = currentButton;
			button = currentButton;
			repaint();
		}

	}

	/**
	 * Works out what to do when a mouse has been released
	 * @param e A mouse event
	 */
	public void mouseReleased(MouseEvent e)
	{
		int thebutton=0;

		if (pressedButton == currentButton) {
			thebutton = pressedButton;
		}

		if (button != 0) {
			button=0;
		}

		highlightButton=currentButton;
		repaint();
		activateButton( thebutton);
	}//public void mouseReleased(MouseEvent e)


	/**
	 * a button shall be activated
	 */
	private void activateButton(int thebutton)
	{
		if (thebutton != 0) {

			switch (thebutton)
			{
				case MainMenu.BUTTON_NEW:
					myrisk.parser("newgame");

					setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));

					removeMouseListener(this);
					removeMouseMotionListener(this);

					loading.setVisible(true);

					break;


				case MainMenu.BUTTON_SERVER:
					if (serverRunning) {
						myrisk.parser("killserver");
					}
					else {
						myrisk.parser("startserver");
					}
					break;


				case MainMenu.BUTTON_LOADGAME:
					JFileChooser fc = new JFileChooser("saves/");
					RiskFileFilter filter = new RiskFileFilter(RiskFileFilter.RISK_SAVE_FILES);
					fc.setFileFilter(filter);

					int returnVal = fc.showDialog( Risk.findParentFrame(this) , risk.engine.translation.TranslationBundle.getBundle().getString("mainmenu.loadgame.loadbutton"));
					if (returnVal == javax.swing.JFileChooser.APPROVE_OPTION) {
						java.io.File file = fc.getSelectedFile();
						// Write your code here what to do with selected file

						myrisk.parser("loadgame " + file.getAbsolutePath() );

					} else {
						// Write your code here what to do if user has canceled Open dialog
					}
					break;


				case MainMenu.BUTTON_HELP:

					try {
						Risk.openDocs( risk.engine.translation.TranslationBundle.getBundle().getString( "helpfiles.flash" ) );
					}
					catch(Exception e) {
						JOptionPane.showMessageDialog( Risk.findParentFrame(this) ,"Unable to open manual: "+e.getMessage(),"Error", JOptionPane.ERROR_MESSAGE);
					}

					break;


				case MainMenu.BUTTON_JOIN:
{
					Frame frame = Risk.findParentFrame(this);

					joinDialog = new JoinDialog( frame , true, myrisk);
					Dimension frameSize = frame.getSize();
					Dimension aboutSize = joinDialog.getPreferredSize();
					int x = frame.getLocation().x + (frameSize.width - aboutSize.width) / 2;
					int y = frame.getLocation().y + (frameSize.height - aboutSize.height) / 2;
					if (x < 0) x = 0;
					if (y < 0) y = 0;
					joinDialog.setLocation(x, y+10);

					joinDialog.setVisible(true);
					break;
}
				case MainMenu.BUTTON_EXIT:

					if (Risk.applet == null) {
						System.exit(0);
					}
					break;

				case MainMenu.BUTTON_ABOUT:
{
					Frame frame = Risk.findParentFrame(this);

					Risk.openAbout(frame,product, version);

					break;
}
			}//switch end

			currentButton=0;
			//do we need this?
//			highlightButton=currentButton;
			repaint();

		}
	}//private void activateButton(int thebutton)


	/**
	 * Checks if highlighting is needed
	 * @param e A mouse event
	 */
	public void mouseMoved(MouseEvent e) {

		int oldhighlightButton = highlightButton;
		int newhighlightButton = insideButton(e.getX(),e.getY());

		if (oldhighlightButton != newhighlightButton) {
			highlightButton = newhighlightButton;
			repaint();
		}

	}

	/**
	 * Works out what to do when the mouse is dragged
	 * @param e A mouse event
	 */
	public void mouseDragged(MouseEvent e) {

		currentButton = insideButton(e.getX(),e.getY());

		if (pressedButton == currentButton ) {
			if (button!=pressedButton) {
				button=pressedButton;
				repaint();
			}
		}
		else {
			if (button !=0) {
				button = 0;
				repaint();
			}
		}

	}

	/**
	 * Works out what button has been pressed
	 * @param x x co-ordinate
	 * @param y y co-ordinate
	 * @return int The type of button presssed
	 */
	public int insideButton(int x, int y) {

		int W=116;
		int H=31;

		int B=0;

		int yrel = Math.abs(455 - y);
		int xrel = (int) (Math.sqrt(2255 - yrel * yrel) * 95 / 95);

		if (x >= 65 && x < (65 + W) && y >= 228 && y < (228 + H)) {
			B=1;
		}
		else if (x >= 220 && x < (220 + W) && y >= 228 && y < (228 + H)) {
			B=2;
		}
		else if (x >= 65 && x < (65 + W) && y >= 289 && y < (289 + H)) {
			B=3;
		}
		else if (x >= 220 && x < (220 + W) && y >= 289 && y < (289 + H)) {
			B=4;
		}
		else if (x >= 65 && x < (65 + W) && y >= 350 && y < (350 + H)) {
			B=5;
		}
		else if (x >= 220 && x < (220 + W) && y >= 350 && y < (350 + H)) {
			B=6;
		}
		else if (x >= 200 - xrel && x < 200 + xrel) {
			B=7;
		}

		return B;

	}

	/**
	 * key control
	 */

	/**
	 * the user has released a key
	 */
	public void keyReleased( KeyEvent event )
	{
		switch (event.getKeyCode()) {
			//tab to the next button
			case KeyEvent.VK_TAB:
				if (event.isShiftDown()) {
					//Shift + Tab -> backwards
					highlightButton--;
				} else {
					//tab only -> forward
					highlightButton++;
				}
				if (highlightButton > 7) {
					highlightButton = 1;
				} else if (highlightButton < 1) {
					highlightButton = 7;
				}
				repaint();
				break;

			//activate the current button
			case KeyEvent.VK_SPACE:
			case KeyEvent.VK_ENTER:
				activateButton( highlightButton);
				break;


			//new game
			case KeyEvent.VK_N:
				activateButton( MainMenu.BUTTON_NEW);
				break;

			//load game
			case KeyEvent.VK_L:
				activateButton( MainMenu.BUTTON_LOADGAME);
				break;

			//exit
			case KeyEvent.VK_Q:
			case KeyEvent.VK_ESCAPE:
				activateButton( MainMenu.BUTTON_EXIT);
				break;

			//join game
			case KeyEvent.VK_J:
				activateButton( MainMenu.BUTTON_JOIN);
				break;

			//about
			case KeyEvent.VK_A:
				activateButton( MainMenu.BUTTON_ABOUT);
				break;

			//server
			case KeyEvent.VK_S:
				activateButton( MainMenu.BUTTON_SERVER);
				break;

			//help
			case KeyEvent.VK_H:
				activateButton( MainMenu.BUTTON_HELP);
				break;
		}//switch keycode
	}//public void keyReleased( KeyEvent event )


	//I don't want these, but we implement the interface
	public void keyPressed( KeyEvent event ) {}
	public void keyTyped( KeyEvent event ) {}


	/**
	 * This runs the program
	 * @param argv
	 */
	public static void main(String[] argv)
	{
		// set up system Look&Feel
		try {
			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
		}
		catch (Exception e) {
			e.printStackTrace();
		}

		risk.engine.translation.TranslationBundle.parseArgs(argv);

		JFrame gui = new JFrame();

		gui.setContentPane( new MainMenu( new Risk(null),gui ) );
		gui.setIconImage(Toolkit.getDefaultToolkit().getImage( Risk.class.getResource("icon.gif") ));
		gui.setTitle( risk.engine.translation.TranslationBundle.getBundle().getString( "mainmenu.title"));
		gui.setResizable(false);
		gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		gui.pack();

		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		Dimension frameSize = gui.getSize();
		frameSize.height = ((frameSize.height > screenSize.height) ? screenSize.height : frameSize.height);
		frameSize.width = ((frameSize.width > screenSize.width) ? screenSize.width : frameSize.width);
		gui.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);

		gui.setVisible(true);
	}

}
