// Path: src/main/java/org/cyclops/integratedtunnels/Reference.java
// @SuppressWarnings("javadoc")
// public class Reference {
// 	
//     // Mod info
//     public static final String MOD_ID = "integratedtunnels";
//     public static final String GA_TRACKING_ID = "UA-65307010-10";
//     public static final String VERSION_URL = "https://raw.githubusercontent.com/CyclopsMC/Versions/master/" + MinecraftHelpers.getMinecraftVersionMajorMinor() + "/IntegratedTunnels.txt";
//     
//     // MOD ID's
//     public static final String MOD_FORGE = "forge";
//     public static final String MOD_CYCLOPSCORE = "cyclopscore";
//     public static final String MOD_INTEGRATEDDYNAMICS = "integrateddynamics";
// }
// 
// Path: src/main/java/org/cyclops/integratedtunnels/part/aspect/operator/PositionedOperatorIngredientIndexFluid.java
// public class PositionedOperatorIngredientIndexFluid extends PositionedOperatorIngredientIndex<FluidStack, Integer> {
//     public PositionedOperatorIngredientIndexFluid(DimPos pos, Direction side, int channel) {
//         super("countbyfluid", new Function(), ValueTypes.OBJECT_FLUIDSTACK, ValueTypes.LONG, pos, side, channel);
//     }
// 
//     @Override
//     protected Capability<? extends IPositionedAddonsNetworkIngredients<FluidStack, Integer>> getNetworkCapability() {
//         return FluidNetworkConfig.CAPABILITY;
//     }
// 
//     public static class Function extends PositionedOperatorIngredientIndex.Function<FluidStack, Integer> {
//         @Override
//         public IValue evaluate(SafeVariablesGetter variables) throws EvaluationException {
//             ValueObjectTypeFluidStack.ValueFluidStack fluidStack = variables.getValue(0, ValueTypes.OBJECT_FLUIDSTACK);
//             return ValueTypeLong.ValueLong.of(getOperator().getChannelIndex()
//                     .map(index -> index.getQuantity(fluidStack.getRawValue()))
//                     .orElse(0L));
//         }
//     }
// }
// 
// Path: src/main/java/org/cyclops/integratedtunnels/part/aspect/operator/PositionedOperatorIngredientIndexItem.java
// public class PositionedOperatorIngredientIndexItem extends PositionedOperatorIngredientIndex<ItemStack, Integer> {
//     public PositionedOperatorIngredientIndexItem(DimPos pos, Direction side, int channel) {
//         super("countbyitem", new Function(), ValueTypes.OBJECT_ITEMSTACK, ValueTypes.LONG, pos, side, channel);
//     }
// 
//     @Override
//     protected Capability<? extends IPositionedAddonsNetworkIngredients<ItemStack, Integer>> getNetworkCapability() {
//         return ItemNetworkConfig.CAPABILITY;
//     }
// 
//     public static class Function extends PositionedOperatorIngredientIndex.Function<ItemStack, Integer> {
//         @Override
//         public IValue evaluate(SafeVariablesGetter variables) throws EvaluationException {
//             ValueObjectTypeItemStack.ValueItemStack itemStack = variables.getValue(0, ValueTypes.OBJECT_ITEMSTACK);
//             return ValueTypeLong.ValueLong.of(getOperator().getChannelIndex()
//                     .map(index -> index.getQuantity(itemStack.getRawValue()))
//                     .orElse(0L));
//         }
//     }
// }


import com.google.common.collect.Iterators;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import org.cyclops.commoncapabilities.api.capability.fluidhandler.FluidMatch;
import org.cyclops.commoncapabilities.api.capability.itemhandler.ItemMatch;
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorage;
import org.cyclops.integrateddynamics.api.part.aspect.IAspectRead;
import org.cyclops.integrateddynamics.api.part.aspect.IAspectWrite;
import org.cyclops.integrateddynamics.core.evaluate.operator.Operators;
import org.cyclops.integrateddynamics.core.evaluate.operator.PositionedOperator;
import org.cyclops.integrateddynamics.core.evaluate.variable.*;
import org.cyclops.integrateddynamics.part.aspect.read.AspectReadBuilders;
import org.cyclops.integratedtunnels.Reference;
import org.cyclops.integratedtunnels.part.aspect.operator.PositionedOperatorIngredientIndexFluid;
import org.cyclops.integratedtunnels.part.aspect.operator.PositionedOperatorIngredientIndexItem;
                    INTEGER_INTERFACES = TunnelAspectReadBuilders.Network.Item.BUILDER_INTEGER
                    .handle(TunnelAspectReadBuilders.Network.Item.PROP_GET_CHANNELINDEX)
                    .handle(channel -> Iterators.size(channel.getPositions(ItemStack.EMPTY, ItemMatch.ANY)))
                    .handle(AspectReadBuilders.PROP_GET_INTEGER, "interfaces")
                    .buildRead();
            static {
                Operators.REGISTRY.registerSerializer(new PositionedOperator.Serializer(
                        PositionedOperatorIngredientIndexItem.class, new ResourceLocation(Reference.MOD_ID, "positioned_ingredient_index_item")));
            }
        }

        public static final class Fluid {
            public static final IAspectRead<ValueTypeLong.ValueLong, ValueTypeLong>
                    LONG_COUNT = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LONG
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_CHANNELINDEX)
                    .handle(channel -> channel.stream().mapToLong(FluidStack::getAmount).sum())
                    .handle(AspectReadBuilders.PROP_GET_LONG, "count")
                    .buildRead();
            public static final IAspectRead<ValueTypeLong.ValueLong, ValueTypeLong>
                    LONG_COUNTMAX = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LONG
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_CHANNEL)
                    .handle(IIngredientComponentStorage::getMaxQuantity)
                    .handle(AspectReadBuilders.PROP_GET_LONG, "countmax")
                    .buildRead();
            public static final IAspectRead<ValueTypeList.ValueList, ValueTypeList>
                    LIST_FLUIDSTACKS = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LIST
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_LIST, "fluidstacks")
                    .buildRead();
            public static final IAspectRead<ValueTypeOperator.ValueOperator, ValueTypeOperator>
                    OPERATOR_GETFLUIDCOUNT = TunnelAspectReadBuilders.Network.Fluid.BUILDER_OPERATOR
// Path: src/main/java/org/cyclops/integratedtunnels/Reference.java
// @SuppressWarnings("javadoc")
// public class Reference {
// 	
//     // Mod info
//     public static final String MOD_ID = "integratedtunnels";
//     public static final String GA_TRACKING_ID = "UA-65307010-10";
//     public static final String VERSION_URL = "https://raw.githubusercontent.com/CyclopsMC/Versions/master/" + MinecraftHelpers.getMinecraftVersionMajorMinor() + "/IntegratedTunnels.txt";
//     
//     // MOD ID's
//     public static final String MOD_FORGE = "forge";
//     public static final String MOD_CYCLOPSCORE = "cyclopscore";
//     public static final String MOD_INTEGRATEDDYNAMICS = "integrateddynamics";
// }
// 
// Path: src/main/java/org/cyclops/integratedtunnels/part/aspect/operator/PositionedOperatorIngredientIndexFluid.java
// public class PositionedOperatorIngredientIndexFluid extends PositionedOperatorIngredientIndex<FluidStack, Integer> {
//     public PositionedOperatorIngredientIndexFluid(DimPos pos, Direction side, int channel) {
//         super("countbyfluid", new Function(), ValueTypes.OBJECT_FLUIDSTACK, ValueTypes.LONG, pos, side, channel);
//     }
// 
//     @Override
//     protected Capability<? extends IPositionedAddonsNetworkIngredients<FluidStack, Integer>> getNetworkCapability() {
//         return FluidNetworkConfig.CAPABILITY;
//     }
// 
//     public static class Function extends PositionedOperatorIngredientIndex.Function<FluidStack, Integer> {
//         @Override
//         public IValue evaluate(SafeVariablesGetter variables) throws EvaluationException {
//             ValueObjectTypeFluidStack.ValueFluidStack fluidStack = variables.getValue(0, ValueTypes.OBJECT_FLUIDSTACK);
//             return ValueTypeLong.ValueLong.of(getOperator().getChannelIndex()
//                     .map(index -> index.getQuantity(fluidStack.getRawValue()))
//                     .orElse(0L));
//         }
//     }
// }
// 
// Path: src/main/java/org/cyclops/integratedtunnels/part/aspect/operator/PositionedOperatorIngredientIndexItem.java
// public class PositionedOperatorIngredientIndexItem extends PositionedOperatorIngredientIndex<ItemStack, Integer> {
//     public PositionedOperatorIngredientIndexItem(DimPos pos, Direction side, int channel) {
//         super("countbyitem", new Function(), ValueTypes.OBJECT_ITEMSTACK, ValueTypes.LONG, pos, side, channel);
//     }
// 
//     @Override
//     protected Capability<? extends IPositionedAddonsNetworkIngredients<ItemStack, Integer>> getNetworkCapability() {
//         return ItemNetworkConfig.CAPABILITY;
//     }
// 
//     public static class Function extends PositionedOperatorIngredientIndex.Function<ItemStack, Integer> {
//         @Override
//         public IValue evaluate(SafeVariablesGetter variables) throws EvaluationException {
//             ValueObjectTypeItemStack.ValueItemStack itemStack = variables.getValue(0, ValueTypes.OBJECT_ITEMSTACK);
//             return ValueTypeLong.ValueLong.of(getOperator().getChannelIndex()
//                     .map(index -> index.getQuantity(itemStack.getRawValue()))
//                     .orElse(0L));
//         }
//     }
// }


// Path: src/main/java/org/cyclops/integratedtunnels/part/aspect/TunnelAspects.java
import com.google.common.collect.Iterators;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fluids.FluidStack;
import org.cyclops.commoncapabilities.api.capability.fluidhandler.FluidMatch;
import org.cyclops.commoncapabilities.api.capability.itemhandler.ItemMatch;
import org.cyclops.commoncapabilities.api.ingredient.storage.IIngredientComponentStorage;
import org.cyclops.integrateddynamics.api.part.aspect.IAspectRead;
import org.cyclops.integrateddynamics.api.part.aspect.IAspectWrite;
import org.cyclops.integrateddynamics.core.evaluate.operator.Operators;
import org.cyclops.integrateddynamics.core.evaluate.operator.PositionedOperator;
import org.cyclops.integrateddynamics.core.evaluate.variable.*;
import org.cyclops.integrateddynamics.part.aspect.read.AspectReadBuilders;
import org.cyclops.integratedtunnels.Reference;
import org.cyclops.integratedtunnels.part.aspect.operator.PositionedOperatorIngredientIndexFluid;
import org.cyclops.integratedtunnels.part.aspect.operator.PositionedOperatorIngredientIndexItem;

                    INTEGER_INTERFACES = TunnelAspectReadBuilders.Network.Item.BUILDER_INTEGER
                    .handle(TunnelAspectReadBuilders.Network.Item.PROP_GET_CHANNELINDEX)
                    .handle(channel -> Iterators.size(channel.getPositions(ItemStack.EMPTY, ItemMatch.ANY)))
                    .handle(AspectReadBuilders.PROP_GET_INTEGER, "interfaces")
                    .buildRead();
            static {
                Operators.REGISTRY.registerSerializer(new PositionedOperator.Serializer(
                        PositionedOperatorIngredientIndexItem.class, new ResourceLocation(Reference.MOD_ID, "positioned_ingredient_index_item")));
            }
        }

        public static final class Fluid {
            public static final IAspectRead<ValueTypeLong.ValueLong, ValueTypeLong>
                    LONG_COUNT = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LONG
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_CHANNELINDEX)
                    .handle(channel -> channel.stream().mapToLong(FluidStack::getAmount).sum())
                    .handle(AspectReadBuilders.PROP_GET_LONG, "count")
                    .buildRead();
            public static final IAspectRead<ValueTypeLong.ValueLong, ValueTypeLong>
                    LONG_COUNTMAX = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LONG
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_CHANNEL)
                    .handle(IIngredientComponentStorage::getMaxQuantity)
                    .handle(AspectReadBuilders.PROP_GET_LONG, "countmax")
                    .buildRead();
            public static final IAspectRead<ValueTypeList.ValueList, ValueTypeList>
                    LIST_FLUIDSTACKS = TunnelAspectReadBuilders.Network.Fluid.BUILDER_LIST
                    .handle(TunnelAspectReadBuilders.Network.Fluid.PROP_GET_LIST, "fluidstacks")
                    .buildRead();
            public static final IAspectRead<ValueTypeOperator.ValueOperator, ValueTypeOperator>
                    OPERATOR_GETFLUIDCOUNT = TunnelAspectReadBuilders.Network.Fluid.BUILDER_OPERATOR
                    .handle(input -> ValueTypeOperator.ValueOperator.of(new PositionedOperatorIngredientIndexFluid(