package crazypants.enderio.conduit.gas;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import mekanism.api.gas.IGasHandler;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import crazypants.enderio.conduit.AbstractConduit;
import crazypants.enderio.conduit.ConduitUtil;
import crazypants.enderio.conduit.ConnectionMode;
import crazypants.enderio.conduit.IConduit;
import crazypants.enderio.conduit.IConduitBundle;
import crazypants.enderio.machine.RedstoneControlMode;
import crazypants.enderio.machine.reservoir.TileReservoir;
import crazypants.util.BlockCoord;
import crazypants.util.DyeColor;
public abstract class AbstractGasConduit extends AbstractConduit implements IGasConduit {
protected final EnumMap<ForgeDirection, RedstoneControlMode> extractionModes = new EnumMap<ForgeDirection, RedstoneControlMode>(ForgeDirection.class);
protected final EnumMap<ForgeDirection, DyeColor> extractionColors = new EnumMap<ForgeDirection, DyeColor>(ForgeDirection.class);
protected final Map<ForgeDirection, Integer> externalRedstoneSignals = new HashMap<ForgeDirection, Integer>();
protected boolean redstoneStateDirty = true;
public IGasHandler getExternalHandler(ForgeDirection direction) {
IGasHandler con = GasUtil.getExternalGasHandler(getBundle().getWorld(), getLocation().getLocation(direction));
return (con != null && !(con instanceof IConduitBundle)) ? con : null;
}
public IGasHandler getTankContainer(BlockCoord bc) {
return GasUtil.getGasHandler(getBundle().getWorld(), bc);
}
@Override
public boolean canConnectToExternal(ForgeDirection direction, boolean ignoreDisabled) {
IGasHandler h = getExternalHandler(direction);
if(h == null) {
return false;
}
return true;
}
@Override
public Class<? extends IConduit> getBaseConduitType() {
return IGasConduit.class;
}
@Override
public boolean onNeighborBlockChange(Block blockId) {
redstoneStateDirty = true;
return super.onNeighborBlockChange(blockId);
}
@Override
public void setExtractionRedstoneMode(RedstoneControlMode mode, ForgeDirection dir) {
extractionModes.put(dir, mode);
redstoneStateDirty = true;
}
@Override
public RedstoneControlMode getExtractionRedstoneMode(ForgeDirection dir) {
RedstoneControlMode res = extractionModes.get(dir);
if(res == null) {
res = RedstoneControlMode.ON;
}
return res;
}
@Override
public void setExtractionSignalColor(ForgeDirection dir, DyeColor col) {
extractionColors.put(dir, col);
}
@Override
public DyeColor getExtractionSignalColor(ForgeDirection dir) {
DyeColor result = extractionColors.get(dir);
if(result == null) {
return DyeColor.RED;
}
return result;
}
@Override
public boolean canOutputToDir(ForgeDirection dir) {
if(isExtractingFromDir(dir) || getConnectionMode(dir) == ConnectionMode.DISABLED) {
return false;
}
if(conduitConnections.contains(dir)) {
return true;
}
if(!externalConnections.contains(dir)) {
return false;
}
IGasHandler ext = getExternalHandler(dir);
if(ext instanceof TileReservoir) { // dont push to an auto ejecting
// resevoir or we loop
TileReservoir tr = (TileReservoir) ext;
return !tr.isMultiblock() || !tr.isAutoEject();
}
return true;
}
protected boolean autoExtractForDir(ForgeDirection dir) {
if(!isExtractingFromDir(dir)) {
return false;
}
RedstoneControlMode mode = getExtractionRedstoneMode(dir);
if(mode == RedstoneControlMode.IGNORE) {
return true;
}
if(mode == RedstoneControlMode.NEVER) {
return false;
}
if(redstoneStateDirty) {
externalRedstoneSignals.clear();
redstoneStateDirty = false;
}
DyeColor col = getExtractionSignalColor(dir);
int signal = ConduitUtil.getInternalSignalForColor(getBundle(), col);
if(mode.isConditionMet(mode, signal) && mode != RedstoneControlMode.OFF) {
return true;
}
return isConditionMetByExternalSignal(dir, mode, col);
}
private boolean isConditionMetByExternalSignal(ForgeDirection dir, RedstoneControlMode mode, DyeColor col) {
int externalSignal = 0;
if(col == DyeColor.RED) {
Integer val = externalRedstoneSignals.get(dir);
if(val == null) {
TileEntity te = getBundle().getEntity();
externalSignal = te.getWorldObj().getStrongestIndirectPower(te.xCoord, te.yCoord, te.zCoord);
externalRedstoneSignals.put(dir, externalSignal);
} else {
externalSignal = val;
}
}
return mode.isConditionMet(mode, externalSignal);
}
@Override
public boolean isExtractingFromDir(ForgeDirection dir) {
return getConnectionMode(dir) == ConnectionMode.INPUT;
}
@Override
public void writeToNBT(NBTTagCompound nbtRoot) {
super.writeToNBT(nbtRoot);
for (Entry<ForgeDirection, RedstoneControlMode> entry : extractionModes.entrySet()) {
if(entry.getValue() != null) {
short ord = (short) entry.getValue().ordinal();
nbtRoot.setShort("extRM." + entry.getKey().name(), ord);
}
}
for (Entry<ForgeDirection, DyeColor> entry : extractionColors.entrySet()) {
if(entry.getValue() != null) {
short ord = (short) entry.getValue().ordinal();
nbtRoot.setShort("extSC." + entry.getKey().name(), ord);
}
}
}
@Override
public void readFromNBT(NBTTagCompound nbtRoot, short nbtVersion) {
super.readFromNBT(nbtRoot, nbtVersion);
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
String key = "extRM." + dir.name();
if(nbtRoot.hasKey(key)) {
short ord = nbtRoot.getShort(key);
if(ord >= 0 && ord < RedstoneControlMode.values().length) {
extractionModes.put(dir, RedstoneControlMode.values()[ord]);
}
}
key = "extSC." + dir.name();
if(nbtRoot.hasKey(key)) {
short ord = nbtRoot.getShort(key);
if(ord >= 0 && ord < DyeColor.values().length) {
extractionColors.put(dir, DyeColor.values()[ord]);
}
}
}
}
}