class BgpTopologyUtils {

  @Nullable
  @VisibleForTesting
  static AsPair computeAsPair(
      @Nullable Long initiatorLocalAs,
      @Nullable Long initiatorConfed,
      @Nonnull LongSpace initiatorRemoteAsns,
      @Nullable Long listenerLocalAs,
      @Nullable Long listenerConfed,
      @Nonnull LongSpace listenerRemoteAsns) {
    if (initiatorLocalAs == null || listenerLocalAs == null) {
      return null; // This is plainly a misconfiguration. No session.
    }
    // Simple case: no confederation config
    if (initiatorConfed == null && listenerConfed == null) {
      // Note: order of evaluation matters.
      if (listenerRemoteAsns.contains(initiatorLocalAs)
          && initiatorRemoteAsns.contains(listenerLocalAs)) {
        return new AsPair(initiatorLocalAs, listenerLocalAs, ConfedSessionType.NO_CONFED);
      } else {
        return null;
      }
    }
    // Confederation config is present on both peers
    if (initiatorConfed != null && listenerConfed != null) {
      // both peers inside *the same* confederation
      if (initiatorConfed.equals(listenerConfed)) {
        if (listenerRemoteAsns.contains(initiatorLocalAs)
            && initiatorRemoteAsns.contains(listenerLocalAs)) {
          return new AsPair(initiatorLocalAs, listenerLocalAs, ConfedSessionType.WITHIN_CONFED);
        } else {
          return null;
        }
      } else {
        // Both peers inside *different* confederations, must use external identifier only
        if (listenerRemoteAsns.contains(initiatorConfed)
            && initiatorRemoteAsns.contains(listenerConfed)) {
          return new AsPair(
              initiatorConfed, listenerConfed, ConfedSessionType.ACROSS_CONFED_BORDER);
        } else {
          return null;
        }
      }
    }
    // Initiator is inside a confederation
    if (initiatorConfed != null) {
      // Initiator and listener are in the same AS, so they're in the same confederation
      if (initiatorLocalAs.equals(listenerLocalAs)) {
        if (listenerRemoteAsns.contains(initiatorLocalAs)
            && initiatorRemoteAsns.contains(listenerLocalAs)) {
          return new AsPair(initiatorLocalAs, listenerLocalAs, ConfedSessionType.WITHIN_CONFED);
        } else {
          return null;
        }
      } else if (listenerRemoteAsns.contains(initiatorConfed)
          && initiatorRemoteAsns.contains(listenerLocalAs)) {
        return new AsPair(initiatorConfed, listenerLocalAs, ConfedSessionType.ACROSS_CONFED_BORDER);
      } else {
        return null;
      }
    } else {
      // Listener is inside a confederation
      // Initiator and listener are in the same AS, so they're in the same confederation
      if (initiatorLocalAs.equals(listenerLocalAs)) {
        if (listenerRemoteAsns.contains(initiatorLocalAs)
            && initiatorRemoteAsns.contains(listenerLocalAs)) {
          return new AsPair(initiatorLocalAs, listenerLocalAs, ConfedSessionType.WITHIN_CONFED);
        } else {
          return null;
        }
      } else if (listenerRemoteAsns.contains(initiatorLocalAs)
          && initiatorRemoteAsns.contains(listenerConfed)) {
        return new AsPair(initiatorLocalAs, listenerConfed, ConfedSessionType.ACROSS_CONFED_BORDER);
      }
    }
    return null;
  }

  private  BgpTopologyUtils();

}