package nxm.net.test.junit.lib;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import nxm.net.lib.RTPHeader;
import nxm.sys.lib.Midas;
import nxm.sys.test.junit.NMTestCase;

/**
 * Tests RTPHeader
 * @author Jeanette McCall
 * @since NeXtMidas 3.8.1
 */
public class RTPHeaderTest extends NMTestCase {

  /** public constructor to allow running this test case directly with JUnit.
   *  @param midas      The midas context to use when running the tests.
  */
  public RTPHeaderTest (String methodName) {
    this(methodName, null);
  }

  /** This constructor is required by NeXtMidas Unit Testing framework.
      @param methodName The name of the method being called.
      @param midas      The midas context to use when running the tests.
  */
  public RTPHeaderTest (String methodName, Midas midas) {
    super(methodName, midas);
  }

  /** test addToSeqNumberWithWrap */
  public void testAddToSeqNumberWithWrap () {
    Method methodAddToSeqNumberWithWrap;
    try {
      methodAddToSeqNumberWithWrap = RTPHeader.class.getDeclaredMethod("addToSeqNumberWithWrap", Integer.TYPE, Integer.TYPE);
      methodAddToSeqNumberWithWrap.setAccessible(true);
      int wrappedValue = (int)methodAddToSeqNumberWithWrap.invoke(RTPHeader.class,0xFFFE,5);
      assertEquals("RTPHeader.addToSeqNumberWithWrap 0xFFFE + 5", 3, wrappedValue);
      wrappedValue = (int)methodAddToSeqNumberWithWrap.invoke(RTPHeader.class,20,-21);
      assertEquals("RTPHeader.addToSeqNumberWithWrap 20 - 21", 0xFFFF, wrappedValue);
      wrappedValue = (int)methodAddToSeqNumberWithWrap.invoke(RTPHeader.class,20,2000);
      assertEquals("RTPHeader.addToSeqNumberWithWrap 20 + 2000", 2020, wrappedValue);
    } catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("RTPHeaderTest testAddToSeqNumberWithWrap failed", e);
    }
  }

  /** test computeNumPktsAhead */
  public void testComputeNumPktsAhead () {
    Method methodComputeNumPktsAhead;
    try {
      methodComputeNumPktsAhead = RTPHeader.class.getDeclaredMethod("computeNumPktsAhead", Integer.TYPE, Integer.TYPE);
      methodComputeNumPktsAhead.setAccessible(true);
      int ahead = (int)methodComputeNumPktsAhead.invoke(RTPHeader.class,0xFFFE,5);
      assertEquals("RTPHeader.computeNumPktsAhead current:0xFFFE previous:5", -7, ahead);
      ahead = (int)methodComputeNumPktsAhead.invoke(RTPHeader.class,8,0xFFF8);
      assertEquals("RTPHeader.computeNumPktsAhead current:8 previous:0xFFF8", 16, ahead);
      ahead = (int)methodComputeNumPktsAhead.invoke(RTPHeader.class,8,-1);
      assertEquals("RTPHeader.computeNumPktsAhead current:8 previous:NOT_INITIALIZED", 1, ahead);
    } catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("RTPHeaderTest testAddToSeqNumberWithWrap failed", e);
    }
  }

  /** test computeNumPktsBetween */
  public void testComputeNumPktsBetween () {
    Method methodComputeNumPktsBetween;
    try {
      methodComputeNumPktsBetween = RTPHeader.class.getDeclaredMethod("computeNumPktsBetween", Integer.TYPE, Integer.TYPE);
      methodComputeNumPktsBetween.setAccessible(true);
      int between = (int)methodComputeNumPktsBetween.invoke(RTPHeader.class,0xFFFE,5);
      assertEquals("RTPHeader.computeNumPktsBetween current:0xFFFE previous:5", 6, between);
      between = (int)methodComputeNumPktsBetween.invoke(RTPHeader.class,8,0xFFF8);
      assertEquals("RTPHeader.computeNumPktsBetween current:8 previous:0xFFF8", 15, between);
      between = (int)methodComputeNumPktsBetween.invoke(RTPHeader.class,8,-1);
      assertEquals("RTPHeader.computeNumPktsBetween current:8 previous:NOT_INITIALIZED", 0, between);
    } catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("RTPHeaderTest testAddToSeqNumberWithWrap failed", e);
    }
  }

  /** test decrementAndWrapSeqNum */
  public void testDecrementAndWrapSeqNum () {
    Method methodDecrementAndWrapSeqNum;
    try {
      methodDecrementAndWrapSeqNum = RTPHeader.class.getDeclaredMethod("decrementAndWrapSeqNum", Integer.TYPE);
      methodDecrementAndWrapSeqNum.setAccessible(true);
      int incrValue = (int)methodDecrementAndWrapSeqNum.invoke(RTPHeader.class,0);
      assertEquals("RTPHeader.decrementAndWrapSeqNum original:0", 0xFFFF, incrValue);
    } catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("RTPHeaderTest testAddToSeqNumberWithWrap failed", e);
    }
  }

  /** test incrementAndWrapSeqNum */
  public void testIncrementAndWrapSeqNum () {
    Method methodIncrementAndWrapSeqNum;
    try {
      methodIncrementAndWrapSeqNum = RTPHeader.class.getDeclaredMethod("incrementAndWrapSeqNum", Integer.TYPE);
      methodIncrementAndWrapSeqNum.setAccessible(true);
      int decValue = (int)methodIncrementAndWrapSeqNum.invoke(RTPHeader.class,0xFFFF);
      assertEquals("RTPHeader.decrementAndWrapSeqNum original:0", 0, decValue);
    } catch (NoSuchMethodException | SecurityException | InvocationTargetException | IllegalAccessException e) {
      throw new RuntimeException("RTPHeaderTest testAddToSeqNumberWithWrap failed", e);
    }
  }


}
