package erogenousbeef.bigreactors.client.gui;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.inventory.Container;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ResourceLocation;
import erogenousbeef.bigreactors.common.BigReactors;
import erogenousbeef.bigreactors.common.multiblock.block.BlockReactorPart;
import erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorControlRod;
import erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorRedNetPort;
import erogenousbeef.bigreactors.common.multiblock.tileentity.TileEntityReactorRedNetPort.CircuitType;
import erogenousbeef.bigreactors.gui.IBeefGuiControl;
import erogenousbeef.bigreactors.gui.controls.BeefGuiLabel;
import erogenousbeef.bigreactors.gui.controls.BeefGuiRedNetChannelSelector;
import erogenousbeef.bigreactors.gui.controls.grab.BeefGuiGrabSource;
import erogenousbeef.bigreactors.gui.controls.grab.RedNetConfigGrabTarget;
import erogenousbeef.bigreactors.gui.controls.grab.RedNetConfigGrabbable;
import erogenousbeef.bigreactors.net.CommonPacketHandler;
import erogenousbeef.bigreactors.net.helpers.RedNetChange;
import erogenousbeef.bigreactors.net.message.ReactorRedNetPortChangeMessage;
import erogenousbeef.core.common.CoordTriplet;
public class GuiReactorRedNetPort extends BeefGuiBase {
protected static final int numChannels = 16;
TileEntityReactorRedNetPort port;
BeefGuiLabel titleString;
BeefGuiLabel settingsString;
BeefGuiLabel subSettingString;
BeefGuiLabel subSettingValueString;
private GuiButton commitBtn;
private GuiButton subSettingForwardBtn;
private GuiButton subSettingBackBtn;
private ResourceLocation _guiBackground;
protected static final String[] channelLabelStrings = new String[] {
"White", "Orange", "Magenta", "LightBlue", "Yellow", "Lime", "Pink", "Gray",
"LightGray", "Cyan", "Purple", "Blue", "Brown", "Green", "Red", "Black"
};
public static final String[] grabbableTooltips = {
"Input: Toggle reactor on/off",
"Input: Change control rod insertion",
"Input: Eject Waste",
"Output: Fuel Temp (C)",
"Output: Casing Temp (C)",
"Output: Fuel mix (% fuel, 0-100)",
"Output: Fuel amount",
"Output: Waste amount",
"Output: Energy amount (%)"
};
BeefGuiRedNetChannelSelector[] channelSelectors = new BeefGuiRedNetChannelSelector[numChannels];
RedNetConfigGrabTarget[] grabTargets = new RedNetConfigGrabTarget[numChannels];
private CoordTriplet[] subSettingCoords = new CoordTriplet[numChannels];
private boolean[] pulseActivated = new boolean[numChannels];
private int selectedChannel = 0;
public GuiReactorRedNetPort(Container container, TileEntityReactorRedNetPort redNetPort) {
super(container);
port = redNetPort;
xSize = 255;
ySize = 214;
_guiBackground = new ResourceLocation(BigReactors.GUI_DIRECTORY + "RedNetPort.png");
}
@Override
public ResourceLocation getGuiBackground() {
return _guiBackground;
}
@Override
public void initGui() {
super.initGui();
int leftX = guiLeft + 4;
int topY = guiTop + 4;
titleString = new BeefGuiLabel(this, "Reactor RedNet Port", leftX+2, topY+2);
settingsString = new BeefGuiLabel(this, "Settings", leftX+154, topY+2);
subSettingString = new BeefGuiLabel(this, "", leftX+154, topY+80);
subSettingValueString = new BeefGuiLabel(this, "", leftX+154, topY+94);
topY += titleString.getHeight() + 8;
selectedChannel = 0;
for(int i = 0; i < channelLabelStrings.length; i+=2) {
channelSelectors[i] = new BeefGuiRedNetChannelSelector(this, channelLabelStrings[i], i, leftX, topY, 60, 20);
grabTargets[i] = new RedNetConfigGrabTarget(this, leftX + 42, topY+2, port, i);
if(i == 0) {
channelSelectors[i].setSelected(true);
}
leftX += 74;
channelSelectors[i + 1] = new BeefGuiRedNetChannelSelector(this, channelLabelStrings[i+1], i+1, leftX, topY, 60, 20);
grabTargets[i + 1] = new RedNetConfigGrabTarget(this, leftX + 42, topY+2, port, i + 1);
topY += 24;
leftX = guiLeft + 4;
registerControl(channelSelectors[i]);
registerControl(channelSelectors[i+1]);
registerControl(grabTargets[i]);
registerControl(grabTargets[i+1]);
}
TileEntityReactorRedNetPort.CircuitType[] circuitTypes = TileEntityReactorRedNetPort.CircuitType.values();
BlockReactorPart reactorPartBlock = (BlockReactorPart)BigReactors.blockReactorPart;
RedNetConfigGrabbable[] grabbables = new RedNetConfigGrabbable[circuitTypes.length - 1];
topY = guiTop + 21;
leftX = guiLeft + 156;
for(int i = 1; i < circuitTypes.length; i++) {
grabbables[i-1] = new RedNetConfigGrabbable(grabbableTooltips[i-1], reactorPartBlock.getRedNetConfigIcon(circuitTypes[i]), circuitTypes[i]);
BeefGuiGrabSource source = new BeefGuiGrabSource(this, leftX, topY, grabbables[i - 1]);
registerControl(source);
leftX += 20;
if(leftX >= guiLeft + 230) {
leftX = guiLeft + 156;
topY += 20;
}
}
registerControl(titleString);
registerControl(settingsString);
registerControl(subSettingString);
registerControl(subSettingValueString);
commitBtn = new GuiButton(0, guiLeft + 190, guiTop + 190, 56, 20, "Commit");
commitBtn.enabled = false;
this.subSettingForwardBtn = new GuiButton(1, guiLeft + 178, guiTop + 114, 20, 20, ">");
this.subSettingBackBtn = new GuiButton(2, guiLeft + 154, guiTop + 114, 20, 20, "<");
this.subSettingForwardBtn.visible = false;
this.subSettingBackBtn.visible = false;
this.buttonList.add(commitBtn);
this.buttonList.add(subSettingForwardBtn);
this.buttonList.add(subSettingBackBtn);
// Populate all the channels with existing settings
TileEntityReactorRedNetPort.CircuitType currentCircuitType;
for(int i = 0; i < TileEntityReactorRedNetPort.numChannels; i++) {
currentCircuitType = port.getChannelCircuitType(i);
pulseActivated[i] = port.isInputActivatedOnPulse(i);
if(currentCircuitType == TileEntityReactorRedNetPort.CircuitType.DISABLED) {
grabTargets[i].setSlotContents(null);
}
else {
grabTargets[i].setSlotContents( grabbables[currentCircuitType.ordinal() - 1 ]);
}
}
for(int i = 0; i < subSettingCoords.length; i++) {
subSettingCoords[i] = port.getMappedCoord(i);
}
updateSubSettingValueText();
}
@Override
public void updateScreen() {
super.updateScreen();
boolean hasChanges = false;
boolean invalidSetting = false;
for(RedNetConfigGrabTarget target : grabTargets) {
if(target.hasChanged()) {
hasChanges = true;
}
}
// See if any subsettings changed
for(int i = 0; i < subSettingCoords.length; i++) {
if(hasSubSettingChanged(i)) {
hasChanges = true;
break;
}
}
for(int i = 0; i < numChannels; i++) {
if(port.isInputActivatedOnPulse(i) != pulseActivated[i]) {
hasChanges = true;
break;
}
}
commitBtn.enabled = hasChanges && !invalidSetting;
}
protected boolean hasSubSettingChanged(int idx) {
if(subSettingCoords[idx] == null) {
if(port.getMappedCoord(idx) != null)
{
return true;
}
}
else if(port.getMappedCoord(idx) == null) {
return true;
}
else if(!subSettingCoords[idx].equals(port.getMappedCoord(idx))) {
return true;
}
return false;
}
protected boolean hasSettingChanged(int idx) {
return grabTargets[idx].hasChanged() || hasSubSettingChanged(idx) || (port.isInputActivatedOnPulse(idx) != pulseActivated[idx]);
}
@Override
protected void actionPerformed(GuiButton button) {
if(button.id == 0) {
RedNetChange[] packetData = getUpdatePacketData();
if(packetData == null) { return; }
CommonPacketHandler.INSTANCE.sendToServer(new ReactorRedNetPortChangeMessage(port, packetData));
}
if(button.id == 1 || button.id == 2) {
changeSubSetting(button.id == 1);
}
}
private RedNetChange[] getUpdatePacketData() {
List<RedNetChange> packetData = new LinkedList<RedNetChange>();
for(int i = 0; i < TileEntityReactorRedNetPort.numChannels; i++) {
if(hasSettingChanged(i)) {
CircuitType circuitType = grabTargets[i].getCircuitType();
RedNetChange change = new RedNetChange(i, circuitType, pulseActivated[i], subSettingCoords[i]);
packetData.add(change);
}
}
if(packetData.size() < 1) { return null; }
RedNetChange[] changes = new RedNetChange[packetData.size()];
changes = packetData.toArray(changes);
return changes;
}
@Override
public void onControlClicked(IBeefGuiControl clickedControl) {
if(clickedControl instanceof BeefGuiRedNetChannelSelector) {
// Set all selectors to unselected, except the one we clicked
// Also change the subsetting selectors, in case those are visible
for(IBeefGuiControl control : controls) {
if(control instanceof BeefGuiRedNetChannelSelector) {
BeefGuiRedNetChannelSelector selector = (BeefGuiRedNetChannelSelector)control;
boolean wasSelected = selector.isSelected();
selector.setSelected(control == clickedControl);
if(control == clickedControl) {
this.selectedChannel = selector.getChannel();
}
onChannelChanged(selector.getChannel());
}
}
}
}
public void onChannelChanged(int changedChannel) {
if(this.selectedChannel != changedChannel) { return; }
CircuitType currentCircuitType = grabTargets[selectedChannel].getCircuitType();
if(CircuitType.hasCoordinate(currentCircuitType)) {
subSettingString.setLabelText("Control Rod: ");
subSettingForwardBtn.visible = true;
subSettingBackBtn.visible = true;
}
else if(TileEntityReactorRedNetPort.isInput(currentCircuitType) && CircuitType.canBeToggledBetweenPulseAndNormal(currentCircuitType)) {
subSettingString.setLabelText("Activates On:");
subSettingForwardBtn.visible = true;
subSettingBackBtn.visible = true;
}
else if(currentCircuitType == CircuitType.inputEjectWaste) {
subSettingString.setLabelText("Activates On:");
subSettingForwardBtn.visible = false;
subSettingBackBtn.visible = false;
}
else {
subSettingString.setLabelText("");
subSettingForwardBtn.visible = false;
subSettingBackBtn.visible = false;
}
updateSubSettingValueText();
}
private String getControlRodLabelFromLocation(CircuitType circuitType, CoordTriplet location) {
if(location == null) {
return "-- ALL --";
}
else {
TileEntity te = port.getWorldObj().getTileEntity(location.x, location.y, location.z);
if( te instanceof TileEntityReactorControlRod ) {
TileEntityReactorControlRod rod = (TileEntityReactorControlRod)te;
if( rod.getName().equals("")) {
return location.toString();
}
else {
return rod.getName();
}
}
else {
return "INVALID: " + location.toString();
}
}
}
private void changeSubSetting(boolean forward) {
CircuitType circuitType = grabTargets[selectedChannel].getCircuitType();
if( CircuitType.hasCoordinate(circuitType) ) {
// Select a new control rod
CoordTriplet[] controlRodLocations = port.getReactorController().getControlRodLocations();
int newIdx = 0;
// Locate current idx; will be -1 if not found, which is expected.
int oldIdx = Arrays.asList(controlRodLocations).indexOf( subSettingCoords[selectedChannel] );
if(forward) {
newIdx = oldIdx + 1;
}
else {
if(oldIdx == -1) {
newIdx = controlRodLocations.length - 1;
}
else {
newIdx = oldIdx - 1;
}
}
if(newIdx < 0 || newIdx >= controlRodLocations.length) {
subSettingCoords[selectedChannel] = null;
}
else {
subSettingCoords[selectedChannel] = controlRodLocations[newIdx];
}
}
else if( CircuitType.canBeToggledBetweenPulseAndNormal(circuitType) ) {
pulseActivated[selectedChannel] = !pulseActivated[selectedChannel];
}
updateSubSettingValueText();
}
private void updateSubSettingValueText() {
subSettingValueString.setLabelTooltip("");
CircuitType circuitType = grabTargets[selectedChannel].getCircuitType();
if( CircuitType.hasCoordinate(circuitType) ) {
subSettingValueString.setLabelText( getControlRodLabelFromLocation(circuitType, subSettingCoords[selectedChannel]) );
}
else if(TileEntityReactorRedNetPort.isInput(circuitType) && CircuitType.canBeToggledBetweenPulseAndNormal(circuitType)) {
subSettingValueString.setLabelText(pulseActivated[selectedChannel]?"Pulse":"Level");
}
else if(circuitType == CircuitType.inputEjectWaste) {
subSettingValueString.setLabelText("Pulse");
}
else {
subSettingValueString.setLabelText("");
}
}
}