package games.strategy.triplea.attachments;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import games.strategy.engine.data.Attachable;
import games.strategy.engine.data.GameData;
import games.strategy.engine.data.GameParseException;
import games.strategy.engine.data.IAttachment;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.annotations.GameProperty;
import games.strategy.triplea.Constants;
import games.strategy.triplea.MapSupport;
import games.strategy.triplea.delegate.Matches;
import games.strategy.util.CompositeMatchAnd;
import games.strategy.util.Match;
/**
* An attachment, attached to a player that will describe which political
* actions a player may take.
*/
@MapSupport
public class PoliticalActionAttachment extends AbstractUserActionAttachment {
private static final long serialVersionUID = 4392770599777282477L;
public PoliticalActionAttachment(final String name, final Attachable attachable, final GameData gameData) {
super(name, attachable, gameData);
}
public static Collection<PoliticalActionAttachment> getPoliticalActionAttachments(final PlayerID player) {
final ArrayList<PoliticalActionAttachment> returnList = new ArrayList<>();
final Map<String, IAttachment> map = player.getAttachments();
final Iterator<String> iter = map.keySet().iterator();
while (iter.hasNext()) {
final IAttachment a = map.get(iter.next());
if (a.getName().startsWith(Constants.POLITICALACTION_ATTACHMENT_PREFIX)
&& a instanceof PoliticalActionAttachment) {
returnList.add((PoliticalActionAttachment) a);
}
}
return returnList;
}
public static PoliticalActionAttachment get(final PlayerID player, final String nameOfAttachment) {
return get(player, nameOfAttachment, null);
}
public static PoliticalActionAttachment get(final PlayerID player, final String nameOfAttachment,
final Collection<PlayerID> playersToSearch) {
PoliticalActionAttachment rVal = (PoliticalActionAttachment) player.getAttachment(nameOfAttachment);
if (rVal == null) {
if (playersToSearch == null) {
throw new IllegalStateException(
"PoliticalActionAttachment: No attachment for:" + player.getName() + " with name: " + nameOfAttachment);
} else {
for (final PlayerID otherPlayer : playersToSearch) {
if (otherPlayer == player) {
continue;
}
rVal = (PoliticalActionAttachment) otherPlayer.getAttachment(nameOfAttachment);
if (rVal != null) {
return rVal;
}
}
throw new IllegalStateException(
"PoliticalActionAttachment: No attachment for:" + player.getName() + " with name: " + nameOfAttachment);
}
}
return rVal;
}
// list of relationship changes to be performed if this action is performed sucessfully
private ArrayList<String> m_relationshipChange = new ArrayList<>();
/**
* Adds to, not sets. Anything that adds to instead of setting needs a clear function as well.
*/
@GameProperty(xmlProperty = true, gameProperty = true, adds = true)
public void setRelationshipChange(final String relChange) throws GameParseException {
final String[] s = relChange.split(":");
if (s.length != 3) {
throw new GameParseException("Invalid relationshipChange declaration: " + relChange
+ " \n Use: player1:player2:newRelation\n" + thisErrorMsg());
}
if (getData().getPlayerList().getPlayerID(s[0]) == null) {
throw new GameParseException("Invalid relationshipChange declaration: " + relChange + " \n player: " + s[0]
+ " unknown in: " + getName() + thisErrorMsg());
}
if (getData().getPlayerList().getPlayerID(s[1]) == null) {
throw new GameParseException("Invalid relationshipChange declaration: " + relChange + " \n player: " + s[1]
+ " unknown in: " + getName() + thisErrorMsg());
}
if (!Matches.isValidRelationshipName(getData()).match(s[2])) {
throw new GameParseException("Invalid relationshipChange declaration: " + relChange + " \n relationshipType: "
+ s[2] + " unknown in: " + getName() + thisErrorMsg());
}
m_relationshipChange.add(relChange);
}
@GameProperty(xmlProperty = true, gameProperty = true, adds = false)
public void setRelationshipChange(final ArrayList<String> value) {
m_relationshipChange = value;
}
public ArrayList<String> getRelationshipChange() {
return m_relationshipChange;
}
public void clearRelationshipChange() {
m_relationshipChange.clear();
}
public void resetRelationshipChange() {
m_relationshipChange = new ArrayList<>();
}
/**
* @return a set of all other players involved in this PoliticalAction.
*/
public Set<PlayerID> getOtherPlayers() {
final HashSet<PlayerID> otherPlayers = new HashSet<>();
for (final String relationshipChange : m_relationshipChange) {
final String[] s = relationshipChange.split(":");
otherPlayers.add(getData().getPlayerList().getPlayerID(s[0]));
otherPlayers.add(getData().getPlayerList().getPlayerID(s[1]));
}
otherPlayers.remove((getAttachedTo()));
return otherPlayers;
}
/**
* @return gets the valid actions for this player.
*/
public static Collection<PoliticalActionAttachment> getValidActions(final PlayerID player,
final HashMap<ICondition, Boolean> testedConditions, final GameData data) {
if (!games.strategy.triplea.Properties.getUsePolitics(data) || !player.amNotDeadYet(data)) {
return new ArrayList<>();
}
return Match.getMatches(getPoliticalActionAttachments(player),
new CompositeMatchAnd<>(
Matches.AbstractUserActionAttachmentCanBeAttempted(testedConditions),
Matches.politicalActionAffectsAtLeastOneAlivePlayer(player, data)));
}
@Override
public void validate(final GameData data) throws GameParseException {
super.validate(data);
if (m_relationshipChange.isEmpty()) {
throw new GameParseException("value: relationshipChange can't be empty" + thisErrorMsg());
}
}
}