package w3c.rtsp.common;

import java.io.*;
import java.util.*;
import java.net.*;


public class SdpMedia {

    /**
     * Media type.
     */
    String media = null;
    /**
     * Port number.
     */
    protected int port = -1;
    /**
     * Number of ports.
     */
    protected int nport = 1;
    /**
     * Transport layer used.
     */
    String transport = null;
    /**
     * Format names.
     */
    String formats[] = null;
    /**
     * Media informations
     */
    public String infos[] = null;
    /**
     * Media connection network type.
     */
    String cnettype = null;
    /**
     * Does this media session has asssociated connection data ?
     */
    protected boolean hasConnection = false;
    /**
     * Media connection address type.
     */
    protected String caddrtype = null;
    /**
     * Media connection address.
     */
    protected InetAddress caddr = null;
    /**
     * Media connection time to live.
     */
    protected int cttl = 1;
    /**
     * Media number of multicast groups.
     */
    protected int cnaddr = 1;
    /**
     * Media total conference bandwidth.
     */
    protected int ctbw = -1;
    /**
     * Media application specific bandwidth.
     */
    protected int asbw = -1;
    /**
     * Media attributes.
     */
    SdpAttributes attrs = null;
     
    public String toString(){
	StringBuffer sb = new StringBuffer(256);
	// Media description
	sb.append("m=");
	sb.append(media); 
	sb.append(' '); sb.append(port);
	if ( nport > 1 ) {
	    sb.append('/'); sb.append(nport);
	}
	sb.append(' '); sb.append(transport);
	for (int i = 0 ; i < formats.length ; i++) {
	    sb.append(' '); sb.append(formats[i]);
	}
	sb.append('\n');
	// Session infos:
	if ( infos != null ) {
	    for (int i = 0 ; i < infos.length ; i++) {
		sb.append("i="); sb.append(infos[i]);
		sb.append('\n');
	    }
	}
	// Connection data:
	if ( hasConnection ) {
	    sb.append("c="); 
	    sb.append(cnettype);
	    sb.append(' '); sb.append(caddrtype);
	    sb.append(' '); sb.append(caddr.getHostAddress()); 
	    sb.append('/'); sb.append(cttl);
	    if ( cnaddr > 1 ) {
		sb.append('/'); sb.append(cnaddr);
	    }
	    sb.append('\n');
	}
	// Bandwidth:
	if ( ctbw > 0 ) {
	    sb.append("b=CT:"); sb.append(ctbw); 
	    sb.append('\n');
	} 
	if ( asbw > 0 ) {
	    sb.append("b=AS:"); sb.append(asbw);
	    sb.append('\n');
	}
	// Attributes:
	attrs.dump(sb);

	System.out.println("\nSESSION in SDp media:"+sb.toString());

	return new String(sb.toString());
    }

    public void addInfos(String info) {
	String s[] = null;
	int    o   = 0;
	if ( infos != null ) {
	    o = infos.length;
	    s = new String[o+1];
	    System.arraycopy(infos, 0, s, 0, o);
	} else {
	    s = new String[1];
	} 
	s[o] = info;
    }

    public void setConnectionData(String ctype, String atype
				  , InetAddress addr
				  , int ttl, int naddr) {
	hasConnection = true;
	this.cnettype  = ctype;
	this.caddrtype = atype;
	this.caddr     = addr;
	this.cnaddr    = cnaddr;
    }

    public void setConferenceTotalBandwidth(int ctbw) {
	this.ctbw = ctbw;
    }

    public void setApplicationSpecificBandwidth(int asbw) {
	this.asbw = asbw;
    }

    /**
     * Add an attribute to that media description.
     * @param key The name of the attribute.
     * @param val The value for that attribute.
     */

    public void addAttribute(String key, String val) {
	if ( val == null )
	    attrs.addFlag(key);
	else
	    attrs.addAttribute(key, val);
    }

    /**
     * Remove an attribute definition.
     * Removes all values for that attribute.
     * @param key The attribute name.
     */

    public void removeAttribute(String key) {
	attrs.removeAttribute(key);
    }

    /**
     * Get the first value of an attribute.
     * @param key The attribute name.
     * @return A String instance, or <strong>null</strong>.
     */

    public String getAttributeValue(String key) {
	return attrs.getValue(key);
    }

    /**
     * Get all mappings of an attribute.
     * @param key The name of the attribute.
     * @return A String array, which might have a zero length (to indicate
     * a <i>flag</i>), or <strong>null</strong>.
     */

    public String[] getAttributeValues(String key) {
	return attrs.getValues(key);
    }

    /**
     * Get the max TTL for that media.
     * @return A integer ttl value.
     */

    public int getTimeToLive() {
	return cttl;
    }

    /**
     * Set this media's time to live.
     * @param ttl The new ttl value for that media.
     */

    public void setTimeToLive(int ttl) {
	this.cttl = Math.min(ttl, 255);
    }

    public SdpMedia(){
    }

    public SdpMedia(String media
		    , int port, int nport
		    , String transport
		    , String formats[]) {
	this.media     = media;
	this.port      = port;
	this.nport     = nport;
	this.transport = transport;
	this.formats   = formats;
	this.attrs     = new SdpAttributes();
    }

   public SdpMedia(String media
		    , int port
		    , String transport
		    , String formats) {
	this.media     = media;
	this.port      = port;
	this.transport = transport;
	this.formats=new String[2];
	this.formats[0]  = formats;
	this.attrs     = new SdpAttributes();
    }

    public int getPort(){
      return this.port;
    }
  
    public String getMedia(){
    return this.media;
    }

   public String getTransport(){
      return this.transport;
    }
  
    public String getFormat(){
    return this.formats[0];
    }
}
