/** Called when a network event changes the amount of something in the storage grid. */
  @Override
  public void postChange(
      final IBaseMonitor<IAEFluidStack> monitor,
      final Iterable<IAEFluidStack> changes,
      final BaseActionSource source) {
    // Ensure we have a filter
    if (this.filterAspect == null) {
      return;
    }

    // Ensure there was a change
    if (changes == null) {
      return;
    }

    // Ensure one of the changes an essentia gas
    for (IAEFluidStack change : changes) {
      if ((change.getFluid() instanceof GaseousEssentia)) {
        // Propagate the update
        this.onMonitorUpdate((IMEMonitor<IAEFluidStack>) monitor);

        // Stop searching
        break;
      }
    }
  }
  private void onMonitorUpdate(final IMEMonitor<IAEFluidStack> monitor) {
    // Do we have a filter?
    if (this.filterAspect == null) {
      // Set the current amount to 0
      this.setCurrentAmount(0);
    }

    // Get the gas for the filter aspect
    GaseousEssentia aspectGas = GaseousEssentia.getGasFromAspect(this.filterAspect);

    // Is there a fluid form of the aspect?
    if (aspectGas == null) {
      // Set the current amount to 0
      this.setCurrentAmount(0);
    }

    // Convert to AE fluid stack
    IAEFluidStack asGasStack =
        EssentiaConversionHelper.instance.createAEFluidStackInFluidUnits(aspectGas, 1);

    // Get how much is in the system
    IAEFluidStack fluidStack = monitor.getStorageList().findPrecise(asGasStack);

    // Was there any in the system?
    if (fluidStack == null) {
      // Set current amount to zero
      this.setCurrentAmount(0);
    } else {
      // Set the current amount
      this.setCurrentAmount(
          EssentiaConversionHelper.instance.convertFluidAmountToEssentiaAmount(
              fluidStack.getStackSize()));
    }
  }
  /** 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;
  }
  /** Is the cell partitioned to accept the fluid? */
  @Override
  public boolean isPrioritized(final IAEFluidStack input) {
    // Is the cell partitioned?
    if (this.isPartitioned()) {
      // Ensure there is an input
      if (input == null) {
        // Null input
        return false;
      }

      // Get the fluid
      Fluid inputFluid = input.getFluid();

      // Is the fluid an essentia gas?
      if (!(inputFluid instanceof GaseousEssentia)) {
        // Not essentia gas
        return false;
      }

      // Get the aspect
      Aspect inputAspect = ((GaseousEssentia) inputFluid).getAspect();

      // Is the cell partitioned for this aspect?
      return this.partitionAspects.contains(inputAspect);
    }

    return false;
  }
  /** Checks if the cell can accept/store the fluid. */
  @Override
  public boolean canAccept(final IAEFluidStack input) {
    // Ensure there is an input
    if (input == null) {
      // Null input
      return false;
    }

    // Get the fluid
    Fluid inputFluid = input.getFluid();

    // Is the fluid an essentia gas?
    if (!(inputFluid instanceof GaseousEssentia)) {
      // Not essentia gas
      return false;
    }

    // Is the cell partitioned?
    if (this.isPartitioned()) {
      // Get the input aspect
      Aspect inputAspect = ((GaseousEssentia) inputFluid).getAspect();

      // Is the cell partitioned for this aspect?
      if (!this.partitionAspects.contains(inputAspect)) {
        // Cell partition will not allow this aspect.
        return false;
      }
    }

    // Return if there is a match or empty slot for the essentia
    return (-1 != this.getSlotFor(((GaseousEssentia) inputFluid).getAspect()));
  }
  /** 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;
  }