@Test
  public void testExceedHistoryBackward() throws OrekitException, IOException {
    final double period = 900.0;

    // the raw detector should trigger one event at each 900s period
    final DateDetector raw =
        new DateDetector(orbit.getDate().shiftedBy(+0.5 * period))
            .withMaxCheck(period / 3)
            .withHandler(new ContinueOnEvent<DateDetector>());
    for (int i = 0; i < 300; ++i) {
      raw.addEventDate(orbit.getDate().shiftedBy(-(i + 0.5) * period));
    }

    // in fact, we will filter out half of these events, so we get only one event every 2 periods
    final EventEnablingPredicateFilter<DateDetector> filtered =
        new EventEnablingPredicateFilter<DateDetector>(
            raw,
            new EnablingPredicate<DateDetector>() {
              public boolean eventIsEnabled(
                  SpacecraftState state, DateDetector eventDetector, double g) {
                double nbPeriod = orbit.getDate().durationFrom(state.getDate()) / period;
                return ((int) FastMath.floor(nbPeriod)) % 2 == 1;
              }
            });
    Propagator propagator = new KeplerianPropagator(orbit);
    EventsLogger logger = new EventsLogger();
    propagator.addEventDetector(logger.monitorDetector(filtered));
    propagator.propagate(orbit.getDate().shiftedBy(-301 * period));
    List<LoggedEvent> events = logger.getLoggedEvents();

    // 300 periods, 150 events as half of them are filtered out
    Assert.assertEquals(150, events.size());

    // as we have encountered a lot of enabling status changes, we exceeded the internal history
    // if we try to display again the filtered g function for dates far in the future,
    // we will not see the zero crossings anymore, they have been lost
    propagator.clearEventsDetectors();
    for (double dt = -5000.0; dt > -10000.0; dt -= 3.0) {
      double filteredG = filtered.g(propagator.propagate(orbit.getDate().shiftedBy(dt)));
      Assert.assertTrue(filteredG < 0.0);
    }

    // on the other hand, if we try to display again the filtered g function for future dates
    // that are still inside the history, we still see the zero crossings
    for (double dt = -195400.0; dt > -196200.0; dt -= 3.0) {
      double filteredG = filtered.g(propagator.propagate(orbit.getDate().shiftedBy(dt)));
      if (dt < -195750) {
        Assert.assertTrue(filteredG < 0.0);
      } else {
        Assert.assertTrue(filteredG > 0.0);
      }
    }
  }
  @Test
  public void testResetState() throws OrekitException {
    final List<AbsoluteDate> reset = new ArrayList<AbsoluteDate>();
    DateDetector raw =
        new DateDetector(orbit.getDate().shiftedBy(3600.0))
            .withMaxCheck(1000.0)
            .withHandler(
                new EventHandler<DateDetector>() {
                  public SpacecraftState resetState(
                      DateDetector detector, SpacecraftState oldState) {
                    reset.add(oldState.getDate());
                    return oldState;
                  }

                  public Action eventOccurred(
                      SpacecraftState s, DateDetector detector, boolean increasing) {
                    return Action.RESET_STATE;
                  }
                });
    for (int i = 2; i < 10; ++i) {
      raw.addEventDate(orbit.getDate().shiftedBy(i * 3600.0));
    }
    EventEnablingPredicateFilter<DateDetector> filtered =
        new EventEnablingPredicateFilter<DateDetector>(
            raw,
            new EnablingPredicate<DateDetector>() {
              public boolean eventIsEnabled(
                  SpacecraftState state, DateDetector eventDetector, double g) {
                return state.getDate().durationFrom(orbit.getDate()) > 20000.0;
              }
            });
    Propagator propagator = new KeplerianPropagator(orbit);
    EventsLogger logger = new EventsLogger();
    propagator.addEventDetector(logger.monitorDetector(filtered));
    propagator.propagate(orbit.getDate().shiftedBy(Constants.JULIAN_DAY));
    List<LoggedEvent> events = logger.getLoggedEvents();
    Assert.assertEquals(4, events.size());
    Assert.assertEquals(
        6 * 3600, events.get(0).getState().getDate().durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(
        7 * 3600, events.get(1).getState().getDate().durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(
        8 * 3600, events.get(2).getState().getDate().durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(
        9 * 3600, events.get(3).getState().getDate().durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(4, reset.size());
    Assert.assertEquals(6 * 3600, reset.get(0).durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(7 * 3600, reset.get(1).durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(8 * 3600, reset.get(2).durationFrom(orbit.getDate()), 1.0e-6);
    Assert.assertEquals(9 * 3600, reset.get(3).durationFrom(orbit.getDate()), 1.0e-6);
  }