package net.ros.common.grid.impl;

import lombok.Getter;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.ros.common.grid.node.IFluidPipe;
import net.ros.common.grid.node.IPipeValve;
import net.ros.common.grid.node.ITileCable;
import net.ros.common.grid.node.ITileNode;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static net.ros.common.util.FluidUtils.getFluidDifference;
import static net.ros.common.util.FluidUtils.getTankPressure;

@Getter
public class PipeGrid extends CableGrid
{
    private final List<IFluidPipe> outputs;
    private final List<IFluidPipe> inputs;

    public PipeGrid(final int identifier)
    {
        super(identifier);

        this.outputs = new ArrayList<>();
        this.inputs = new ArrayList<>();
    }

    @Override
    public void addCable(@Nonnull final ITileNode cable)
    {
        super.addCable(cable);
    }

    @Override
    public boolean removeCable(final ITileNode cable)
    {
        return super.removeCable(cable);
    }

    @Override
    public void tick()
    {
        if (!this.getInputs().isEmpty())
            this.getInputs().forEach(IFluidPipe::drainNeighbors);

        for (ITileNode<?> node : this.getCables())
        {
            IFluidPipe pipe = (IFluidPipe) node;

            if ((pipe instanceof IPipeValve && !((IPipeValve) pipe).isOpen()) ||
                    (pipe.getBufferTank().getFluidAmount() == 0))
                continue;

            IFluidTank tank = pipe.getBufferTank();
            int transferred = 0;

            for (Map.Entry<EnumFacing, ITileCable<PipeGrid>> entry : pipe.getConnectionsMap().entrySet())
            {
                FluidStack pipeFluid = pipe.getBufferTank().getFluid();
                FluidStack otherFluid = ((IFluidPipe) entry.getValue()).getBufferTank().getFluid();

                if (pipeFluid != null && otherFluid != null && !pipeFluid.equals(otherFluid))
                    continue;

                transferred += balanceTanks(tank, ((IFluidPipe) entry.getValue()).getBufferTank(),
                        pipe.getTransferRate() - transferred);

                if (transferred >= pipe.getTransferRate())
                    break;
            }
        }

        if (!this.getOutputs().isEmpty())
            this.getOutputs().forEach(IFluidPipe::fillNeighbors);
    }

    private int balanceTanks(IFluidTank first, IFluidTank second, int transferRate)
    {
        float average = (getTankPressure(second) + getTankPressure(first)) / 2;

        if (getTankPressure(second) < average)
        {
            FluidStack drained = first.drain(Math.min(transferRate, getFluidDifference(first, average)), false);
            int filled = second.fill(drained, false);

            if (filled < 1)
                return 0;

            return second.fill(first.drain(filled, true), true);
        }
        return 0;
    }

    @Override
    public CableGrid copy(final int identifier)
    {
        return new PipeGrid(identifier);
    }

    @Override
    public boolean canMerge(final CableGrid grid)
    {
        if (grid instanceof PipeGrid)
            return super.canMerge(grid);
        return false;
    }

    @Override
    public void onMerge(final CableGrid grid)
    {
        this.getOutputs().addAll(((PipeGrid) grid).getOutputs());
        this.getInputs().addAll(((PipeGrid) grid).getInputs());
    }

    @Override
    public void onSplit(final CableGrid grid)
    {
        this.getOutputs().addAll(
                ((PipeGrid) grid).getOutputs().stream().filter(this.getCables()::contains)
                        .collect(Collectors.toList()));
        this.getInputs().addAll(
                ((PipeGrid) grid).getInputs().stream().filter(this.getCables()::contains).collect(Collectors.toList()));
    }

    public void addConnectedPipe(IFluidPipe pipe)
    {
        if (pipe.isInput())
            this.inputs.add(pipe);
        if (pipe.isOutput())
            this.outputs.add(pipe);
    }

    public void removeConnectedPipe(IFluidPipe pipe)
    {
        if (pipe.isInput())
            this.inputs.remove(pipe);
        if (pipe.isOutput())
            this.outputs.remove(pipe);
    }
}

@@ -53,16 +53,51 @@
 etter;%0D%0A
+import net.minecraft.init.Blocks;%0D%0A
 import n
@@ -127,16 +127,16 @@
 acing;%0D%0A
-
 import n
@@ -255,152 +255,9 @@
 ode.
-IFluidPipe;%0D%0Aimport net.ros.common.grid.node.IPipeValve;%0D%0Aimport net.ros.common.grid.node.ITileCable;%0D%0Aimport net.ros.common.grid.node.ITileNode
+*
 ;%0D%0A%0D
@@ -1257,24 +1257,82 @@
 ghbors);%0D%0A%0D%0A
+        List%3CITileNode%3E toDestroy = new ArrayList%3C%3E();%0D%0A%0D%0A
         for 
@@ -1697,24 +1697,161 @@
 red = 0;%0D%0A%0D%0A
+            if (tank.getFluid().getFluid().getTemperature() %3E PipeType.getHeat(pipe.getType()))%0D%0A                toDestroy.add(node);%0D%0A%0D%0A
             
@@ -2525,32 +2525,32 @@
 %0A            %7D%0D%0A
-
         %7D%0D%0A%0D%0A   
@@ -2542,24 +2542,166 @@
        %7D%0D%0A%0D%0A
+        toDestroy.forEach(node -%3E node.getBlockWorld().setBlockState(node.getBlockPos(),%0D%0A                Blocks.FIRE.getDefaultState()));%0D%0A%0D%0A
         if (

Add fluidpipe overheat effect