/** Attempts to extract essentia gas from the cell. returns the number of items extracted, null */
  @Override
  public IAEFluidStack extractItems(
      final IAEFluidStack request, final Actionable mode, final BaseActionSource src) {
    // Ensure there is a request, and that it is an essentia gas
    if ((request == null)
        || (request.getFluid() == null)
        || (!(request.getFluid() instanceof GaseousEssentia))) {
      // Invalid request.
      return null;
    }

    // Get the aspect of the essentia
    Aspect requestAspect = ((GaseousEssentia) request.getFluid()).getAspect();

    // Calculate the amount of essentia to extract
    long essentiaAmountRequested =
        EssentiaConversionHelper.INSTANCE.convertFluidAmountToEssentiaAmount(
            request.getStackSize());

    // Is the requested amount a whole essentia?
    if (essentiaAmountRequested == 0) {
      // Can not extract partial amounts
      return null;
    }

    // Extract
    long extractedEssentiaAmount =
        this.extractEssentiaFromCell(requestAspect, essentiaAmountRequested, mode);

    // Did we extract any?
    if (extractedEssentiaAmount == 0) {
      // Nothing was extracted
      return null;
    }

    // Copy the request
    IAEFluidStack extractedFluid = request.copy();

    /*
     * NOTE: I don't like this 'fix'
     * If the machine requesting the extraction is the IO port, lie and say that the full request
     * was extracted. If I report the actual amount extracted, it gets hung in an infinite loop and
     * suddenly the network thinks we only have 6mb of essentia gas stored.
     */
    if (!((src instanceof MachineSource) && (((MachineSource) src).via instanceof TileIOPort))) {
      // Not IO port, set the actual amount extracted
      extractedFluid.setStackSize(
          EssentiaConversionHelper.INSTANCE.convertEssentiaAmountToFluidAmount(
              extractedEssentiaAmount));
    }

    return extractedFluid;
  }
  /** Attempts to add essentia gas to the cell. returns the number of items not added. */
  @Override
  public IAEFluidStack injectItems(
      final IAEFluidStack input, final Actionable mode, final BaseActionSource src) {
    // Ensure we have an input.
    if ((input == null)) {
      // No input
      return null;
    }

    // Ensure the input is a gas
    if ((input.getFluid() == null) || !(input.getFluid() instanceof GaseousEssentia)) {
      // Invalid fluid
      return input.copy();
    }

    // Ensure the essentia can be accepted
    if (!this.canAccept(input)) {
      // Can not accept this essentia
      return input.copy();
    }

    // Get the aspect of the gas
    Aspect essentiaAspect = ((GaseousEssentia) input.getFluid()).getAspect();

    // Calculate the amount to store
    long amountToStore =
        EssentiaConversionHelper.INSTANCE.convertFluidAmountToEssentiaAmount(input.getStackSize());

    // Is the amount a whole essentia?
    if (amountToStore == 0) {
      // Can not store partial amounts.
      return input.copy();
    }

    // Get the amount not stored
    long amountNotStored = this.addEssentiaToCell(essentiaAspect, amountToStore, mode);

    // Was all stored?
    if (amountNotStored == 0) {
      // All was stored
      return null;
    }

    // Copy the input
    IAEFluidStack result = input.copy();

    // Set the size to how much was left over
    result.setStackSize(
        EssentiaConversionHelper.INSTANCE.convertEssentiaAmountToFluidAmount(amountNotStored));

    return result;
  }
  /** Gets the list of essentia gasses stored on the cell. */
  @Override
  public IItemList<IAEFluidStack> getAvailableItems(final IItemList<IAEFluidStack> availableList) {
    for (AspectStack essentiaStack : this.storedEssentia) {
      // Skip if null
      if (essentiaStack == null) {
        continue;
      }

      // Get the gas
      GaseousEssentia essentiaGas = GaseousEssentia.getGasFromAspect(essentiaStack.aspect);

      // Create the AE fluid stack
      availableList.add(
          EssentiaConversionHelper.INSTANCE.createAEFluidStackInEssentiaUnits(
              essentiaGas, essentiaStack.stackSize));
    }

    return availableList;
  }