package mekanism.common.base;
import ic2.api.energy.EnergyNet;
import ic2.api.energy.tile.IEnergySink;
import ic2.api.energy.tile.IEnergyTile;
import mekanism.api.Coord4D;
import mekanism.api.MekanismConfig.general;
import mekanism.api.energy.IStrictEnergyAcceptor;
import mekanism.api.util.CapabilityUtils;
import mekanism.common.capabilities.Capabilities;
import mekanism.common.util.MekanismUtils;
import net.darkhax.tesla.api.ITeslaConsumer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import cofh.api.energy.IEnergyReceiver;
public abstract class EnergyAcceptorWrapper implements IStrictEnergyAcceptor
{
public Coord4D coord;
public static EnergyAcceptorWrapper get(TileEntity tileEntity, EnumFacing side)
{
if(tileEntity == null || tileEntity.getWorld() == null)
{
return null;
}
EnergyAcceptorWrapper wrapper = null;
if(CapabilityUtils.hasCapability(tileEntity, Capabilities.ENERGY_ACCEPTOR_CAPABILITY, null))
{
wrapper = new MekanismAcceptor(CapabilityUtils.getCapability(tileEntity, Capabilities.ENERGY_ACCEPTOR_CAPABILITY, side));
}
else if(MekanismUtils.useTesla() && CapabilityUtils.hasCapability(tileEntity, Capabilities.TESLA_CONSUMER_CAPABILITY, side))
{
wrapper = new TeslaAcceptor(CapabilityUtils.getCapability(tileEntity, Capabilities.TESLA_CONSUMER_CAPABILITY, side));
}
else if(MekanismUtils.useRF() && tileEntity instanceof IEnergyReceiver)
{
wrapper = new RFAcceptor((IEnergyReceiver)tileEntity);
}
else if(MekanismUtils.useIC2())
{
IEnergyTile tile = EnergyNet.instance.getSubTile(tileEntity.getWorld(), tileEntity.getPos());
if(tile instanceof IEnergySink)
{
wrapper = new IC2Acceptor((IEnergySink)tile);
}
}
if(wrapper != null)
{
wrapper.coord = Coord4D.get(tileEntity);
}
return wrapper;
}
public abstract boolean needsEnergy(EnumFacing side);
public static class MekanismAcceptor extends EnergyAcceptorWrapper
{
private IStrictEnergyAcceptor acceptor;
public MekanismAcceptor(IStrictEnergyAcceptor mekAcceptor)
{
acceptor = mekAcceptor;
}
@Override
public double transferEnergyToAcceptor(EnumFacing side, double amount)
{
return acceptor.transferEnergyToAcceptor(side, amount);
}
@Override
public boolean canReceiveEnergy(EnumFacing side)
{
return acceptor.canReceiveEnergy(side);
}
@Override
public double getEnergy()
{
return acceptor.getEnergy();
}
@Override
public void setEnergy(double energy)
{
acceptor.setEnergy(energy);
}
@Override
public double getMaxEnergy()
{
return acceptor.getMaxEnergy();
}
@Override
public boolean needsEnergy(EnumFacing side)
{
return acceptor.getMaxEnergy() - acceptor.getEnergy() > 0;
}
}
public static class RFAcceptor extends EnergyAcceptorWrapper
{
private IEnergyReceiver acceptor;
public RFAcceptor(IEnergyReceiver rfAcceptor)
{
acceptor = rfAcceptor;
}
@Override
public double transferEnergyToAcceptor(EnumFacing side, double amount)
{
return fromRF(acceptor.receiveEnergy(side, Math.min(Integer.MAX_VALUE, toRF(amount)), false));
}
@Override
public boolean canReceiveEnergy(EnumFacing side)
{
return acceptor.canConnectEnergy(side);
}
@Override
public double getEnergy()
{
return fromRF(acceptor.getEnergyStored(null));
}
@Override
public void setEnergy(double energy)
{
int rfToSet = toRF(energy);
int amountToReceive = rfToSet - acceptor.getEnergyStored(null);
acceptor.receiveEnergy(null, amountToReceive, false);
}
@Override
public double getMaxEnergy()
{
return fromRF(acceptor.getMaxEnergyStored(null));
}
@Override
public boolean needsEnergy(EnumFacing side)
{
return acceptor.receiveEnergy(side, 1, true) > 0;
}
public int toRF(double joules)
{
return (int)Math.round(joules*general.TO_RF);
}
public double fromRF(int rf)
{
return rf*general.FROM_RF;
}
}
public static class IC2Acceptor extends EnergyAcceptorWrapper
{
private IEnergySink acceptor;
public IC2Acceptor(IEnergySink ic2Acceptor)
{
acceptor = ic2Acceptor;
}
@Override
public double transferEnergyToAcceptor(EnumFacing side, double amount)
{
double toTransfer = Math.min(Math.min(acceptor.getDemandedEnergy(), toEU(amount)), Integer.MAX_VALUE);
double rejects = acceptor.injectEnergy(side, toTransfer, 0);
return fromEU(toTransfer - rejects);
}
@Override
public boolean canReceiveEnergy(EnumFacing side)
{
return acceptor.acceptsEnergyFrom(null, side);
}
@Override
public double getEnergy()
{
return 0;
}
@Override
public void setEnergy(double energy) {}
@Override
public double getMaxEnergy()
{
return 0;
}
@Override
public boolean needsEnergy(EnumFacing side)
{
return acceptor.getDemandedEnergy() > 0;
}
public double toEU(double joules)
{
return joules*general.TO_IC2;
}
public double fromEU(double eu)
{
return eu*general.FROM_IC2;
}
}
public static class TeslaAcceptor extends EnergyAcceptorWrapper
{
private ITeslaConsumer acceptor;
public TeslaAcceptor(ITeslaConsumer teslaConsumer)
{
acceptor = teslaConsumer;
}
@Override
public double transferEnergyToAcceptor(EnumFacing side, double amount)
{
return fromTesla(acceptor.givePower(toTesla(amount), false));
}
@Override
public boolean canReceiveEnergy(EnumFacing side)
{
return acceptor.givePower(1, true) > 0;
}
@Override
public double getEnergy()
{
return 0;
}
@Override
public void setEnergy(double energy) {}
@Override
public double getMaxEnergy()
{
return 0;
}
@Override
public boolean needsEnergy(EnumFacing side)
{
return canReceiveEnergy(side);
}
public long toTesla(double joules)
{
return (long)Math.round(joules*general.TO_TESLA);
}
public double fromTesla(double tesla)
{
return tesla*general.FROM_TESLA;
}
}
}