package brn.swans.app.rtcp.msg;

import java.util.ArrayList;
import java.util.List;

import jist.runtime.Main;
import jist.swans.misc.Pickle;
import jist.swans.misc.Util;

import brn.swans.app.rtcp.ReceptionReport;

/**
 * This class represents rtcp receiver report packets. It can hold 0 to 31
 * ReceptionReports. Also the header field ssrc is included.
 */
public class RtcpReceiverReportMessage extends RtcpMessage {

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

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

  /**
   * The ssrc identifier of the source of this rtcp packet (unsigned).
   */
  protected int ssrc;

  /**
   * The reception reports in this packet are stored here.
   */
  protected List receptionReports;

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

  public RtcpReceiverReportMessage() {
    packetType = RTCP_PT_RR;
    ssrc = 0;
    receptionReports = new ArrayList();

    // an empty rtcp receiver report packet is 4 bytes
    // longer, the ssrc identifier is stored in it
    length += 4;
  }

  public RtcpReceiverReportMessage(byte[] msg, int offset) {
    super(msg, offset);
    receptionReports = new ArrayList();

    if (RTCP_PT_SR == packetType)
      return;

    if (Main.ASSERT)
      Util.assertion(RTCP_PT_RR == packetType);

    // Bytes 4-7: ssrc
    ssrc = (int)Pickle.arrayToUInt(msg, offset + RtcpMessage.COMMON_HEADER_SIZE);

    // Bytes 8-: receiver infos
    for (int i = 0; i < count; i++) {
      ReceptionReport report = new ReceptionReport(msg, offset
          + 4 + COMMON_HEADER_SIZE + i*ReceptionReport.HEADER_SIZE);
      receptionReports.add(report);
    }
  }

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

  public int getSsrc() {
    return ssrc;
  }

  public void setSsrc(int ssrc) {
    this.ssrc = ssrc;
  }

  public List getReceptionReports() {
    return receptionReports;
  }

  /**
   * Adds a receiver report to this receiver report packet.
   */
  public void addReceptionReport(ReceptionReport report) {
    receptionReports.add(report);
    count++;

    // an rtcp receiver report is 24 bytes long
    length += ReceptionReport.HEADER_SIZE;
  }

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

  public String toString() {
    String ret = "RTCPReceiverReportPacket [";
    for (int i = 0; i < receptionReports.size(); i++) {
      ret += receptionReports.get(i).toString();
    }
    return ret + "]";
  }

  /*
   * (non-Javadoc)
   * @see brn.swans.app.rtcp.msg.RtcpMessage#getBytes(byte[], int)
   */
  public void getBytes(byte[] msg, int offset) {
    // Bytes 0-3: get the common header
    super.getCommonHeaderBytes(msg, offset);
    // Bytes 4-7: ssrc
    Pickle.uintToArray(ssrc, msg, offset + COMMON_HEADER_SIZE);
    // Bytes 8-: receiver infos
    for (int i = 0; i < receptionReports.size(); i++) {
      ReceptionReport repo = (ReceptionReport) receptionReports.get(i);
      repo.getBytes(msg, offset + COMMON_HEADER_SIZE + 4 +
          i * ReceptionReport.HEADER_SIZE);
    }
  }

  /* (non-Javadoc)
   * @see java.lang.Object#hashCode()
   */
  public int hashCode() {
    final int PRIME = 31;
    int result = super.hashCode();
    result = PRIME * result + ((receptionReports == null) ? 0 : receptionReports.hashCode());
    result = PRIME * result + ssrc;
    return result;
  }

  /* (non-Javadoc)
   * @see java.lang.Object#equals(java.lang.Object)
   */
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (!super.equals(obj))
      return false;
    if (getClass() != obj.getClass())
      return false;
    final RtcpReceiverReportMessage other = (RtcpReceiverReportMessage) obj;
    if (receptionReports == null) {
      if (other.receptionReports != null)
        return false;
    } else if (!receptionReports.equals(other.receptionReports))
      return false;
    if (ssrc != other.ssrc)
      return false;
    return true;
  }
}
