package brn.swans.app.rtcp.msg;

import java.util.ArrayList;

import jist.runtime.Main;
import jist.swans.misc.Pickle;
import jist.swans.misc.Util;
import brn.swans.app.rtcp.ReceptionReport;
import brn.swans.app.rtcp.SenderReport;

/**
 * This class represents rtcp sender report packets. A rtcp sender report packet
 * is very similar to an rtcp receiver report packet with the only difference
 * that it includes exactly one sender report. To express this similarity it is
 * a subclass of RTPReceiverReportPacket.
 */
public class RtcpSenderReportMessage extends RtcpReceiverReportMessage {

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

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

  /**
   * The sender report stored in the packet.
   */
  protected SenderReport senderReport;

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

  public RtcpSenderReportMessage() {
    packetType = RTCP_PT_SR;
    senderReport = new SenderReport();

    // a sender report is 20 bytes long
    length += 20;
  }

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

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

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

    // Bytes 8-27: sender info
    senderReport = new SenderReport(msg, offset + COMMON_HEADER_SIZE + 4);

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


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

  public SenderReport getSenderReport() {
    return senderReport;
  }

  public void setSenderReport(SenderReport senderReport) {
    this.senderReport = senderReport;
  }

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

  public String toString() {
    String ret = "RTCPSenderReportPacket [senderReport=";
    ret += senderReport.toString();
    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-27: sender info
    senderReport.getBytes(msg, offset + COMMON_HEADER_SIZE + 4);
    // Bytes 28-: receiver infos
    for (int i = 0; i < receptionReports.size(); i++) {
      ReceptionReport repo = (ReceptionReport) receptionReports.get(i);
      repo.getBytes(msg, offset + COMMON_HEADER_SIZE + 4 +
          SenderReport.HEADER_SIZE + 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 + ((senderReport == null) ? 0 : senderReport.hashCode());
    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 RtcpSenderReportMessage other = (RtcpSenderReportMessage) obj;
    if (senderReport == null) {
      if (other.senderReport != null)
        return false;
    } else if (!senderReport.equals(other.senderReport))
      return false;
    return true;
  }
}
