// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.

package org.wpilib.math.filter;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.wpilib.util.WPIUtilJNI;

class EdgeCounterFilterTest {
  @BeforeEach
  void setUp() {
    WPIUtilJNI.enableMockTime();
    WPIUtilJNI.setMockTime(0L);
  }

  @AfterEach
  void tearDown() {
    WPIUtilJNI.setMockTime(0L);
    WPIUtilJNI.disableMockTime();
  }

  @Test
  void edgeCounterFilterActivatedTest() {
    var filter = new EdgeCounterFilter(2, 0.2);

    assertFalse(filter.calculate(true)); // First edge

    WPIUtilJNI.setMockTime(50_000L);
    assertFalse(filter.calculate(false)); // First edge ended

    WPIUtilJNI.setMockTime(100_000L);
    assertTrue(filter.calculate(true)); // Second edge

    WPIUtilJNI.setMockTime(150_000L);
    assertTrue(filter.calculate(true)); // Still true

    WPIUtilJNI.setMockTime(250_000L);
    assertTrue(filter.calculate(true)); // Still true

    WPIUtilJNI.setMockTime(300_000L);
    assertFalse(filter.calculate(false)); // Input false, should reset
  }

  @Test
  void edgeCounterFilterExpiredTest() {
    var filter = new EdgeCounterFilter(2, 0.2);

    assertFalse(filter.calculate(true)); // First edge

    WPIUtilJNI.setMockTime(50_000L);
    filter.calculate(false); // First edge ended

    WPIUtilJNI.setMockTime(250_000L);
    assertFalse(filter.calculate(true)); // Second edge after window expired

    WPIUtilJNI.setMockTime(300_000L);
    assertFalse(filter.calculate(true)); // Still false
  }

  @Test
  void edgeCounterFilterParamsTest() {
    var filter = new EdgeCounterFilter(2, 0.2);

    assertEquals(filter.getRequiredEdges(), 2);
    assertEquals(filter.getWindowTime(), 0.2);

    filter.setRequiredEdges(3);

    assertEquals(filter.getRequiredEdges(), 3);

    filter.setWindowTime(0.5);

    assertEquals(filter.getWindowTime(), 0.5);
  }
}
