package mekanism.common.multipart;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.LinkedHashSet;
import mekanism.api.Coord4D;
import mekanism.api.IAlloyInteraction;
import mekanism.api.transmitters.DynamicNetwork;
import mekanism.api.transmitters.DynamicNetwork.NetworkClientRequest;
import mekanism.api.transmitters.IGridTransmitter;
import mekanism.api.transmitters.TransmitterNetworkRegistry;
import mekanism.common.capabilities.Capabilities;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.Capability;
public abstract class PartTransmitter<A, N extends DynamicNetwork<A, N>> extends PartSidedPipe implements IAlloyInteraction
{
public MultipartTransmitter<A, N> transmitterDelegate;
public boolean unloaded = true;
public boolean dataRequest = false;
public PartTransmitter()
{
transmitterDelegate = new MultipartTransmitter<>(this);
}
public MultipartTransmitter<A, N> getTransmitter()
{
return transmitterDelegate;
}
public abstract N createNewNetwork();
public abstract N createNetworkByMerging(Collection<N> networks);
@Override
public void onWorldJoin()
{
if(!getWorld().isRemote)
{
TransmitterNetworkRegistry.registerOrphanTransmitter(getTransmitter());
}
unloaded = false;
}
@Override
public void update()
{
super.update();
if(getWorld().isRemote)
{
if(!dataRequest)
{
dataRequest = true;
MinecraftForge.EVENT_BUS.post(new NetworkClientRequest(getWorld().getTileEntity(getPos())));
}
}
}
@Override
public void onUnloaded()
{
if(!getWorld().isRemote)
{
getTransmitter().takeShare();
}
super.onUnloaded();
}
@Override
public void onWorldSeparate()
{
unloaded = true;
if(!getWorld().isRemote)
{
TransmitterNetworkRegistry.invalidateTransmitter(getTransmitter());
}
else {
getTransmitter().setTransmitterNetwork(null);
}
}
@Override
public void markDirtyTransmitters()
{
super.markDirtyTransmitters();
if(getTransmitter().hasTransmitterNetwork())
{
TransmitterNetworkRegistry.invalidateTransmitter(getTransmitter());
}
}
@Override
public void markDirtyAcceptor(EnumFacing side)
{
super.markDirtyAcceptor(side);
if(getTransmitter().hasTransmitterNetwork())
{
getTransmitter().getTransmitterNetwork().acceptorChanged(getTransmitter(), side);
}
}
public abstract A getCachedAcceptor(EnumFacing side);
protected TileEntity getCachedTile(EnumFacing side)
{
ConnectionType type = connectionTypes[side.ordinal()];
if(type == ConnectionType.PULL || type == ConnectionType.NONE)
{
return null;
}
return connectionMapContainsSide(currentAcceptorConnections, side) ? cachedAcceptors[side.ordinal()] : null;
}
@Override
public void onAlloyInteraction(EntityPlayer player, EnumHand hand, ItemStack stack, int tierOrdinal)
{
if(getTransmitter().hasTransmitterNetwork())
{
int upgraded = 0;
Object[] array = ((LinkedHashSet)getTransmitter().getTransmitterNetwork().transmitters.clone()).toArray();
Arrays.sort(array, new Comparator() {
@Override
public int compare(Object o1, Object o2)
{
if(o1 instanceof IGridTransmitter && o2 instanceof IGridTransmitter)
{
Coord4D thisCoord = new Coord4D(getPos(), getWorld());
Coord4D o1Coord = ((IGridTransmitter)o1).coord();
Coord4D o2Coord = ((IGridTransmitter)o2).coord();
return o1Coord.distanceTo(thisCoord) > o2Coord.distanceTo(thisCoord) ? 1 :
(o1Coord.distanceTo(thisCoord) < o2Coord.distanceTo(thisCoord) ? -1 : 0);
}
return 0;
}
});
for(Object iter : array)
{
if(iter instanceof MultipartTransmitter)
{
PartTransmitter t = ((MultipartTransmitter)iter).containingPart;
if(t.upgrade(tierOrdinal))
{
upgraded++;
if(upgraded == 8)
{
break;
}
}
}
}
if(upgraded > 0)
{
if(!player.capabilities.isCreativeMode)
{
stack.stackSize--;
if(stack.stackSize == 0)
{
player.setHeldItem(hand, null);
}
}
}
}
}
public boolean upgrade(int tierOrdinal)
{
return false;
}
public abstract int getCapacity();
public abstract Object getBuffer();
public abstract void takeShare();
public abstract void updateShare();
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing side)
{
return capability == Capabilities.GRID_TRANSMITTER_CAPABILITY || capability == Capabilities.ALLOY_INTERACTION_CAPABILITY
|| super.hasCapability(capability, side);
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing side)
{
if(capability == Capabilities.GRID_TRANSMITTER_CAPABILITY)
{
return (T)getTransmitter();
}
else if(capability == Capabilities.ALLOY_INTERACTION_CAPABILITY)
{
return (T)this;
}
return super.getCapability(capability, side);
}
}