package nxm.net.lib;

import nxm.net.lib.DatagramData.RTCPCallBack;
import nxm.sys.inc.DataTypes;
import nxm.sys.inc.InternalUseOnly;
import nxm.sys.inc.ProvisionalUseOnly;
import nxm.sys.lib.Convert;

/** Utility class for parsing an RTCP Header
 * <pre>
 *  The Real Time Control Protocol header has the following format:
 * 0                   1                   2                   3
 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|V=2|P|   RC    |  PT=SR=200    |           length              |
 *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *|        synchronization source (SSRC) identifier of sender     |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|             NTP timestamp, most significant word              |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|            NTP timestamp, least significant word              |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                         RTP timestamp                         |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                    sender's packet count                      |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                    sender's octet count                       |
 *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *|  synchronization source (SSRC\_1) identifier of first source  |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *| fraction lost |      cumulative number of packets lost        |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|           extended highest sequence number received           |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                      interarrival jitter                      |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                         last SR (LSR)                         |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                   delay since last SR (LSR)                   |
 *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *| synchronization source (SSRC\_2) identifier of second source  |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *|                             ....                              |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *|                  profile specific extensions                  |
 *+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * </pre>
 * <b>This class is under development, do not touch!!!!!</b>
 * @author Jeanette McCall
 * @since NeXtMidas 3.8.1
 *
 */
@InternalUseOnly
public class RTCPHeader {

  /** Byte containing RTCP Version, P (Padding), RC -
   * i.e. number of identifiers that follow the fixed header) */
  static final byte VPRC_BYTE=0;
  /** Byte containing RTCP PT (Payload Type) */
  static final byte PT_BYTE=1;
  /** Byte containing RTCP Length (high octet) */
  static final byte LGTHH_BYTE=2;
  /** Byte containing RTCP Length (high octet) */
  static final byte LGTHL_BYTE=3;
  /** First byte containing RTP SSRC (synchronization source identifier) */
  private static final byte SSRC_BYTE=4;
  /** First byte containing most significant word of NTP Timestamp */
  static final byte NTPTSH_BYTE=8;
  /** First byte containing least significant word of NTP Timestamp */
  static final byte NTPTSL_BYTE=12;
  /** First byte containing RTCP Timestamp */
  static final byte TS_BYTE=16;

  private String invalidMessage = null;

  /** RTCP Payload type: ITU-T G.711 PCM Mu-Law audio */
  @ProvisionalUseOnly("API could change")
  public static final int PAYLOADTYPE_AUDIO_MULAW = 0;
  /** RTCP Payload type: Linear audio */
  @ProvisionalUseOnly("API could change")
  public static final int PAYLOADTYPE_AUDIO_LINEAR = 96;
  /** RTCP Payload type: Speex audio */
  @ProvisionalUseOnly("API could change")
  public static final int PAYLOADTYPE_AUDIO_SPEEX = 101;
  /** RTCP Payload type: Raw */
  @ProvisionalUseOnly("API could change")
  public static final int PAYLOADTYPE_RAW = 97;
  /** RTCP Payload type: Spectral ? */
  @ProvisionalUseOnly("API could change")
  public static final int PAYLOADTYPE_SPECTRA = 98;

  /** Mask for RC count */
  private static final int RC_MASK      = 0x1F;
  /** Mask for Padding */
  private static final int P_MASK       = 0x20;
  /** Mask for Version */
  private static final int VERSION_MASK = 0xC0;
  /** Mask for Payload Type */
  private static final int PT_MASK      = 0x7F;

  /** Mask for lower byte worth of integer */
  private static final int LOWER_BYTE_MASK = 0x000000FF;

  /** Maximum sequence value */
  static int MAX_SEQUENCE_VAL = 0xFFFF;

  /** Maximum gap in sequence number before sequence number is assumed to be behind rather than ahead */
  static int MAX_AHEAD_SEQUENCE_NUM = (int) (MAX_SEQUENCE_VAL * 0.7);

  /** Indicates that this value is not available */
  private static final int NOT_AVAILABLE = -1;

  /** bytes per word */
  @InternalUseOnly
  public static final int BYTES_PER_WORD = 4;

  /** RC                      */
  private int rc        = 0;
  /** P (Padding)             */
  private int padding   = 0;
  /** Version                 */
  private int version   = 0;
  /** PT (Payload Type)       */
  private int payload   = 0;
  /** Length                  */
  private int length    = -1;
  /** Extension Type          */
  private int xtype     = 0;
  /** Extension Length (Bytes)*/
  private int xlenBytes = 0;
  /** Header Length           */
  private int headerLen = 0;
  /** Timestamp               */
  private int timeStamp = 0;
  /** SSRC (Synchronization source identifier */
  private int ssrc      = 0;

  /** return code for is RTCP packet */
  static final int RTCP_STOP_PARSE_RETURN_CODE = 0;
  /** Return code for is RTCP packet and do parse */
  static final int RTCP_DO_PARSERETURN_CODE = 1;
  /** Return code for not RTCP packet */
  static final int RTCP_NOT_VALID_RETURN_CODE = 2;

  /** static methods, so no constructor is needed */
  private RTCPHeader () {}

  /** Check if this is an RTCP Packet
   *  @param buf         buffer containing header
   *  @param  ignore_rtcp true if ignoring RTCP packets
   *  @param  rtcpCB      true if we are doing RTCP callback
   *  @return RTCP_STOP_PARSE_RETURN_CODE, RTCP_DO_PARSERETURN_CODE, or RTCP_NOT_VALID_RETURN_CODE
   */
  public static int isRtcpPacket(byte[] buf, boolean ignore_rtcp, RTCPCallBack rtcpCB) {
    if (buf[VPRC_BYTE]>=194 && buf[VPRC_BYTE]<=210) { //check for usual RTCP cases
      if (ignore_rtcp) return RTCP_STOP_PARSE_RETURN_CODE;
      if (rtcpCB!=null) {
        //all RTCP packets are supposed to be compound starting with either 200 or 201 - SR, RR
        if (buf[VPRC_BYTE]==200 || buf[VPRC_BYTE]==201) return RTCP_DO_PARSERETURN_CODE;
        return RTCP_STOP_PARSE_RETURN_CODE;
      }
    }
    return RTCP_NOT_VALID_RETURN_CODE;
  }

  /**
   * Utility method to return the sequence number of the RTPHeader
   * @param     rtpBuf The buffer containing the header
   * @param     offset Offset to where the start of the header is located in the rtpBuf
   * @return    The length of the RTCP Packet
   */

  public static int parseLength(byte[] rtpBuf, int offset) {
    return Convert.unpackI(rtpBuf, offset+LGTHH_BYTE, DataTypes.IEEE);
  }

//  /** Get Reception report count (RC)
//   *  @return the number of reception report blocks contained in this packet
//   */
//  public int getRc () {
//    return rc;
//  }
//
//  /** @return the number of extra padding bytes at the end of the RTP packet */
//  public int getPadding () {
//    return padding;
//  }
//
//  /** @return the version of RTP */
//  public int getVersion () {
//    return version;
//  }
//
//  /** @return the payload type */
//  public int getPayload () {
//    return payload;
//  }
//
//  /** @return the length of this RTCP packet */
//  public int getLength () {
//    return length;
//  }
//
//  /** @return the Extension Type */
//  public int getXtype () {
//    return xtype;
//  }
//
//  /** @return the xlenBytes in bytes */
//  public int getXlenBytes () {
//    return xlenBytes;
//  }
//
//  /** @return length of this RTCP packet */
//  public int getHeaderLen () {
//    return headerLen;
//  }
//
//  /** @return the time stamp */
//  public int getTimeStamp () {
//    return timeStamp;
//  }
//
//  /** @return the SSRC (Synchronization source identifier) */
//  public int getSsrc () {
//    return ssrc;
//  }

}
