/*
 * OpenMRCP - Open Source Media Resource Control Protocol Stack
 * Copyright (C) 2007, Cepstral LLC
 *
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Author(s):
 * Arsen Chaloyan <achaloyan@yahoo.com>
 *
 * Contributor(s):
 *
 */

#include "rtsp_header.h"
#include "apt_string_table.h"

/* string table of RTSP header fields (rtsp_header_field_id) */
static const apt_string_table_item_t rtsp_header_string_table[] = {
	{"CSeq",           4,1},
	{"Transport",      9,0},
	{"Session",        7,0},
	{"RTP-Info",       8,0},
	{"Content-Type",  12,8},
	{"Content-Length",14,8}, 
};

/* string table of RTSP content types (rtsp_content_type) */
static const apt_string_table_item_t rtsp_content_type_string_table[] = {
	{"application/sdp", 15,12},
	{"application/mrcp",16,12},
};

/* string table of RTSP trasnport profiles (rtsp_transport_profile_t) */
static const apt_string_table_item_t rtsp_profile_string_table[] = {
	{"RTP/AVP", 7,4},
	{"RTP/SAVP",8,4},
};

/* string table of RTSP trasnport delivery param (rtsp_delivery_t) */
static const apt_string_table_item_t rtsp_delivery_string_table[] = {
	{"unicast",  7,0},
	{"multicast",9,0},
};

/** Parse RTSP transport */
static apt_bool_t rtsp_trasnport_parse(rtsp_transport_t *transport, char *line)
{
	/* to be done */
	transport->profile = RTSP_PROFILE_RTP_AVP;
	transport->lower_transport = RTSP_LOWER_TRANSPORT_UDP;
	transport->delivery = RTSP_DELIVERY_UNICAST;

	return TRUE;
}

/** Generate RTSP trasnport */
static size_t rtsp_trasnport_generate(rtsp_transport_t *transport, char *line)
{
	size_t length = 0;
	const char *profile = apt_string_table_get(rtsp_profile_string_table,RTSP_PROFILE_COUNT,transport->profile);
	if(!profile) {
		return 0;
	}
	length += apt_string_value_generate(profile,line + length);

	if(transport->delivery != RTSP_DELIVERY_NONE) {
		int ret;
		const char *delivery = apt_string_table_get(rtsp_delivery_string_table,RTSP_DELIVERY_COUNT,transport->delivery);
		if(!delivery) {
			return 0;
		}
		
		ret = sprintf(line+length,";%s",delivery);
		if(ret < 0) {
			ret = 0;
		}
		length += ret;
	}

	if(transport->client_port_range.min != transport->client_port_range.max) {
		int ret = sprintf(line+length,";client_port=%hu-%hu",transport->client_port_range.min,transport->client_port_range.max);
		if(ret < 0) {
			ret = 0;
		}
		length += ret;
	}
	if(transport->server_port_range.min != transport->server_port_range.max) {
		int ret = sprintf(line+length,";server_port=%hu-%hu",transport->server_port_range.min,transport->server_port_range.max);
		if(ret < 0) {
			ret = 0;
		}
		length += ret;
	}
	return length;
}


/** Parse RTSP header field */
apt_bool_t rtsp_header_field_parse(rtsp_header_t *header, rtsp_header_field_id id, char *value, apr_pool_t *pool)
{
	apt_bool_t status = TRUE;
	switch(id) {
		case RTSP_HEADER_FIELD_CSEQ:
			header->cseq = apt_size_value_parse(value);
			break;
		case RTSP_HEADER_FIELD_TRANSPORT:
			rtsp_trasnport_parse(&header->transport,value);
			break;
		case RTSP_HEADER_FIELD_SESSION_ID:
			header->session_id = apr_pstrdup(pool,value);
			break;
		case RTSP_HEADER_FIELD_RTP_INFO:
			header->rtp_info = apr_pstrdup(pool,value);
			break;
		case RTSP_HEADER_FIELD_CONTENT_TYPE:
			header->content_type = apt_string_table_find(rtsp_content_type_string_table,RTSP_CONTENT_TYPE_COUNT,value);
			break;
		case RTSP_HEADER_FIELD_CONTENT_LENGTH:
			header->content_length = apt_size_value_parse(value);
			break;
		default:
			status = FALSE;
	}
	return status;
}

/** Generate RTSP header field */
static size_t rtsp_header_field_generate(rtsp_header_t *header, size_t id, char *value)
{
	size_t length = 0;
	switch(id) {
		case RTSP_HEADER_FIELD_CSEQ:
			length = apt_size_value_generate(header->cseq,value);
			break;
		case RTSP_HEADER_FIELD_TRANSPORT:
			if(header->transport.profile != RTSP_PROFILE_NONE) {
				length = rtsp_trasnport_generate(&header->transport,value);
			}
			break;
		case RTSP_HEADER_FIELD_SESSION_ID:
			if(header->session_id) {
				length = apt_string_value_generate(header->session_id,value);
			}
			break;
		case RTSP_HEADER_FIELD_RTP_INFO:
			if(header->rtp_info) {
				length = apt_string_value_generate(header->rtp_info,value);
			}
			break;
		case RTSP_HEADER_FIELD_CONTENT_TYPE:
			if(header->content_type != RTSP_CONTENT_TYPE_NONE) {
				const char *name = apt_string_table_get(rtsp_content_type_string_table,RTSP_CONTENT_TYPE_COUNT,header->content_type);
				if(name) {
					length = apt_string_value_generate(name,value);
				}
			}
			break;
		case RTSP_HEADER_FIELD_CONTENT_LENGTH:
			length = apt_size_value_generate(header->content_length,value);
			break;
	}
	return length;
}


/** Parse RTSP header */
apt_bool_t rtsp_header_parse(rtsp_header_t *header, apt_text_stream_t *text_stream, apr_pool_t *pool)
{
	char *line;
	apt_name_value_pair_t header_field;

	do {
		line = apt_read_line(text_stream);
		if(!line) {
			return FALSE;
		}
		if(*line == '\0') {
			break;
		}
		if(apt_name_value_pair_parse(&header_field,line) == TRUE) {
			/* parse header_field (name/value) */
			rtsp_header_field_id id = apt_string_table_find(rtsp_header_string_table,RTSP_HEADER_FIELD_COUNT,header_field.name);
			if(id < RTSP_HEADER_FIELD_COUNT) {
				if(rtsp_header_field_parse(header,id,header_field.value,pool) == TRUE) {
					rtsp_header_property_add(&header->property_set,id);
				}
			}
		}
	}
	while(line);

	return TRUE;
}

/** Generate RTSP header */
apt_bool_t rtsp_header_generate(rtsp_header_t *header, apt_text_stream_t *text_stream)
{
	const char *name;
	size_t i;
	rtsp_header_property_set_t property_set;

	property_set = header->property_set;
	for(i=0; i<RTSP_HEADER_FIELD_COUNT && property_set != 0; i++) {
		if(rtsp_header_property_check(&property_set,i) == TRUE) {
			name = apt_string_table_get(rtsp_header_string_table,RTSP_HEADER_FIELD_COUNT,i);
			if(!name) {
				continue;
			}
			
			text_stream->pos += apt_name_value_generate_name(name,text_stream->pos);
			text_stream->pos += rtsp_header_field_generate(header,i,text_stream->pos);
			apt_insert_end_of_line(text_stream);
			
			rtsp_header_property_remove(&property_set,i);
		}
	}
	apt_insert_end_of_line(text_stream);
	return TRUE;
}
