package games.strategy.engine.framework.startup.ui;
import java.awt.Color;
import java.awt.Container;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.framework.message.PlayerListing;
import games.strategy.engine.framework.startup.launcher.ILauncher;
import games.strategy.engine.framework.startup.launcher.LocalLauncher;
import games.strategy.engine.framework.startup.mc.GameSelectorModel;
import games.strategy.engine.pbem.PBEMMessagePoster;
import games.strategy.engine.random.IRandomSource;
import games.strategy.engine.random.PlainRandomSource;
/** Setup panel when hosting a local game. */
public class LocalSetupPanel extends SetupPanel implements Observer {
private static final long serialVersionUID = 2284030734590389060L;
private final GameSelectorModel m_gameSelectorModel;
private final List<LocalPlayerComboBoxSelector> m_playerTypes = new ArrayList<>();
public LocalSetupPanel(final GameSelectorModel model) {
m_gameSelectorModel = model;
createComponents();
layoutComponents();
setupListeners();
setWidgetActivation();
}
private void createComponents() {}
private void layoutComponents() {
final GameData data = m_gameSelectorModel.getGameData();
removeAll();
m_playerTypes.clear();
setLayout(new GridBagLayout());
if (data == null) {
add(new JLabel("No game selected!"));
return;
}
final Collection<String> disableable = data.getPlayerList().getPlayersThatMayBeDisabled();
final HashMap<String, Boolean> playersEnablementListing = data.getPlayerList().getPlayersEnabledListing();
final Map<String, String> reloadSelections = PlayerID.currentPlayers(data);
final String[] playerTypes = data.getGameLoader().getServerPlayerTypes();
final String[] playerNames = data.getPlayerList().getNames();
// if the xml was created correctly, this list will be in turn order. we want to keep it that way.
int gridx = 0;
int gridy = 0;
if (!disableable.isEmpty() || playersEnablementListing.containsValue(Boolean.FALSE)) {
final JLabel enableLabel = new JLabel("Use");
enableLabel.setForeground(Color.black);
this.add(enableLabel, new GridBagConstraints(gridx++, gridy, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
}
final JLabel nameLabel = new JLabel("Name");
nameLabel.setForeground(Color.black);
this.add(nameLabel, new GridBagConstraints(gridx++, gridy, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
final JLabel typeLabel = new JLabel("Type");
typeLabel.setForeground(Color.black);
this.add(typeLabel, new GridBagConstraints(gridx++, gridy, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
final JLabel allianceLabel = new JLabel("Alliance");
allianceLabel.setForeground(Color.black);
this.add(allianceLabel, new GridBagConstraints(gridx++, gridy, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 7, 5, 5), 0, 0));
for (final String playerName : playerNames) {
final LocalPlayerComboBoxSelector selector =
new LocalPlayerComboBoxSelector(playerName, reloadSelections, disableable, playersEnablementListing,
data.getAllianceTracker().getAlliancesPlayerIsIn(data.getPlayerList().getPlayerID(playerName)),
playerTypes, this);
m_playerTypes.add(selector);
selector.layout(++gridy, this);
}
validate();
invalidate();
setWidgetActivation();
}
private void setupListeners() {
m_gameSelectorModel.addObserver(this);
}
@Override
public boolean isMetaSetupPanelInstance() {
return false;
}
@Override
public void setWidgetActivation() {}
@Override
public boolean canGameStart() {
if (m_gameSelectorModel.getGameData() == null) {
return false;
}
// make sure at least 1 player is enabled
for (final LocalPlayerComboBoxSelector player : m_playerTypes) {
if (player.isPlayerEnabled()) {
return true;
}
}
return false;
}
@Override
public void postStartGame() {
final GameData data = m_gameSelectorModel.getGameData();
data.getProperties().set(PBEMMessagePoster.PBEM_GAME_PROP_NAME, false);
}
@Override
public void shutDown() {
m_gameSelectorModel.deleteObserver(this);
}
@Override
public void cancel() {
m_gameSelectorModel.deleteObserver(this);
}
@Override
public void update(final Observable o, final Object arg) {
if (!SwingUtilities.isEventDispatchThread()) {
SwingUtilities.invokeLater(() -> layoutComponents());
return;
}
layoutComponents();
}
public String getPlayerType(final String playerName) {
for (final LocalPlayerComboBoxSelector item : m_playerTypes) {
if (item.getPlayerName().equals(playerName)) {
return item.getPlayerType();
}
}
throw new IllegalStateException("No player found:" + playerName);
}
@Override
public ILauncher getLauncher() {
final IRandomSource randomSource = new PlainRandomSource();
final Map<String, String> playerTypes = new HashMap<>();
final Map<String, Boolean> playersEnabled = new HashMap<>();
for (final LocalPlayerComboBoxSelector player : m_playerTypes) {
playerTypes.put(player.getPlayerName(), player.getPlayerType());
playersEnabled.put(player.getPlayerName(), player.isPlayerEnabled());
}
// we don't need the playerToNode list, the disable-able players, or the alliances
// list, for a local game
final PlayerListing pl =
new PlayerListing(null, playersEnabled, playerTypes, m_gameSelectorModel.getGameData().getGameVersion(),
m_gameSelectorModel.getGameName(), m_gameSelectorModel.getGameRound(), null, null);
final LocalLauncher launcher = new LocalLauncher(m_gameSelectorModel, randomSource, pl);
return launcher;
}
}
class LocalPlayerComboBoxSelector {
private final JCheckBox m_enabledCheckBox;
private final String m_playerName;
private final JComboBox<String> m_playerTypes;
private boolean m_enabled = true;
private final JLabel m_name;
private final JLabel m_alliances;
private final Collection<String> m_disableable;
private final String[] m_types;
private final SetupPanel m_parent;
LocalPlayerComboBoxSelector(final String playerName, final Map<String, String> reloadSelections,
final Collection<String> disableable, final HashMap<String, Boolean> playersEnablementListing,
final Collection<String> playerAlliances, final String[] types, final SetupPanel parent) {
m_playerName = playerName;
m_name = new JLabel(m_playerName + ":");
m_enabledCheckBox = new JCheckBox();
final ActionListener m_disablePlayerActionListener = new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
if (m_enabledCheckBox.isSelected()) {
m_enabled = true;
// the 1st in the list should be human
m_playerTypes.setSelectedItem(m_types[0]);
} else {
m_enabled = false;
// the 2nd in the list should be Weak AI
m_playerTypes.setSelectedItem(m_types[Math.max(0, Math.min(m_types.length - 1, 1))]);
}
setWidgetActivation();
}
};
m_enabledCheckBox.addActionListener(m_disablePlayerActionListener);
m_enabledCheckBox.setSelected(playersEnablementListing.get(playerName));
m_enabledCheckBox.setEnabled(disableable.contains(playerName));
m_disableable = disableable;
m_parent = parent;
m_types = types;
m_playerTypes = new JComboBox<>(types);
String previousSelection = reloadSelections.get(playerName);
if (previousSelection.equalsIgnoreCase("Client")) {
previousSelection = types[0];
}
if (!(previousSelection.equals("no_one")) && Arrays.asList(types).contains(previousSelection)) {
m_playerTypes.setSelectedItem(previousSelection);
} else if (m_playerName.startsWith("Neutral") || playerName.startsWith("AI")) {
// the 4th in the list should be Pro AI (Hard AI)
m_playerTypes.setSelectedItem(types[Math.max(0, Math.min(types.length - 1, 3))]);
}
// we do not set the default for the combobox because the default is the top item, which in this case is human
String m_playerAlliances;
if (playerAlliances.contains(playerName)) {
m_playerAlliances = "";
} else {
m_playerAlliances = playerAlliances.toString();
}
m_alliances = new JLabel(m_playerAlliances);
setWidgetActivation();
}
public void layout(final int row, final Container container) {
int gridx = 0;
if (!m_disableable.isEmpty()) {
container.add(m_enabledCheckBox, new GridBagConstraints(gridx++, row, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
}
container.add(m_name, new GridBagConstraints(gridx++, row, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
container.add(m_playerTypes, new GridBagConstraints(gridx++, row, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 5, 5, 0), 0, 0));
container.add(m_alliances, new GridBagConstraints(gridx++, row, 1, 1, 0, 0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(0, 7, 5, 5), 0, 0));
}
public String getPlayerName() {
return m_playerName;
}
public String getPlayerType() {
return (String) m_playerTypes.getSelectedItem();
}
public boolean isPlayerEnabled() {
return m_enabledCheckBox.isSelected();
}
private void setWidgetActivation() {
m_name.setEnabled(m_enabled);
m_alliances.setEnabled(m_enabled);
m_enabledCheckBox.setEnabled(m_disableable.contains(m_playerName));
m_parent.notifyObservers();
}
}