package net.demilich.metastone.gui.sandboxmode;
import java.util.EnumMap;
import java.util.Map;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.CheckBox;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.util.Callback;
import net.demilich.metastone.game.Attribute;
import net.demilich.metastone.game.entities.Entity;
import net.demilich.metastone.game.utils.TagValueType;
import net.demilich.metastone.gui.common.IntegerTextField;
import net.demilich.metastone.utils.ICallback;
public class EntityEditor extends SandboxEditor {
private class PairKeyFactory implements Callback<TableColumn.CellDataFeatures<GameTagEntry, String>, ObservableValue<String>> {
@Override
public ObservableValue<String> call(TableColumn.CellDataFeatures<GameTagEntry, String> data) {
return new ReadOnlyObjectWrapper<>(data.getValue().getName());
}
}
private class PairValueCell extends TableCell<GameTagEntry, Object> {
@Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (item == null) {
return;
}
GameTagEntry entry = (GameTagEntry) item;
TagValueType tagValueType = entry.getValueType();
Attribute tag = entry.getTag();
if (tagValueType == TagValueType.INTEGER) {
IntegerTextField numericTextfield = getNumericTextField();
numericTextfield.setIntValue(entry.getValueInt());
numericTextfield.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, Number newValue) {
workingCopy.put(tag, numericTextfield.getIntValue());
}
});
setGraphic(numericTextfield);
setText(null);
} else if (tagValueType == TagValueType.BOOLEAN) {
CheckBox checkBox = new CheckBox();
checkBox.setSelected(entry.getValueBool());
checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldValue, Boolean newValue) {
if (checkBox.isSelected()) {
workingCopy.put(tag, 1);
} else {
workingCopy.remove(tag);
}
}
});
setGraphic(checkBox);
setText(null);
} else {
setGraphic(null);
setText(entry.getValue().toString());
}
}
}
private class PairValueFactory implements Callback<TableColumn.CellDataFeatures<GameTagEntry, Object>, ObservableValue<Object>> {
@Override
public ObservableValue<Object> call(TableColumn.CellDataFeatures<GameTagEntry, Object> data) {
return new ReadOnlyObjectWrapper<>(data.getValue());
}
}
private final Map<Attribute, Object> workingCopy = new EnumMap<Attribute, Object>(Attribute.class);
private final Entity entity;
@FXML
private TableView<GameTagEntry> propertiesTable;
@FXML
private TableColumn<GameTagEntry, String> nameColumn;
@FXML
private TableColumn<GameTagEntry, Object> valueColumn;
private final ICallback callback;
public EntityEditor(Entity entity, ICallback callback) {
super("EntityEditor.fxml");
this.entity = entity;
this.callback = callback;
setTitle("Edit " + entity.getName());
okButton.setOnAction(this::handleOkButton);
cancelButton.setOnAction(this::handleCancelButton);
nameColumn.setCellValueFactory(new PairKeyFactory());
valueColumn.setCellValueFactory(new PairValueFactory());
valueColumn.setCellFactory(new Callback<TableColumn<GameTagEntry, Object>, TableCell<GameTagEntry, Object>>() {
@Override
public TableCell<GameTagEntry, Object> call(TableColumn<GameTagEntry, Object> column) {
return new PairValueCell();
}
});
addTagsIfMissing(entity);
populateTable(entity);
}
private void addTagIfMissing(Entity entity, Attribute tag, Object defaultValue) {
if (entity.hasAttribute(tag)) {
return;
}
entity.setAttribute(tag, defaultValue);
}
private void addTagsIfMissing(Entity entity) {
switch (entity.getEntityType()) {
case CARD:
break;
case HERO:
addTagIfMissing(entity, Attribute.ARMOR, 0);
break;
case MINION:
addTagIfMissing(entity, Attribute.DIVINE_SHIELD, 0);
addTagIfMissing(entity, Attribute.WINDFURY, 0);
addTagIfMissing(entity, Attribute.FROZEN, 0);
addTagIfMissing(entity, Attribute.TEMPORARY_ATTACK_BONUS, 0);
addTagIfMissing(entity, Attribute.HP_BONUS, 0);
addTagIfMissing(entity, Attribute.ATTACK_BONUS, 0);
addTagIfMissing(entity, Attribute.CHARGE, 0);
addTagIfMissing(entity, Attribute.STEALTH, 0);
addTagIfMissing(entity, Attribute.TAUNT, 0);
break;
case WEAPON:
break;
default:
break;
}
}
private IntegerTextField getNumericTextField() {
IntegerTextField textField = new IntegerTextField(3);
textField.setMaxWidth(100);
return textField;
}
private void handleCancelButton(ActionEvent actionEvent) {
this.getScene().getWindow().hide();
}
private void handleOkButton(ActionEvent actionEvent) {
entity.getAttributes().clear();
for (Attribute tag : workingCopy.keySet()) {
entity.setAttribute(tag, workingCopy.get(tag));
}
this.getScene().getWindow().hide();
if (callback != null) {
callback.call(entity);
}
}
private void populateTable(Entity entity) {
Map<Attribute, Object> tags = entity.getAttributes();
ObservableList<GameTagEntry> data = FXCollections.observableArrayList();
for (Attribute tag : tags.keySet()) {
Object value = tags.get(tag);
workingCopy.put(tag, value);
GameTagEntry entry = new GameTagEntry(tag, value);
data.add(entry);
}
propertiesTable.getItems().setAll(data);
}
}