package mekanism.common.content.transporter;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.List;
import mekanism.api.Coord4D;
import mekanism.api.EnumColor;
import mekanism.api.transmitters.IBlockableConnection;
import mekanism.common.PacketHandler;
import mekanism.common.base.ILogisticalTransporter;
import mekanism.common.base.ITransporterTile;
import mekanism.common.content.transporter.TransporterPathfinder.Destination;
import mekanism.common.tile.TileEntityLogisticalSorter;
import mekanism.common.util.TransporterUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public class TransporterStack
{
public ItemStack itemStack;
public int progress;
public EnumColor color = null;
public boolean initiatedPath = false;
public ForgeDirection idleDir = ForgeDirection.UNKNOWN;
public List<Coord4D> pathToTarget = new ArrayList<Coord4D>();
public Coord4D originalLocation;
public Coord4D homeLocation;
public Coord4D clientNext;
public Coord4D clientPrev;
public Path pathType;
public void write(ILogisticalTransporter transporter, ArrayList data)
{
if(color != null)
{
data.add(TransporterUtils.colors.indexOf(color));
}
else {
data.add(-1);
}
data.add(progress);
originalLocation.write(data);
data.add(pathType.ordinal());
if(pathToTarget.indexOf(transporter.coord()) > 0)
{
data.add(true);
getNext(transporter).write(data);
}
else {
data.add(false);
}
getPrev(transporter).write(data);
data.add(itemStack);
}
public void read(ByteBuf dataStream)
{
int c = dataStream.readInt();
if(c != -1)
{
color = TransporterUtils.colors.get(c);
}
else {
color = null;
}
progress = dataStream.readInt();
originalLocation = Coord4D.read(dataStream);
pathType = Path.values()[dataStream.readInt()];
if(dataStream.readBoolean())
{
clientNext = Coord4D.read(dataStream);
}
clientPrev = Coord4D.read(dataStream);
itemStack = PacketHandler.readStack(dataStream);
}
public void write(NBTTagCompound nbtTags)
{
if(color != null)
{
nbtTags.setInteger("color", TransporterUtils.colors.indexOf(color));
}
nbtTags.setInteger("progress", progress);
nbtTags.setTag("originalLocation", originalLocation.write(new NBTTagCompound()));
nbtTags.setInteger("idleDir", idleDir.ordinal());
if(homeLocation != null)
{
nbtTags.setTag("homeLocation", homeLocation.write(new NBTTagCompound()));
}
nbtTags.setInteger("pathType", pathType.ordinal());
itemStack.writeToNBT(nbtTags);
}
public void read(NBTTagCompound nbtTags)
{
if(nbtTags.hasKey("color"))
{
color = TransporterUtils.colors.get(nbtTags.getInteger("color"));
}
progress = nbtTags.getInteger("progress");
originalLocation = Coord4D.read(nbtTags.getCompoundTag("originalLocation"));
idleDir = ForgeDirection.values()[nbtTags.getInteger("idleDir")];
if(nbtTags.hasKey("homeLocation"))
{
homeLocation = Coord4D.read(nbtTags.getCompoundTag("homeLocation"));
}
pathType = Path.values()[nbtTags.getInteger("pathType")];
itemStack = ItemStack.loadItemStackFromNBT(nbtTags);
}
public static TransporterStack readFromNBT(NBTTagCompound nbtTags)
{
TransporterStack stack = new TransporterStack();
stack.read(nbtTags);
return stack;
}
public static TransporterStack readFromPacket(ByteBuf dataStream)
{
TransporterStack stack = new TransporterStack();
stack.read(dataStream);
return stack;
}
public boolean hasPath()
{
return pathToTarget != null && pathToTarget.size() >= 2;
}
public ItemStack recalculatePath(ILogisticalTransporter transporter, int min)
{
Destination newPath = TransporterPathfinder.getNewBasePath(transporter, this, min);
if(newPath == null)
{
return itemStack;
}
pathToTarget = newPath.path;
pathType = Path.DEST;
idleDir = ForgeDirection.UNKNOWN;
initiatedPath = true;
return newPath.rejected;
}
public ItemStack recalculateRRPath(TileEntityLogisticalSorter outputter, ILogisticalTransporter transporter, int min)
{
Destination newPath = TransporterPathfinder.getNewRRPath(transporter, this, outputter, min);
if(newPath == null)
{
return itemStack;
}
pathToTarget = newPath.path;
pathType = Path.DEST;
idleDir = ForgeDirection.UNKNOWN;
initiatedPath = true;
return newPath.rejected;
}
public boolean calculateIdle(ILogisticalTransporter transporter)
{
List<Coord4D> newPath = TransporterPathfinder.getIdlePath(transporter, this);
if(newPath == null)
{
return false;
}
if(pathType == Path.HOME)
{
idleDir = ForgeDirection.UNKNOWN;
}
pathToTarget = newPath;
originalLocation = transporter.coord();
initiatedPath = true;
return true;
}
public boolean isFinal(ILogisticalTransporter transporter)
{
return pathToTarget.indexOf(transporter.coord()) == (pathType == Path.NONE ? 0 : 1);
}
public Coord4D getNext(ILogisticalTransporter transporter)
{
if(!transporter.world().isRemote)
{
int index = pathToTarget.indexOf(transporter.coord())-1;
if(index < 0)
{
return null;
}
return pathToTarget.get(index);
}
else {
return clientNext;
}
}
public Coord4D getPrev(ILogisticalTransporter transporter)
{
if(!transporter.world().isRemote)
{
int index = pathToTarget.indexOf(transporter.coord())+1;
if(index < pathToTarget.size())
{
return pathToTarget.get(index);
}
else {
return originalLocation;
}
}
else {
return clientPrev;
}
}
public int getSide(ILogisticalTransporter transporter)
{
if(progress < 50)
{
if(getPrev(transporter) != null)
{
return transporter.coord().sideDifference(getPrev(transporter)).ordinal();
}
}
else if(progress == 50)
{
if(getNext(transporter) != null)
{
return getNext(transporter).sideDifference(transporter.coord()).ordinal();
}
}
else if(progress > 50)
{
if(getNext(transporter) != null)
{
return getNext(transporter).sideDifference(transporter.coord()).ordinal();
}
}
return 0;
}
public boolean canInsertToTransporter(TileEntity tileEntity, ForgeDirection from)
{
if(!(tileEntity instanceof ITransporterTile))
{
return false;
}
ILogisticalTransporter transporter = ((ITransporterTile)tileEntity).getTransmitter();
if(!((ITransporterTile)tileEntity).canConnectMutual(from.getOpposite()))
{
return false;
}
return transporter.getColor() == color || transporter.getColor() == null;
}
public boolean canInsertToTransporter(ILogisticalTransporter transporter, ForgeDirection side)
{
if(!transporter.canConnectMutual(side))
{
return false;
}
return transporter.getColor() == color || transporter.getColor() == null;
}
public Coord4D getDest()
{
return pathToTarget.get(0);
}
public static enum Path
{
DEST, HOME, NONE
}
}