package mekhq.gui.model;
import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.UUID;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import megamek.common.EntityWeightClass;
import megamek.common.Jumpship;
import megamek.common.SmallCraft;
import megamek.common.Tank;
import megamek.common.TargetRoll;
import megamek.common.UnitType;
import mekhq.IconPackage;
import mekhq.campaign.Campaign;
import mekhq.campaign.force.Force;
import mekhq.campaign.personnel.Person;
import mekhq.campaign.personnel.RetirementDefectionTracker;
import mekhq.campaign.unit.Unit;
import mekhq.gui.BasicInfo;
import mekhq.gui.dialog.RetirementDefectionDialog;
public class RetirementTableModel extends AbstractTableModel {
/**
*
*/
private static final long serialVersionUID = 7461821036790309952L;
public final static int COL_PERSON = 0;
public final static int COL_ASSIGN = 1;
public final static int COL_FORCE = 2;
public final static int COL_TARGET = 3;
public final static int COL_SHARES = 4;
public final static int COL_BONUS_COST = 5;
public final static int COL_PAY_BONUS = 6;
public final static int COL_MISC_MOD = 7;
public final static int COL_PAYOUT = 8;
public final static int COL_RECRUIT = 9;
public final static int COL_UNIT = 10;
public final static int N_COL = 11;
private final static String[] colNames = {
"Person", "Assignment", "Force", "Target",
"Shares", "Bonus Cost", "Pay Bonus", "Misc Modifier",
"Payout", "Recruit", "Unit"
};
private Campaign campaign;
private ArrayList<UUID> data;
private HashMap<UUID, TargetRoll> targets;
private HashMap<UUID, Boolean> payBonus;
private HashMap<UUID, Integer> miscMods;
private int generalMod;
private HashMap<UUID, UUID> unitAssignments;
private HashMap<UUID, Integer> altPayout;
boolean editPayout;
private DecimalFormat formatter;
public RetirementTableModel(Campaign c) {
this.campaign = c;
data = new ArrayList<UUID>();
payBonus = new HashMap<UUID, Boolean>();
miscMods = new HashMap<UUID, Integer>();
generalMod = 0;
unitAssignments = new HashMap<UUID, UUID>();
altPayout = new HashMap<UUID, Integer>();
editPayout = false;
formatter = new DecimalFormat();
}
public void setData(ArrayList<UUID> list,
HashMap<UUID, UUID> unitAssignments) {
this.unitAssignments = unitAssignments;
data = list;
fireTableDataChanged();
}
public void setData(HashMap<UUID, TargetRoll> targets) {
this.targets = targets;
data.clear();
for (UUID id : targets.keySet()) {
data.add(id);
payBonus.put(id, false);
miscMods.put(id, 0);
}
fireTableDataChanged();
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return N_COL;
}
@Override
public String getColumnName(int column) {
return colNames[column];
}
public int getColumnWidth(int c) {
switch(c) {
case COL_PERSON:
case COL_ASSIGN:
case COL_FORCE:
case COL_UNIT:
case COL_RECRUIT:
return 125;
case COL_BONUS_COST:
case COL_PAYOUT:
return 70;
case COL_TARGET:
case COL_SHARES:
case COL_MISC_MOD:
return 50;
case COL_PAY_BONUS:
default:
return 20;
}
}
public int getAlignment(int col) {
switch(col) {
case COL_PERSON:
case COL_ASSIGN:
case COL_FORCE:
case COL_UNIT:
case COL_RECRUIT:
return SwingConstants.LEFT;
case COL_BONUS_COST:
case COL_PAYOUT:
return SwingConstants.RIGHT;
case COL_TARGET:
case COL_PAY_BONUS:
case COL_SHARES:
case COL_MISC_MOD:
default:
return SwingConstants.CENTER;
}
}
@Override
public boolean isCellEditable(int row, int col) {
switch (col) {
case COL_PAYOUT:
return editPayout;
case COL_PAY_BONUS:
case COL_MISC_MOD:
return true;
case COL_RECRUIT:
return campaign.getRetirementDefectionTracker().getPayout(data.get(row)).hasRecruit();
default:
return false;
}
}
@Override
public Class<?> getColumnClass(int col) {
Class<?> retVal = Object.class;
try {
retVal = getValueAt(0, col).getClass();
} catch (NullPointerException e) {
System.out.println("NPE at column " + colNames[col]);
}
return retVal;
}
@Override
public Object getValueAt(int row, int col) {
Person p;
if(data.isEmpty()) {
return "";
} else {
p = campaign.getPerson(data.get(row));
}
switch (col) {
case COL_PERSON:
return p.makeHTMLRank();
case COL_ASSIGN:
Unit u = campaign.getUnit(p.getUnitId());
if(null != u) {
String name = u.getName();
if(u.getEntity() instanceof Tank) {
if(u.isDriver(p)) {
name = name + " [Driver]";
} else {
name = name + " [Gunner]";
}
}
if(u.getEntity() instanceof SmallCraft || u.getEntity() instanceof Jumpship) {
if(u.isNavigator(p)) {
name = name + " [Navigator]";
}
else if(u.isDriver(p)) {
name = name + " [Pilot]";
}
else if(u.isGunner(p)) {
name = name + " [Gunner]";
} else {
name = name + " [Crew]";
}
}
return name;
}
//check for tech
if(!p.getTechUnitIDs().isEmpty()) {
if(p.getTechUnitIDs().size() == 1) {
u = campaign.getUnit(p.getTechUnitIDs().get(0));
if(null != u) {
return u.getName() + " (" + p.getMaintenanceTimeUsing() + "m)";
}
} else {
return "" + p.getTechUnitIDs().size() + " units (" + p.getMaintenanceTimeUsing() + "m)";
}
}
return "-";
case COL_FORCE:
Force force = campaign.getForceFor(p);
if(null != force) {
return force.getName();
} else {
return "None";
}
case COL_TARGET:
if (null == targets) {
return 0;
}
return targets.get(p.getId()).getValue() -
(payBonus.get(p.getId())?1:0) +
miscMods.get(p.getId()) + generalMod;
case COL_BONUS_COST:
return formatter.format(RetirementDefectionTracker.getBonusCost(p));
case COL_PAY_BONUS:
if (null == payBonus.get(p.getId())) {
return false;
}
return payBonus.get(p.getId());
case COL_MISC_MOD:
if (null == miscMods.get(p.getId())) {
return false;
}
return miscMods.get(p.getId());
case COL_SHARES:
return p.getNumShares(campaign.getCampaignOptions().getSharesForAll());
case COL_PAYOUT:
if (null == campaign.getRetirementDefectionTracker().getPayout(p.getId())) {
return "";
}
if (altPayout.keySet().contains(p.getId())) {
return formatter.format(altPayout.get(p.getId()));
}
long payout = campaign.getRetirementDefectionTracker().getPayout(p.getId()).getCbills();
/* If no unit is required as part of the payout, the unit is part or all of the
* final payout. If using the share system and tracking the original unit,
* the payout is also reduced by the value of the unit.
*/
if ((campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass() == 0 &&
null != unitAssignments.get(p.getId())) ||
(campaign.getCampaignOptions().getUseShareSystem() &&
campaign.getCampaignOptions().getTrackOriginalUnit() &&
p.getOriginalUnitId() == unitAssignments.get(p.getId()) &&
null != campaign.getUnit(unitAssignments.get(p.getId())))) {
payout -= campaign.getUnit(unitAssignments.get(p.getId())).getBuyCost();
}
if (null != unitAssignments.get(p.getId())) {
payout += RetirementDefectionDialog.getShortfallAdjustment(campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass(),
RetirementDefectionDialog.weightClassIndex(campaign.getUnit(unitAssignments.get(p.getId()))));
}
/* No payout if the pilot stole a unit */
if (campaign.getRetirementDefectionTracker().getPayout(p.getId()).hasStolenUnit() &&
null != unitAssignments.get(p.getId())) {
payout = 0;
}
return formatter.format(Math.max(payout, 0));
case COL_UNIT:
if (null == campaign.getRetirementDefectionTracker().getPayout(p.getId()) ||
null == unitAssignments) {
return "";
}
if (null != unitAssignments.get(p.getId())) {
return campaign.getUnit(unitAssignments.get(p.getId())).getName();
} else if (campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass() < EntityWeightClass.WEIGHT_LIGHT) {
return "";
} else {
return "Class " + campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass();
}
case COL_RECRUIT:
RetirementDefectionTracker.Payout pay =
campaign.getRetirementDefectionTracker().getPayout(data.get(row));
if (null == pay) {
return "";
}
if (pay.getDependents() > 0) {
return pay.getDependents() + " Dependents";
} else if (pay.hasRecruit()) {
return Person.getRoleDesc(pay.getRecruitType(),
campaign.getFaction().isClan());
} else if (pay.hasHeir()) {
return "Heir";
} else {
return "";
}
default:
return "?";
}
}
@Override
public void setValueAt(Object value, int row, int col) {
if (col == COL_PAYOUT) {
Number payout;
try {
payout = formatter.parse((String)value);
} catch (ParseException e1) {
return;
}
if (null != payout) {
altPayout.put(data.get(row), payout.intValue());
}
} else if (col == COL_PAY_BONUS) {
payBonus.put(data.get(row), (Boolean)value);
} else if (col == COL_MISC_MOD) {
miscMods.put(data.get(row), (Integer)value);
} else if (col == COL_UNIT) {
if (null != value) {
unitAssignments.put(getPerson(row).getId(), (UUID)value);
}
} else if (col == COL_RECRUIT) {
for (int i = 0; i < Person.T_NUM; i++) {
if (Person.getRoleDesc(i, campaign.getFaction().isClan()).equals((String)value)) {
campaign.getRetirementDefectionTracker().getPayout(data.get(row)).setRecruitType(i);
break;
}
}
}
fireTableDataChanged();
}
public Person getPerson(int row) {
return campaign.getPerson(data.get(row));
}
public boolean getPayBonus(UUID id) {
return payBonus.get(id);
}
public int getMiscModifier(UUID id) {
return miscMods.get(id);
}
public void setGeneralMod(int mod) {
generalMod = mod;
fireTableDataChanged();
}
public HashMap<UUID, Integer> getAltPayout() {
return altPayout;
}
public void setEditPayout(boolean edit) {
editPayout = edit;
}
public TableCellRenderer getRenderer(int col, IconPackage icons) {
if (col < COL_TARGET) {
return new VisualRenderer(icons);
} else return new TextRenderer();
}
public class TextRenderer extends DefaultTableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 770305943352316265L;
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
int actualRow = table.convertRowIndexToModel(row);
int actualCol = table.convertColumnIndexToModel(column);
Person p = getPerson(actualRow);
setHorizontalAlignment(getAlignment(actualCol));
setForeground(isSelected?Color.WHITE:Color.BLACK);
if (isSelected) {
setBackground(Color.DARK_GRAY);
} else if (null != campaign.getRetirementDefectionTracker().getPayout(p.getId()) &&
campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass() > 0) {
setBackground(Color.LIGHT_GRAY);
} else {
// tiger stripes
if ((row % 2) == 0) {
setBackground(new Color(220, 220, 220));
} else {
setBackground(Color.WHITE);
}
}
return this;
}
}
public class VisualRenderer extends BasicInfo implements TableCellRenderer {
/**
*
*/
private static final long serialVersionUID = 7261885081786958754L;
public VisualRenderer(IconPackage icons) {
super(icons);
}
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
Component c = this;
int actualCol = table.convertColumnIndexToModel(column);
int actualRow = table.convertRowIndexToModel(row);
Person p = getPerson(actualRow);
String color = "black";
if(isSelected) {
color = "white";
}
setText(getValueAt(actualRow, actualCol).toString(), color);
if (actualCol == COL_PERSON) {
setPortrait(p);
setText(p.getFullDesc(), color);
}
if(actualCol == COL_ASSIGN) {
Unit u = campaign.getUnit(p.getUnitId());
if(!p.getTechUnitIDs().isEmpty()) {
u = campaign.getUnit(p.getTechUnitIDs().get(0));
}
if(null != u) {
String desc = "<b>" + u.getName() + "</b><br>";
desc += u.getEntity().getWeightClassName();
if(!(u.getEntity() instanceof SmallCraft || u.getEntity() instanceof Jumpship)) {
desc += " " + UnitType.getTypeDisplayableName(UnitType.determineUnitTypeCode(u.getEntity()));
}
desc += "<br>" + u.getStatus() + "";
setText(desc, color);
Image mekImage = getImageFor(u);
if(null != mekImage) {
setImage(mekImage);
} else {
clearImage();
}
} else {
clearImage();
}
}
if(actualCol == COL_FORCE) {
Force force = campaign.getForceFor(p);
if(null != force) {
String desc = "<html><b>" + force.getName() + "</b>";
Force parent = force.getParentForce();
//cut off after three lines and don't include the top level
int lines = 1;
while(parent != null && null != parent.getParentForce() && lines < 4) {
desc += "<br>" + parent.getName();
lines++;
parent = parent.getParentForce();
}
desc += "</html>";
setText(desc, color);
Image forceImage = getImageFor(force);
if(null != forceImage) {
setImage(forceImage);
} else {
clearImage();
}
} else {
clearImage();
}
}
if (isSelected) {
c.setBackground(Color.DARK_GRAY);
} else if (null != campaign.getRetirementDefectionTracker().getPayout(p.getId()) &&
campaign.getRetirementDefectionTracker().getPayout(p.getId()).getWeightClass() > 0) {
c.setBackground(Color.LIGHT_GRAY);
} else {
// tiger stripes
if ((row % 2) == 0) {
c.setBackground(new Color(220, 220, 220));
} else {
c.setBackground(Color.WHITE);
}
}
return c;
}
}
}