/**
   * Returns a boolean indicating whether the neutral loss should be accounted for.
   *
   * @param neutralLosses map of expected neutral losses
   * @param neutralLoss the neutral loss of interest
   * @param ion the fragment ion of interest
   * @return boolean indicating whether the neutral loss should be considered
   */
  public boolean isAccounted(NeutralLossesMap neutralLosses, NeutralLoss neutralLoss, Ion ion) {

    if (neutralLosses == null || neutralLosses.isEmpty()) {
      return false;
    }

    for (String neutralLossName : neutralLosses.getAccountedNeutralLosses()) {

      NeutralLoss neutralLossRef = NeutralLoss.getNeutralLoss(neutralLossName);

      if (neutralLoss.isSameAs(neutralLossRef)) {
        switch (ion.getType()) {
          case PEPTIDE_FRAGMENT_ION:
            PeptideFragmentIon peptideFragmentIon = ((PeptideFragmentIon) ion);
            switch (ion.getSubType()) {
              case PeptideFragmentIon.A_ION:
              case PeptideFragmentIon.B_ION:
              case PeptideFragmentIon.C_ION:
                return neutralLosses.getForwardStart(neutralLossName)
                    <= peptideFragmentIon.getNumber();
              case PeptideFragmentIon.X_ION:
              case PeptideFragmentIon.Y_ION:
              case PeptideFragmentIon.Z_ION:
                return neutralLosses.getRewindStart(neutralLossName)
                    <= peptideFragmentIon.getNumber();
              default:
                throw new UnsupportedOperationException(
                    "Fragment ion type "
                        + ion.getSubTypeAsString()
                        + " not implemented in the spectrum annotator.");
            }
          case TAG_FRAGMENT_ION:
            TagFragmentIon tagFragmentIon = ((TagFragmentIon) ion);
            switch (ion.getSubType()) {
              case TagFragmentIon.A_ION:
              case TagFragmentIon.B_ION:
              case TagFragmentIon.C_ION:
                return neutralLosses.getForwardStart(neutralLossName) <= tagFragmentIon.getNumber();
              case TagFragmentIon.X_ION:
              case TagFragmentIon.Y_ION:
              case TagFragmentIon.Z_ION:
                return neutralLosses.getRewindStart(neutralLossName) <= tagFragmentIon.getNumber();
              default:
                throw new UnsupportedOperationException(
                    "Fragment ion type "
                        + ion.getSubTypeAsString()
                        + " not implemented in the spectrum annotator.");
            }
          default:
            return true;
        }
      }
    }
    return false;
  }