package brn.swans.app.rtcp;

import jist.runtime.JistAPI;
import jist.swans.misc.Pickle;

/**
 * The class SenderReport represents an rtp sender report as contained in an
 * RTCPSenderReportPacket.
 */
public class SenderReport implements JistAPI.Timeless {

  // ////////////////////////////////////////////////
  // constants
  //

  // ////////////////////////////////////////////////
  // locals
  //

  /**
   * Size of the sender info = 5 * 4 octets
   */
  public static final int HEADER_SIZE = 5 * 4;

  /**
   * The ntp time stamp (unsigned).
   */
  protected long ntpTimeStamp;

  /**
   * The rtp time stamp (unsigned).
   */
  protected int rtpTimeStamp;

  /**
   * The number of packets sent (unsigned).
   */
  protected int packetCount;

  /**
   * The number of (payload) bytes sent (unsigned).
   */
  protected int byteCount;

  // ////////////////////////////////////////////////
  // initialization
  //

  /**
   * Default constructior.
   */
  public SenderReport() {
    this.ntpTimeStamp = 0;
    this.rtpTimeStamp = 0;
    this.packetCount = 0;
    this.byteCount = 0;
  }

  // ////////////////////////////////////////////////
  // accessors
  //

  public SenderReport(byte[] msg, int offset) {
    // Bytes 8-11: ntp timestamp, most significant
    ntpTimeStamp = Pickle.arrayToUInt(msg, offset) << 32;
    // Bytes 12-15: ntp timestamp, least significant
    ntpTimeStamp += Pickle.arrayToUInt(msg, offset + 4);
    // Bytes 16-19: rtp timestamp
    rtpTimeStamp = (int)Pickle.arrayToUInt(msg, offset + 8);
    // Bytes 20-23: senders packet count
    packetCount = (int)Pickle.arrayToUInt(msg, offset + 12);
    // Bytes 24-27: senders octet count
    byteCount = (int)Pickle.arrayToUInt(msg, offset + 16);
  }

  public int getByteCount() {
    return byteCount;
  }

  public void setByteCount(int byteCount) {
    this.byteCount = byteCount;
  }

  public long getNtpTimeStamp() {
    return ntpTimeStamp;
  }

  public void setNtpTimeStamp(long ntpTimeStamp) {
    this.ntpTimeStamp = ntpTimeStamp;
  }

  public int getPacketCount() {
    return packetCount;
  }

  public void setPacketCount(int packetCount) {
    this.packetCount = packetCount;
  }

  public int getRtpTimeStamp() {
    return rtpTimeStamp;
  }

  public void setRtpTimeStamp(int rtpTimeStamp) {
    this.rtpTimeStamp = rtpTimeStamp;
  }


  // ////////////////////////////////////////////////
  // overwrites
  //

  public String toString() {
    return ("SenderReport [" + "ntpTimeStamp=" + ntpTimeStamp
        + ", rtpTimeStamp=" + rtpTimeStamp + ", packetCount=" + packetCount
        + ", byteCount=" + byteCount + "]");
  }


  // ////////////////////////////////////////////////
  // implementation
  //

  public void getBytes(byte[] msg, int offset) {
    // Bytes 8-11: ntp timestamp, most significant
    Pickle.uintToArray((ntpTimeStamp >> 32) & 0xFFFFFFFF, msg, offset);
    // Bytes 12-15: ntp timestamp, least significant
    Pickle.uintToArray(ntpTimeStamp & 0xFFFFFFFF, msg, offset + 4);
    // Bytes 16-19: rtp timestamp
    Pickle.uintToArray(rtpTimeStamp, msg, offset + 8);
    // Bytes 20-23: senders packet count
    Pickle.uintToArray(packetCount, msg, offset + 12);
    // Bytes 24-27: senders octet count
    Pickle.uintToArray(byteCount, msg, offset + 16);
  }

  /* (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
  public int hashCode() {
    final int PRIME = 31;
    int result = 1;
    result = PRIME * result + byteCount;
    result = PRIME * result + (int) (ntpTimeStamp ^ (ntpTimeStamp >>> 32));
    result = PRIME * result + packetCount;
    result = PRIME * result + rtpTimeStamp;
    return result;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    final SenderReport other = (SenderReport) obj;
    if (byteCount != other.byteCount)
      return false;
    if (ntpTimeStamp != other.ntpTimeStamp)
      return false;
    if (packetCount != other.packetCount)
      return false;
    if (rtpTimeStamp != other.rtpTimeStamp)
      return false;
    return true;
  }

}
