package brn.swans.app.rtp;

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import jist.runtime.JistAPI;
import jist.swans.misc.Message;
import jist.swans.misc.Util;
import jist.swans.net.NetAddress;

import org.apache.log4j.Logger;

import brn.swans.app.rtp.msg.RtpMessage;

/**
 * The class RTPPayloadReceiver acts as a base class for modules processing
 * incoming rtp data packets.
 */
public abstract class RtpPayloadReceiver {

  /**
   * Logger.
   */
  public static final Logger log = Logger.getLogger(RtpPayloadReceiver.class.getName());

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

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

  protected class Output implements JistAPI.DoNotRewrite {
    /**
     * The output file stream.
     */
    private OutputStream outputStream;

    /**
     * This method is called by initialize and opens the output file stream. For
     * most payload receivers this method works well, only when using a library
     * for a payload type which provides an own open method it must be
     * overwritten.
     * @throws IOException 
     */
    public void openOutputFile(String fileName) throws IOException {
      if (null != fileName)
        outputStream = new BufferedOutputStream(new FileOutputStream(fileName)); 
    }

    /**
     * Closes the output file stream.
     */
    public void closeOutputFile() throws IOException {
      if (null != outputStream)
        outputStream.close();
    }

    public void write(byte[] b) throws IOException {
      if (null == RtpPayloadReceiver.this.outputFileName)
        return; // pass
      
      if (null == outputStream) {
        RtpPayloadReceiver.this.openOutputFile(RtpPayloadReceiver.this.outputFileName);
      }

      outputStream.write(b);
    }
  }
  
  protected Output output = new Output();;
  
  /**
   * The payload type this RTPPayloadReceiver module processes.
   */
  protected int payloadType;

  /**
   * An output vector used to store arrival of rtp data packets.
   */
  protected List packetArrival;

  protected RtpProfile rtpProfile;

  private String outputFileName;

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

  public RtpPayloadReceiver() {
    this.outputFileName = null;
    this.packetArrival = new ArrayList();
  }

  // ////////////////////////////////////////////////
  // entity hookup
  //

  /**
   * Hook up with the rtp profile entity.
   * 
   * @param profile
   *          profile entity
   */
  public void setProfile(RtpProfile profile) {
    this.rtpProfile = profile;
  }

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

  public void setOutputFileName(String outputFileName) {
    this.outputFileName = outputFileName;
  }

  // ////////////////////////////////////////////////
  // overwrites
  //
  
  public String toString() {
    return "RtpPayloadReceiver" + 
      " " + Util.timeSeconds();
  }

  // ////////////////////////////////////////////////
  // called from rtp profile
  //

  /**
   * Writes contents of this RTPPacket into the output file. Must be overwritten
   * by subclasses.
   */
  public void dataIn(Message msg, NetAddress src, int srcPort) {
    RtpMessage packet = (RtpMessage) msg;
    processPacket(packet);
  }

  /**
   * Writes contents of this RTPPacket into the output file. Must be overwritten
   * by subclasses.
   */
  protected void processPacket(RtpMessage packet) {
    if (log.isDebugEnabled())
      log.debug(this + " received packet " + packet);

    packetArrival.add(new Integer(packet.getTimeStamp()));
  }

  // ////////////////////////////////////////////////
  // Internals
  //

  /**
   * This method is called by initialize and opens the output file stream. For
   * most payload receivers this method works well, only when using a library
   * for a payload type which provides an own open method it must be
   * overwritten.
   * @throws IOException 
   */
  protected void openOutputFile(String fileName) throws IOException {
    output.openOutputFile(fileName); 
  }

  /**
   * Closes the output file stream.
   */
  public void leaveSession() {
    try {
      output.closeOutputFile();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }

}
