/*
 * 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 "mrcp_generic_header.h"
#include "apt_string_table.h"

/* string table of mrcp generic-header fields (mrcp_generic_header_id) */
static const apt_string_table_item_t generic_header_string_table[] = {
	{"Active-Request-Id-List",22,2},
	{"Proxy-Sync-Id",         13,0},
	{"Accept-Charset",        14,3},
	{"Content-Type",          12,9},
	{"Content-Id",            10,8},
	{"Content-Base",          12,8},
	{"Content-Encoding",      16,8},
	{"Content-Location",      16,9},
	{"Content-Length",        14,9},
	{"Cache-Control",         13,1},
	{"Logging-Tag",           11,0}, 
};


/* parses mrcp request-id list */
static mrcp_status_t mrcp_request_id_list_parse(mrcp_request_id_list_t *request_id_list, char *value)
{
	char *field;
	request_id_list->count = 0;
	while(*value != '\0' && request_id_list->count < MAX_ACTIVE_REQUEST_ID_COUNT) {
		field = apt_read_field(&value,',',1);
		if(field) {
			request_id_list->ids[request_id_list->count] = apt_size_value_parse(field);
			request_id_list->count++;
		}
	}
	return MRCP_STATUS_SUCCESS;
}

/* generates mrcp request-id list */
static size_t mrcp_request_id_list_generate(mrcp_request_id_list_t *request_id_list, char *value)
{
	size_t i;
	size_t offset = 0;
	for(i=0; i<request_id_list->count; i++) {
		offset += apt_size_value_generate(request_id_list->ids[i],value+offset);
		if(i < request_id_list->count-1) {
			value[offset++] = ',';
		}
	}
	return offset;
}




/* initializes generic-header */
void mrcp_generic_header_init(mrcp_generic_header_t *generic_header)
{
	generic_header->active_request_id_list.count = 0;
	generic_header->proxy_sync_id = NULL;
	generic_header->accept_charset = NULL;
	generic_header->content_type = NULL;
	generic_header->content_id = NULL;
	generic_header->content_base = NULL;
	generic_header->content_encoding = NULL;
	generic_header->content_location = NULL;
	generic_header->content_length = 0;
	generic_header->cache_control = NULL;
	generic_header->logging_tag = NULL;
}

/* destroys generic-header */
void mrcp_generic_header_destroy(mrcp_generic_header_t *generic_header)
{
	/* nothing to do as data is allocated from the memory pool and
	will be destroyed with memory pool */
	mrcp_generic_header_init(generic_header);
}

/* allocates generic-header */
static void* mrcp_generic_header_accsessor_allocate(mrcp_header_base_t *header, apr_pool_t *pool)
{
	mrcp_generic_header_t *generic_header = apr_palloc(pool,sizeof(mrcp_generic_header_t));
	mrcp_generic_header_init(generic_header);
	header->data = generic_header;
	return header->data;
}

/* destroys generic-header */
static void mrcp_generic_header_accsessor_destroy(mrcp_header_base_t *header)
{
	if(header->data) {
		mrcp_generic_header_destroy(header->data);
		header->data = NULL;
	}
}

/* parses generic-header */
static mrcp_status_t mrcp_generic_header_accsessor_parse(mrcp_header_base_t *header, size_t id, char *value, apr_pool_t *pool)
{
	mrcp_generic_header_t *generic_header = header->data;
	mrcp_status_t status = MRCP_STATUS_SUCCESS;
	switch(id)
	{
		case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
			mrcp_request_id_list_parse(&generic_header->active_request_id_list,value);
			break;
		case GENERIC_HEADER_PROXY_SYNC_ID:
			generic_header->proxy_sync_id = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_ACCEPT_CHARSET:
			generic_header->accept_charset = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_TYPE:
			generic_header->content_type = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_ID:
			generic_header->content_id = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_BASE:
			generic_header->content_base = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_ENCODING:
			generic_header->content_encoding = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_LOCATION:
			generic_header->content_location = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_CONTENT_LENGTH:
			generic_header->content_length = apt_size_value_parse(value);
			break;
		case GENERIC_HEADER_CACHE_CONTROL:
			generic_header->cache_control = apr_pstrdup(pool,value);
			break;
		case GENERIC_HEADER_LOGGING_TAG:
			generic_header->logging_tag = apr_pstrdup(pool,value);
			break;
		default:
			status = MRCP_STATUS_FAILURE;
	}
	return status;
}

/* generates generic-header */
static size_t mrcp_generic_header_accsessor_generate(mrcp_header_base_t *header, size_t id, char *value)
{
	size_t length = 0;
	mrcp_generic_header_t *generic_header = header->data;
	switch(id) {
		case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
			if(generic_header->active_request_id_list.count) {
				length = mrcp_request_id_list_generate(&generic_header->active_request_id_list,value);
			}
			break;
		case GENERIC_HEADER_PROXY_SYNC_ID:
			if(generic_header->proxy_sync_id) {
				length = apt_string_value_generate(generic_header->proxy_sync_id,value);
			}
			break;
		case GENERIC_HEADER_ACCEPT_CHARSET:
			if(generic_header->accept_charset) {
				length = apt_string_value_generate(generic_header->accept_charset,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_TYPE:
			if(generic_header->content_type) {
				length = apt_string_value_generate(generic_header->content_type,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_ID:
			if(generic_header->content_id) {
				length = apt_string_value_generate(generic_header->content_id,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_BASE:
			if(generic_header->content_base) {
				length = apt_string_value_generate(generic_header->content_base,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_ENCODING:
			if(generic_header->content_encoding) {
				length = apt_string_value_generate(generic_header->content_encoding,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_LOCATION:
			if(generic_header->content_location) {
				length = apt_string_value_generate(generic_header->content_location,value);
			}
			break;
		case GENERIC_HEADER_CONTENT_LENGTH:
			length = apt_size_value_generate(generic_header->content_length,value);
			break;
		case GENERIC_HEADER_CACHE_CONTROL:
			if(generic_header->cache_control) {
				length = apt_string_value_generate(generic_header->cache_control,value);
			}
			break;
		case GENERIC_HEADER_LOGGING_TAG:
			if(generic_header->logging_tag) {
				length = apt_string_value_generate(generic_header->logging_tag,value);
			}
			break;
		default:
			length = 0;
	}
	return length;
}

/* duplicates generic-header */
static mrcp_status_t mrcp_generic_header_accsessor_duplicate(mrcp_header_base_t *header, const mrcp_header_base_t *src, size_t id, apr_pool_t *pool)
{
	mrcp_generic_header_t *generic_header = header->data;
	const mrcp_generic_header_t *src_generic_header = header->data;
	mrcp_status_t status = MRCP_STATUS_SUCCESS;

	if(!generic_header || !src_generic_header) {
		return MRCP_STATUS_FAILURE;
	}

	switch(id)
	{
		case GENERIC_HEADER_ACTIVE_REQUEST_ID_LIST:
			break;
		case GENERIC_HEADER_PROXY_SYNC_ID:
			generic_header->proxy_sync_id = apr_pstrdup(pool,src_generic_header->proxy_sync_id);
			break;
		case GENERIC_HEADER_ACCEPT_CHARSET:
			generic_header->accept_charset = apr_pstrdup(pool,src_generic_header->accept_charset);
			break;
		case GENERIC_HEADER_CONTENT_TYPE:
			generic_header->content_type = apr_pstrdup(pool,src_generic_header->content_type);
			break;
		case GENERIC_HEADER_CONTENT_ID:
			generic_header->content_id = apr_pstrdup(pool,src_generic_header->content_id);
			break;
		case GENERIC_HEADER_CONTENT_BASE:
			generic_header->content_base = apr_pstrdup(pool,src_generic_header->content_base);
			break;
		case GENERIC_HEADER_CONTENT_ENCODING:
			generic_header->content_encoding = apr_pstrdup(pool,src_generic_header->content_encoding);
			break;
		case GENERIC_HEADER_CONTENT_LOCATION:
			generic_header->content_location = apr_pstrdup(pool,src_generic_header->content_location);
			break;
		case GENERIC_HEADER_CONTENT_LENGTH:
			generic_header->content_length = src_generic_header->content_length;
			break;
		case GENERIC_HEADER_CACHE_CONTROL:
			generic_header->cache_control = apr_pstrdup(pool,src_generic_header->cache_control);
			break;
		case GENERIC_HEADER_LOGGING_TAG:
			generic_header->logging_tag = apr_pstrdup(pool,src_generic_header->logging_tag);
			break;
		default:
			status = MRCP_STATUS_FAILURE;
	}
	return status;
}

/* initializes generic-header accessor */
void mrcp_generic_header_accessor_init(mrcp_header_accessor_t *header_accessor)
{
	header_accessor->allocator = mrcp_generic_header_accsessor_allocate;
	header_accessor->destructor = mrcp_generic_header_accsessor_destroy;

	header_accessor->field_parser = mrcp_generic_header_accsessor_parse;
	header_accessor->field_generator = mrcp_generic_header_accsessor_generate;
	header_accessor->field_duplicator = mrcp_generic_header_accsessor_duplicate;

	header_accessor->field_table = generic_header_string_table;
	header_accessor->field_count = GENERIC_HEADER_COUNT;
}

/* destroys generic-header accessor */
void mrcp_generic_header_accessor_destroy(mrcp_header_accessor_t *header_accessor)
{
	header_accessor->allocator = NULL;
	header_accessor->destructor = NULL;

	header_accessor->field_parser = NULL;
	header_accessor->field_generator = NULL;
	header_accessor->field_duplicator = NULL;

	header_accessor->field_table = NULL;
	header_accessor->field_count = 0;
}
