/* $Id: rpid.c 4537 2013-06-19 06:47:43Z riza $ */
/* 
 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
#include <pjsip-simple/rpid.h>
#include <pjsip-simple/errno.h>
#include <pj/assert.h>
#include <pj/guid.h>
#include <pj/pool.h>
#include <pj/string.h>


static const pj_str_t DM_NAME = {"xmlns:dm", 8};
static const pj_str_t DM_VAL = {"urn:ietf:params:xml:ns:pidf:data-model", 38};
static const pj_str_t RPID_NAME = {"xmlns:rpid", 10};
static const pj_str_t RPID_VAL = {"urn:ietf:params:xml:ns:pidf:rpid", 32};

static const pj_str_t DM_NOTE = {"dm:note", 7};
static const pj_str_t DM_PERSON = {"dm:person", 9};
static const pj_str_t ID = {"id", 2};
static const pj_str_t NOTE = {"note", 4};
static const pj_str_t RPID_ACTIVITIES = {"rpid:activities", 15};
static const pj_str_t RPID_AWAY = {"rpid:away", 9};
static const pj_str_t RPID_BUSY = {"rpid:busy", 9};
static const pj_str_t RPID_UNKNOWN = {"rpid:unknown", 12};


/* Duplicate RPID element */
PJ_DEF(void) pjrpid_element_dup(pj_pool_t *pool, pjrpid_element *dst,
				const pjrpid_element *src)
{
    pj_memcpy(dst, src, sizeof(pjrpid_element));
    pj_strdup(pool, &dst->id, &src->id);
    pj_strdup(pool, &dst->note, &src->note);
}


/* Update RPID namespaces. */
static void update_namespaces(pjpidf_pres *pres,
			      pj_pool_t *pool)
{
    /* Check if namespace is already present. */
    if (pj_xml_find_attr(pres, &DM_NAME, NULL) != NULL)
	return;

    pj_xml_add_attr(pres, pj_xml_attr_new(pool, &DM_NAME, &DM_VAL));
    pj_xml_add_attr(pres, pj_xml_attr_new(pool, &RPID_NAME, &RPID_VAL));
}


/* Comparison function to find node name substring */
static pj_bool_t substring_match(const pj_xml_node *node, 
				 const char *part_name,
				 pj_ssize_t part_len)
{
    pj_str_t end_name;

    if (part_len < 1)
	part_len = pj_ansi_strlen(part_name);

    if (node->name.slen < part_len)
	return PJ_FALSE;

    end_name.ptr = node->name.ptr + (node->name.slen - part_len);
    end_name.slen = part_len;

    return pj_strnicmp2(&end_name, part_name, part_len)==0;
}

/* Util to find child node with the specified substring */
static pj_xml_node *find_node(const pj_xml_node *parent, 
			      const char *part_name)
{
    const pj_xml_node *node = parent->node_head.next, 
		      *head = (pj_xml_node*) &parent->node_head;
    pj_ssize_t part_len = pj_ansi_strlen(part_name);

    while (node != head) {
	if (substring_match(node, part_name, part_len))
	    return (pj_xml_node*) node;

	node = node->next;
    }

    return NULL;
}

/*
 * Add RPID element into existing PIDF document.
 */
PJ_DEF(pj_status_t) pjrpid_add_element(pjpidf_pres *pres, 
				       pj_pool_t *pool,
				       unsigned options,
				       const pjrpid_element *elem)
{
    pj_xml_node *nd_person, *nd_activities, *nd_activity, *nd_note;
    pj_xml_attr *attr;

    PJ_ASSERT_RETURN(pres && pool && options==0 && elem, PJ_EINVAL);

    PJ_UNUSED_ARG(options);

    /* Check if we need to add RPID information into the PIDF document. */
    if (elem->id.slen==0 && 
	elem->activity==PJRPID_ACTIVITY_UNKNOWN &&
	elem->note.slen==0)
    {
	/* No RPID information to be added. */
	return PJ_SUCCESS;
    }

    /* Add <note> to <tuple> */
    if (elem->note.slen != 0) {
	pj_xml_node *nd_tuple;

	nd_tuple = find_node(pres, "tuple");

	if (nd_tuple) {
	    nd_note = pj_xml_node_new(pool, &NOTE);
	    pj_strdup(pool, &nd_note->content, &elem->note);
	    pj_xml_add_node(nd_tuple, nd_note);
	    nd_note = NULL;
	}
    }

    /* Update namespace */
    update_namespaces(pres, pool);

    /* Add <person> */
    nd_person = pj_xml_node_new(pool, &DM_PERSON);
    if (elem->id.slen != 0) {
	attr = pj_xml_attr_new(pool, &ID, &elem->id);
    } else {
	pj_str_t person_id;
	/* xs:ID must start with letter */
	//pj_create_unique_string(pool, &person_id);
	person_id.ptr = (char*)pj_pool_alloc(pool, PJ_GUID_STRING_LENGTH+2);
	person_id.ptr += 2;
	pj_generate_unique_string(&person_id);
	person_id.ptr -= 2;
	person_id.ptr[0] = 'p';
	person_id.ptr[1] = 'j';
	person_id.slen += 2;

	attr = pj_xml_attr_new(pool, &ID, &person_id);
    }
    pj_xml_add_attr(nd_person, attr);
    pj_xml_add_node(pres, nd_person);

    /* Add <activities> */
    nd_activities = pj_xml_node_new(pool, &RPID_ACTIVITIES);
    pj_xml_add_node(nd_person, nd_activities);

    /* Add the activity */
    switch (elem->activity) {
    case PJRPID_ACTIVITY_AWAY:
	nd_activity = pj_xml_node_new(pool, &RPID_AWAY);
	break;
    case PJRPID_ACTIVITY_BUSY:
	nd_activity = pj_xml_node_new(pool, &RPID_BUSY);
	break;
    case PJRPID_ACTIVITY_UNKNOWN:
    default:
	nd_activity = pj_xml_node_new(pool, &RPID_UNKNOWN);
	break;
    }
    pj_xml_add_node(nd_activities, nd_activity);

    /* Add custom text if required. */
    if (elem->note.slen != 0) {
	nd_note = pj_xml_node_new(pool, &DM_NOTE);
	pj_strdup(pool, &nd_note->content, &elem->note);
	pj_xml_add_node(nd_person, nd_note);
    }

    /* Done */
    return PJ_SUCCESS;
}


/* Get <note> element from PIDF <tuple> element */
static pj_status_t get_tuple_note(const pjpidf_pres *pres,
				  pj_pool_t *pool,
				  pjrpid_element *elem)
{
    const pj_xml_node *nd_tuple, *nd_note;

    nd_tuple = find_node(pres, "tuple");
    if (!nd_tuple)
	return PJSIP_SIMPLE_EBADRPID;

    nd_note = find_node(pres, "note");
    if (nd_note) {
	pj_strdup(pool, &elem->note, &nd_note->content);
	return PJ_SUCCESS;
    }

    return PJSIP_SIMPLE_EBADRPID;
}

/*
 * Get RPID element from PIDF document, if any.
 */
PJ_DEF(pj_status_t) pjrpid_get_element(const pjpidf_pres *pres,
				       pj_pool_t *pool,
				       pjrpid_element *elem)
{
    const pj_xml_node *nd_person, *nd_activities, *nd_note = NULL;
    const pj_xml_attr *attr;

    /* Reset */
    pj_bzero(elem, sizeof(*elem));
    elem->activity = PJRPID_ACTIVITY_UNKNOWN;

    /* Find <person> */
    nd_person = find_node(pres, "person");
    if (!nd_person) {
	/* <person> not found, try to get <note> from <tuple> */
	return get_tuple_note(pres, pool, elem);
    }

    /* Get element id attribute */
    attr = pj_xml_find_attr((pj_xml_node*)nd_person, &ID, NULL);
    if (attr)
	pj_strdup(pool, &elem->id, &attr->value);

    /* Get <activities> */
    nd_activities = find_node(nd_person, "activities");
    if (nd_activities) {
	const pj_xml_node *nd_activity;

	/* Try to get <note> from <activities> */
	nd_note = find_node(nd_activities, "note");

	/* Get the activity */
	nd_activity = nd_activities->node_head.next;
	if (nd_activity == nd_note)
	    nd_activity = nd_activity->next;

	if (nd_activity != (pj_xml_node*) &nd_activities->node_head) {
	    if (substring_match(nd_activity, "busy", -1))
		elem->activity = PJRPID_ACTIVITY_BUSY;
	    else if (substring_match(nd_activity, "away", -1))
		elem->activity = PJRPID_ACTIVITY_AWAY;
	    else
		elem->activity = PJRPID_ACTIVITY_UNKNOWN;

	}
    }

    /* If <note> is not found, get <note> from <person> */
    if (nd_note == NULL)
	nd_note = find_node(nd_person, "note");

    if (nd_note) {
	pj_strdup(pool, &elem->note, &nd_note->content);
    } else {
	get_tuple_note(pres, pool, elem);
    }

    return PJ_SUCCESS;
}


