package gui;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import logic.GameBuilder;
import logic.Result;
import models.Game;
import net.NetworkPlayManager;
import timer.ChessTimer;
import timer.TimerTypes;
import utility.FileUtility;
import utility.GuiUtility;
import utility.RunnableOfT;
import ai.AIAdapter;
import ai.AIManager;
import ai.AIPlugin;
import com.google.common.collect.Lists;
public class NewGamePanel extends ChessPanel
{
public NewGamePanel()
{
initGuiComponents();
}
private void initGuiComponents()
{
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridy = 0;
constraints.ipadx = 0;
constraints.insets = new Insets(5, 50, 5, 50);
constraints.anchor = GridBagConstraints.CENTER;
add(GuiUtility.createJLabel(Messages.getString("NewGamePanel.howToPlay")), constraints); //$NON-NLS-1$
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridBagLayout());
buttonPanel.setOpaque(false);
JButton humanPlayButton = new JButton(Messages.getString("NewGamePanel.humanPlay")); //$NON-NLS-1$
humanPlayButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
Driver.getInstance().pushPanel(createHumanGamePanel());
}
});
constraints.gridy = 1;
constraints.ipadx = 7;
constraints.insets = new Insets(5, 5, 5, 5);
buttonPanel.add(humanPlayButton, constraints);
if (NetworkPlayManager.getInstance().networkPlayIsAvailable())
{
JButton networkPlayButton = new JButton(Messages.getString("NewGamePanel.networkPlay")); //$NON-NLS-1$
networkPlayButton.addActionListener(NetworkPlayManager.getInstance().createNetworkPlayActionListener());
constraints.gridy = 2;
constraints.ipadx = 0;
constraints.insets = new Insets(2, 5, 0, 5);
buttonPanel.add(networkPlayButton, constraints);
}
JButton aiPlayButton = new JButton(Messages.getString("NewGamePanel.aiPlay")); //$NON-NLS-1$
aiPlayButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
if (validAIFilesExist())
Driver.getInstance().pushPanel(createAIGamePanel());
}
});
constraints.gridy = 3;
constraints.ipadx = 28;
constraints.insets = new Insets(2, 5, 5, 5);
buttonPanel.add(aiPlayButton, constraints);
constraints.gridy = 1;
add(buttonPanel, constraints);
JButton backButton = new JButton(Messages.getString("NewGamePanel.returnToMenu")); //$NON-NLS-1$
backButton.setToolTipText(Messages.getString("NewGamePanel.returnToMenu")); //$NON-NLS-1$
backButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
Driver.getInstance().revertToMainPanel();
}
});
constraints.gridy = 2;
add(backButton, constraints);
}
private ChessPanel createHumanGamePanel()
{
mPanel = new ChessPanel();
mPanel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
final JComboBox dropdown;
try
{
dropdown = new JComboBox(GameBuilder.getVariantFileArray());
}
catch (IOException e1)
{
JOptionPane.showMessageDialog(Driver.getInstance(), Messages.getString("NewGamePanel.errorCouldntLoadVariantFiles")); //$NON-NLS-1$
e1.printStackTrace();
return null;
}
// variant type selector
constraints.gridx = 0;
constraints.gridy = 0;
constraints.insets = new Insets(3, 10, 3, 10);
constraints.anchor = GridBagConstraints.WEST;
mPanel.add(GuiUtility.createJLabel(Messages.getString("NewGamePanel.type")), constraints); //$NON-NLS-1$
constraints.gridx = 1;
constraints.gridy = 0;
constraints.insets = new Insets(3, 10, 3, 10);
constraints.fill = GridBagConstraints.HORIZONTAL;
mPanel.add(dropdown, constraints);
// total time and increment fields
final JLabel totalTimeLabel = GuiUtility.createJLabel(Messages.getString("NewGamePanel.totalTime")); //$NON-NLS-1$
totalTimeLabel.setEnabled(false);
totalTimeLabel.setForeground(Color.white);
final JTextField totalTimeField = new JTextField("120", 3); //$NON-NLS-1$
totalTimeField.setEnabled(false);
final JLabel incrementLabel = GuiUtility.createJLabel(Messages.getString("NewGamePanel.increment")); //$NON-NLS-1$
incrementLabel.setEnabled(false);
incrementLabel.setForeground(Color.white);
final JTextField incrementField = new JTextField("10", 3); //$NON-NLS-1$
incrementField.setEnabled(false);
// combo box for selecting a timer
final JComboBox timerComboBox = new JComboBox(TimerTypes.values());
timerComboBox.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
TimerTypes timerType = (TimerTypes) timerComboBox.getSelectedItem();
if (timerType != TimerTypes.NO_TIMER)
{
totalTimeLabel.setEnabled(true);
totalTimeField.setEnabled(true);
incrementLabel.setEnabled(true);
incrementField.setEnabled(true);
}
else
{
totalTimeLabel.setEnabled(false);
totalTimeField.setEnabled(false);
incrementLabel.setEnabled(false);
incrementField.setEnabled(false);
}
}
});
// add the combo box to the frame
constraints.gridx = 0;
constraints.gridy = 1;
constraints.insets = new Insets(3, 10, 3, 10);
mPanel.add(GuiUtility.createJLabel(Messages.getString("NewGamePanel.timer")), constraints); //$NON-NLS-1$
constraints.gridx = 1;
constraints.gridy = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.insets = new Insets(3, 10, 3, 10);
mPanel.add(timerComboBox, constraints);
// add the total time field to the frame
constraints.gridx = 0;
constraints.gridy = 2;
constraints.insets = new Insets(3, 10, 3, 10);
mPanel.add(totalTimeLabel, constraints);
constraints.gridx = 1;
constraints.gridy = 2;
constraints.insets = new Insets(3, 10, 3, 10);
mPanel.add(totalTimeField, constraints);
// add the increment field to the frame
constraints.gridx = 0;
constraints.gridy = 3;
constraints.insets = new Insets(3, 10, 3, 10);
constraints.anchor = GridBagConstraints.CENTER;
mPanel.add(incrementLabel, constraints);
constraints.gridx = 1;
constraints.gridy = 3;
constraints.insets = new Insets(3, 10, 3, 10);
mPanel.add(incrementField, constraints);
// set up the done button
final JButton doneButton = new JButton(Messages.getString("NewGamePanel.start")); //$NON-NLS-1$
doneButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
TimerTypes timerType = (TimerTypes) timerComboBox.getSelectedItem();
long startTime = Integer.parseInt(totalTimeField.getText()) * 1000;
long increment = Integer.parseInt(incrementField.getText()) * 1000;
final Game gameToPlay = GameBuilder.newGame(dropdown.getSelectedItem().toString());
RunnableOfT<Boolean> timeElapsedCallback = new RunnableOfT<Boolean>()
{
@Override
public void run(Boolean isBlackTimer)
{
Result result = isBlackTimer ? Result.WHITE_WIN : Result.BLACK_WIN;
result.setGuiText(Messages.getString("NewGamePanel.timeHasRunOut") + result.winText() + Messages.getString("NewGamePanel.newLine")); //$NON-NLS-1$ //$NON-NLS-2$
GuiUtility.getChessCrafter().getPlayGameScreen(gameToPlay).endOfGame(result);
}
};
ChessTimer blackTimer = ChessTimer.createTimer(timerType, timeElapsedCallback, increment, startTime, true);
ChessTimer whiteTimer = ChessTimer.createTimer(timerType, timeElapsedCallback, increment, startTime, false);
gameToPlay.setTimers(whiteTimer, blackTimer);
PlayGamePanel gamePanel = new PlayGamePanel(gameToPlay);
Driver.getInstance().pushPanel(gamePanel);
}
});
// set up the cancel button
final JButton cancelButton = new JButton(Messages.getString("NewGamePanel.cancel")); //$NON-NLS-1$
cancelButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
Driver.getInstance().popPanel();
}
});
// add the done and cancel buttons to the panel
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.setOpaque(false);
buttonPanel.add(doneButton);
buttonPanel.add(cancelButton);
constraints.gridx = 0;
constraints.gridy = 4;
constraints.gridwidth = 2;
constraints.insets = new Insets(3, 10, 3, 10);
constraints.fill = GridBagConstraints.HORIZONTAL;
mPanel.add(buttonPanel, constraints);
return mPanel;
}
private ChessPanel createAIGamePanel()
{
mPanel = new ChessPanel();
mPanel.setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
// add the variant type selector to the frame
constraints.gridx = 0;
constraints.gridy = 0;
mPanel.add(GuiUtility.createJLabel(Messages.getString("NewGamePanel.type")), constraints); //$NON-NLS-1$
constraints.gridx = 1;
constraints.gridy = 0;
constraints.insets = new Insets(3, 0, 3, 0);
try
{
mPanel.add(new JComboBox(GameBuilder.getVariantFileArray()), constraints);
}
catch (IOException e1)
{
JOptionPane.showMessageDialog(Driver.getInstance(), Messages.getString("NewGamePanel.errorDidYouDeleteSomething")); //$NON-NLS-1$
e1.printStackTrace();
}
// add the AI selector to the frame
constraints.gridx = 0;
constraints.gridy = 1;
mPanel.add(GuiUtility.createJLabel(Messages.getString("NewGamePanel.ai")), constraints); //$NON-NLS-1$
final JComboBox aiComboBox = new JComboBox(AIManager.getInstance().getAIFiles());
constraints.gridx = 1;
constraints.gridy = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
mPanel.add(aiComboBox, constraints);
// add a button to the frame for installing a new AI
JButton addAIFileButton = new JButton(Messages.getString("NewGamePanel.installNewAI")); //$NON-NLS-1$
addAIFileButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
if (GuiUtility.tryAIFileInstall(NewGamePanel.this))
{
aiComboBox.removeAllItems();
for (String fileName : AIManager.getInstance().getAIFiles())
aiComboBox.addItem(fileName);
}
}
});
JButton nextButton = new JButton(Messages.getString("NewGamePanel.next")); //$NON-NLS-1$
nextButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
final String aiFileName = (String) aiComboBox.getSelectedItem();
File aiFile = FileUtility.getAIFile(aiFileName);
if (aiComboBox.getSelectedItem() == null)
{
JOptionPane.showMessageDialog(Driver.getInstance(),
Messages.getString("NewGamePanel.youHaveNotSelectedAI"), Messages.getString("NewGamePanel.noAIFile"), //$NON-NLS-1$ //$NON-NLS-2$
JOptionPane.PLAIN_MESSAGE);
return;
}
Game gameToPlay;
try
{
gameToPlay = GameBuilder.newGame((String) new JComboBox(GameBuilder.getVariantFileArray()).getSelectedItem());
}
catch (IOException e1)
{
e1.printStackTrace();
JOptionPane.showMessageDialog(Driver.getInstance(), Messages.getString("NewGamePanel.errorDidYouDeleteSomething")); //$NON-NLS-1$
return;
}
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, Locale.getDefault(), null);
String[] compileOptions = new String[] { "-d", "bin" }; //$NON-NLS-1$ //$NON-NLS-2$
Iterable<String> compilationOptions = Arrays.asList(compileOptions);
List<File> sourceFileList = Lists.newArrayList();
sourceFileList.add(aiFile);
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
CompilationTask task = compiler.getTask(null, fileManager, null, compilationOptions, null, compilationUnits);
if (!task.call())
{
JOptionPane.showMessageDialog(
Driver.getInstance(),
Messages.getString("NewGamePanel.compilationFailed") //$NON-NLS-1$
+
Messages.getString("NewGamePanel.makeSureClassImplementsAIPlugin") //$NON-NLS-1$
+ Messages.getString("NewGamePanel.makeSureClassIncludes") + "import ai.*;\n" //$NON-NLS-1$ //$NON-NLS-2$
+ "import ai.AIAdapter.*;\n", Messages.getString("NewGamePanel.compilationFailure"), JOptionPane.PLAIN_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$
return;
}
try
{
fileManager.close();
final AIPlugin aiPlugin;
final AIAdapter aiAdapter = new AIAdapter(gameToPlay);
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
Class<?> klazz = classLoader.loadClass(aiFileName.substring(0, aiFileName.indexOf(".java"))); //$NON-NLS-1$
Constructor<?> constructor = klazz.getConstructor();
aiPlugin = (AIPlugin) constructor.newInstance();
Thread aiThread;
aiThread = new Thread(new Runnable()
{
@Override
public void run()
{
try
{
aiAdapter.runGame(aiPlugin);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
aiThread.start();
PlayNetGamePanel playNetGame = new PlayNetGamePanel(gameToPlay, false, false);
playNetGame.setIsAIGame(true);
Driver.getInstance().pushPanel(playNetGame);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
JButton cancelButton = new JButton(Messages.getString("NewGamePanel.cancel")); //$NON-NLS-1$
cancelButton.addActionListener(new ActionListener()
{
@Override
public void actionPerformed(ActionEvent event)
{
Driver.getInstance().popPanel();
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
buttonPanel.setOpaque(false);
buttonPanel.add(nextButton);
buttonPanel.add(cancelButton);
constraints.gridx = 0;
constraints.gridy = 2;
constraints.gridwidth = 2;
constraints.insets = new Insets(3, 0, 3, 0);
mPanel.add(addAIFileButton, constraints);
constraints.gridx = 0;
constraints.gridy = 3;
mPanel.add(buttonPanel, constraints);
return mPanel;
}
public boolean validAIFilesExist()
{
if (AIManager.getInstance().getAIFiles().length == 0)
{
switch (JOptionPane.showConfirmDialog(Driver.getInstance(),
Messages.getString("NewGamePanel.noAIFilesInstalled"), Messages.getString("NewGamePanel.installAIFiles"), //$NON-NLS-1$ //$NON-NLS-2$
JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE))
{
case JOptionPane.YES_OPTION:
return GuiUtility.tryAIFileInstall(NewGamePanel.this);
case JOptionPane.NO_OPTION:
default:
return false;
}
}
else
{
return true;
}
}
private static final long serialVersionUID = -6371389704966320508L;
private ChessPanel mPanel;
}