package games.strategy.triplea.ui;
import java.awt.event.ActionEvent;
import java.util.Collection;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.NamedAttachable;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.ProductionRule;
import games.strategy.engine.data.Territory;
import games.strategy.engine.data.Unit;
import games.strategy.engine.data.UnitType;
import games.strategy.triplea.Constants;
import games.strategy.triplea.TripleAUnit;
import games.strategy.triplea.attachments.RulesAttachment;
import games.strategy.triplea.delegate.Matches;
import games.strategy.triplea.formatter.MyFormatter;
import games.strategy.triplea.util.UnitSeperator;
import games.strategy.util.IntegerMap;
import games.strategy.util.Match;
public class PurchasePanel extends ActionPanel {
private static final long serialVersionUID = -6121756876868623355L;
private final JLabel actionLabel = new JLabel();
private IntegerMap<ProductionRule> m_purchase;
private boolean m_bid;
private final SimpleUnitPanel m_purchasedPreviousRoundsUnits;
private final JLabel m_purchasedPreviousRoundsLabel;
private final SimpleUnitPanel m_purhcasedUnits;
private final JLabel m_purchasedLabel = new JLabel();
private final JButton m_buyButton;
// if this is set Purchase will use the tabbedProductionPanel - this is modifyable through the View Menu
private static boolean m_tabbedProduction = true;
private static final String BUY = "Buy...";
private static final String CHANGE = "Change...";
/** Creates new PurchasePanel. */
public PurchasePanel(final GameData data, final MapPanel map) {
super(data, map);
m_purchasedPreviousRoundsUnits = new SimpleUnitPanel(map.getUIContext());
m_purhcasedUnits = new SimpleUnitPanel(map.getUIContext());
m_buyButton = new JButton(BUY);
m_buyButton.addActionListener(PURCHASE_ACTION);
m_purchasedPreviousRoundsLabel = new JLabel("Unplaced from previous rounds");
}
@Override
public void display(final PlayerID id) {
super.display(id);
m_purchase = new IntegerMap<>();
SwingUtilities.invokeLater(() -> {
removeAll();
actionLabel.setText(id.getName() + " production");
add(actionLabel);
m_buyButton.setText(BUY);
add(m_buyButton);
add(new JButton(DoneAction));
add(Box.createVerticalStrut(9));
m_purchasedLabel.setText("");
add(m_purchasedLabel);
add(Box.createVerticalStrut(4));
m_purhcasedUnits.setUnitsFromProductionRuleMap(new IntegerMap<>(), id, getData());
add(m_purhcasedUnits);
getData().acquireReadLock();
try {
m_purchasedPreviousRoundsUnits.setUnitsFromCategories(UnitSeperator.categorize(id.getUnits().getUnits()),
getData());
add(Box.createVerticalStrut(4));
if (!id.getUnits().isEmpty()) {
add(m_purchasedPreviousRoundsLabel);
}
add(m_purchasedPreviousRoundsUnits);
} finally {
getData().releaseReadLock();
}
add(Box.createVerticalGlue());
SwingUtilities.invokeLater(REFRESH);
});
}
private void refreshActionLabelText() {
SwingUtilities.invokeLater(
() -> actionLabel.setText(getCurrentPlayer().getName() + " production " + (m_bid ? " for bid" : "")));
}
public IntegerMap<ProductionRule> waitForPurchase(final boolean bid) {
m_bid = bid;
refreshActionLabelText();
// automatically "click" the buy button for us!
SwingUtilities.invokeLater(() -> PURCHASE_ACTION.actionPerformed(null));
waitForRelease();
return m_purchase;
}
private final AbstractAction PURCHASE_ACTION = new AbstractAction("Buy") {
private static final long serialVersionUID = -2931438906267249990L;
@Override
public void actionPerformed(final ActionEvent e) {
final PlayerID player = getCurrentPlayer();
final GameData data = getData();
if (isTabbedProduction()) {
m_purchase = TabbedProductionPanel.getProduction(player, (JFrame) getTopLevelAncestor(), data, m_bid,
m_purchase, getMap().getUIContext());
} else {
m_purchase = ProductionPanel.getProduction(player, (JFrame) getTopLevelAncestor(), data, m_bid, m_purchase,
getMap().getUIContext());
}
m_purhcasedUnits.setUnitsFromProductionRuleMap(m_purchase, player, data);
if (m_purchase.totalValues() == 0) {
m_purchasedLabel.setText("");
m_buyButton.setText(BUY);
} else {
m_buyButton.setText(CHANGE);
m_purchasedLabel.setText(totalUnitNumberPurchased(m_purchase)
+ MyFormatter.pluralize(" unit", totalUnitNumberPurchased(m_purchase)) + " to be produced:");
}
}
};
private static int totalUnitNumberPurchased(final IntegerMap<ProductionRule> purchase) {
int totalUnits = 0;
final Collection<ProductionRule> rules = purchase.keySet();
for (final ProductionRule current : rules) {
totalUnits += purchase.getInt(current) * current.getResults().totalValues();
}
return totalUnits;
}
private final Action DoneAction = new AbstractAction("Done") {
private static final long serialVersionUID = -209781523508962628L;
@Override
public void actionPerformed(final ActionEvent event) {
final boolean hasPurchased = m_purchase.totalValues() != 0;
if (!hasPurchased) {
final int rVal = JOptionPane.showConfirmDialog(JOptionPane.getFrameForComponent(PurchasePanel.this),
"Are you sure you dont want to buy anything?", "End Purchase", JOptionPane.YES_NO_OPTION);
if (rVal != JOptionPane.YES_OPTION) {
return;
}
}
// give a warning if the
// player tries to produce too much
if (isWW2V2() || isRestrictedPurchase()) {
int totalProd = 0;
getData().acquireReadLock();
try {
for (final Territory t : Match.getMatches(getData().getMap().getTerritories(),
Matches.territoryHasOwnedIsFactoryOrCanProduceUnits(getCurrentPlayer()))) {
totalProd += TripleAUnit.getProductionPotentialOfTerritory(t.getUnits().getUnits(), t, getCurrentPlayer(),
getData(), true, true);
}
} finally {
getData().releaseReadLock();
}
// sum production for all units except factories
int totalProduced = 0;
for (final ProductionRule rule : m_purchase.keySet()) {
final NamedAttachable resourceOrUnit = rule.getResults().keySet().iterator().next();
if (resourceOrUnit instanceof UnitType) {
final UnitType type = (UnitType) resourceOrUnit;
if (!Matches.UnitTypeIsConstruction.match(type)) {
totalProduced += m_purchase.getInt(rule) * rule.getResults().totalValues();
}
}
}
final PlayerID player = getCurrentPlayer();
final Collection<Unit> unitsNeedingFactory =
Match.getMatches(player.getUnits().getUnits(), Matches.UnitIsNotConstruction);
if (!m_bid && totalProduced + unitsNeedingFactory.size() > totalProd && !isUnlimitedProduction(player)) {
final String text = "You have purchased " + (totalProduced + unitsNeedingFactory.size())
+ " units, and can only place " + totalProd + " of them. Continue with purchase?";
final int rVal = JOptionPane.showConfirmDialog(JOptionPane.getFrameForComponent(PurchasePanel.this), text,
"End Purchase", JOptionPane.YES_NO_OPTION);
if (rVal != JOptionPane.YES_OPTION) {
return;
}
}
}
release();
}
};
private static boolean isUnlimitedProduction(final PlayerID player) {
final RulesAttachment ra = (RulesAttachment) player.getAttachment(Constants.RULES_ATTACHMENT_NAME);
if (ra == null) {
return false;
}
return ra.getUnlimitedProduction();
}
@Override
public String toString() {
return "PurchasePanel";
}
public static void setTabbedProduction(final boolean tabbedProduction) {
m_tabbedProduction = tabbedProduction;
}
public static boolean isTabbedProduction() {
return m_tabbedProduction;
}
}