package games.strategy.triplea.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import games.strategy.engine.data.PlayerID;
import games.strategy.engine.data.Unit;
import games.strategy.engine.data.UnitType;
import games.strategy.triplea.TripleAUnit;
import games.strategy.triplea.attachments.UnitAttachment;
import games.strategy.triplea.attachments.UnitTypeComparator;
import games.strategy.triplea.delegate.Matches;
import games.strategy.util.Util;
public class UnitCategory implements Comparable<Object> {
private final UnitType m_type;
// Collection of UnitOwners, the type of our dependents, not the dependents
private Collection<UnitOwner> m_dependents;
// movement of the units
private final int m_movement;
// movement of the units
private final int m_transportCost;
// movement of the units
// private final Territory m_originatingTerr;
private final PlayerID m_owner;
// the units in the category, may be duplicates.
private final List<Unit> m_units = new ArrayList<>();
private int m_damaged = 0;
private int m_bombingDamage = 0;
private boolean m_disabled = false;
public UnitCategory(final Unit unit) {
final TripleAUnit taUnit = (TripleAUnit) unit;
m_type = taUnit.getType();
m_owner = taUnit.getOwner();
m_movement = -1;
m_transportCost = -1;
m_damaged = taUnit.getHits();
m_bombingDamage = taUnit.getUnitDamage();
m_disabled = Matches.UnitIsDisabled.match(unit);
m_dependents = Collections.emptyList();
}
public UnitCategory(final Unit unit, final Collection<Unit> dependents, final int movement, final int transportCost) {
this(unit, dependents, movement, 0, 0, false, transportCost);
}
public UnitCategory(final UnitType type, final PlayerID owner) {
m_type = type;
m_dependents = Collections.emptyList();
m_movement = -1;
m_transportCost = -1;
m_owner = owner;
}
public UnitCategory(final Unit unit, final Collection<Unit> dependents, final int movement, final int damaged,
final int bombingDamage, final boolean disabled, final int transportCost) {
m_type = unit.getType();
m_movement = movement;
m_transportCost = transportCost;
m_owner = unit.getOwner();
m_damaged = damaged;
m_bombingDamage = bombingDamage;
m_disabled = disabled;
m_units.add(unit);
createDependents(dependents);
}
public int getDamaged() {
return m_damaged;
}
public int getBombingDamage() {
return m_bombingDamage;
}
public boolean hasDamageOrBombingUnitDamage() {
return m_damaged > 0 || m_bombingDamage > 0;
}
public boolean getDisabled() {
return m_disabled;
}
public int getHitPoints() {
return UnitAttachment.get(m_type).getHitPoints();
}
private void createDependents(final Collection<Unit> dependents) {
m_dependents = new ArrayList<>();
if (dependents == null) {
return;
}
for (final Unit current : dependents) {
m_dependents.add(new UnitOwner(current));
}
}
@Override
public boolean equals(final Object o) {
if (o == null) {
return false;
}
if (!(o instanceof UnitCategory)) {
return false;
}
final UnitCategory other = (UnitCategory) o;
// equality of categories does not compare the number
// of units in the category, so don't compare on m_units
final boolean equalsIgnoreDamaged = equalsIgnoreDamagedAndBombingDamageAndDisabled(other);
// return equalsIgnoreDamaged && other.m_damaged == this.m_damaged;
return equalsIgnoreDamaged && other.m_damaged == this.m_damaged && other.m_bombingDamage == this.m_bombingDamage
&& other.m_disabled == this.m_disabled;
}
public boolean equalsIgnoreDamagedAndBombingDamageAndDisabled(final UnitCategory other) {
final boolean equalsIgnoreDamaged = other.m_type.equals(this.m_type) && other.m_movement == this.m_movement
&& other.m_owner.equals(this.m_owner) && Util.equals(this.m_dependents, other.m_dependents);
return equalsIgnoreDamaged;
}
public boolean equalsIgnoreMovement(final UnitCategory other) {
final boolean equalsIgnoreMovement = other.m_type.equals(this.m_type) && other.m_owner.equals(this.m_owner)
&& other.m_damaged == this.m_damaged && other.m_bombingDamage == this.m_bombingDamage
&& other.m_disabled == this.m_disabled && Util.equals(this.m_dependents, other.m_dependents);
return equalsIgnoreMovement;
}
public boolean equalsIgnoreDependents(final UnitCategory other) {
final boolean equalsIgnoreDependents = other.m_type.equals(this.m_type) && other.m_owner.equals(this.m_owner)
&& other.m_movement == this.m_movement && other.m_damaged == this.m_damaged
&& other.m_bombingDamage == this.m_bombingDamage && other.m_disabled == this.m_disabled;
return equalsIgnoreDependents;
}
@Override
public int hashCode() {
return m_type.hashCode() | m_owner.hashCode();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
sb.append("Entry type:").append(m_type.getName()).append(" owner:").append(m_owner.getName()).append(" damaged:")
.append(m_damaged).append(" bombingUnitDamage:").append(m_bombingDamage).append(" disabled:").append(m_disabled)
.append(" dependents:").append(m_dependents).append(" movement:").append(m_movement);
return sb.toString();
}
/**
* Collection of UnitOwners, the type of our dependents, not the dependents.
*/
public Collection<UnitOwner> getDependents() {
return m_dependents;
}
public List<Unit> getUnits() {
return m_units;
}
public int getMovement() {
return m_movement;
}
public int getTransportCost() {
return m_transportCost;
}
public PlayerID getOwner() {
return m_owner;
}
public void addUnit(final Unit unit) {
m_units.add(unit);
}
void removeUnit(final Unit unit) {
m_units.remove(unit);
}
public UnitType getType() {
return m_type;
}
@Override
public int compareTo(final Object o) {
if (o == null) {
return -1;
}
final UnitCategory other = (UnitCategory) o;
if (!other.m_owner.equals(this.m_owner)) {
return this.m_owner.getName().compareTo(other.m_owner.getName());
}
final int typeCompare = new UnitTypeComparator().compare(this.getType(), other.getType());
if (typeCompare != 0) {
return typeCompare;
}
if (m_movement != other.m_movement) {
return m_movement - other.m_movement;
}
if (!Util.equals(this.m_dependents, other.m_dependents)) {
return m_dependents.toString().compareTo(other.m_dependents.toString());
}
if (this.m_damaged != other.m_damaged) {
return this.m_damaged - other.m_damaged;
}
if (this.m_bombingDamage != other.m_bombingDamage) {
return this.m_bombingDamage - other.m_bombingDamage;
}
if (this.m_disabled != other.m_disabled) {
if (m_disabled) {
return 1;
}
return -1;
}
return 0;
}
}