/*
 * Copyright (C) 2010-2012 Felix Fietkau <nbd@openwrt.org>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
#include <libubox/blobmsg.h>
#include <mxml.h>
#include "blobmsg_xml.h"


#define XML_ELEMENT_LIST_ITEM "Item"
#define XML_LIST_ATTR_INDEX "index" 

void blobmsg_format_xml(struct blob_attr *attr, int len, bool array)
{
	struct blob_attr *pos;
	int rem = len;

	mxml_node_t *xml;
	mxml_node_t *rgw;
	mxml_node_t *node;

	xml = mxmlNewXML("1.0");
	rgw = mxmlNewElement(xml,"RGW");
	node = rgw;

 	__blob_for_each_attr(pos, attr, rem)
	{
		blobmsg_format_xml_element(&node, pos, array);
	}
}
void blobmsg_format_xml_list_item(mxml_node_t *node, struct blob_attr *attr,  int len, bool array)
{
	int field;
	mxml_node_t *cur;
	struct blob_attr *pos;
	int rem = len;
	__blob_for_each_attr(pos, attr, rem)
	{
		//For every table item
		blobmsg_format_xml_element(&node, pos, array);
		//cur=mxmlNewElement(node, blobmsg_name(attr));
		//mxmlAdd(node, MXML_ADD_AFTER, NULL, cur);
		//mxmlNewOpaque(cur, blobmsg_data(attr));
	}
	return;

}
void blobmsg_format_xml_list(mxml_node_t *node, struct blob_attr *attr,  int len, bool array)
{
	mxml_node_t *cur;
	int index=0;
	struct blob_attr *pos;
	int rem = len;
	char index_str[10] = {'\0'};
	int size;
	__blob_for_each_attr(pos, attr, rem)
	{
		// For every table in parent array
		//New param node <Item></Item>
		cur=mxmlNewElement(node, XML_ELEMENT_LIST_ITEM);
		mxmlAdd(node, MXML_ADD_AFTER, NULL, cur);
		snprintf(index_str, 10, "%d", ++index);
		mxmlElementSetAttr(cur, XML_LIST_ATTR_INDEX, index_str);
		//skip blobmsg_name(pos)
		//pass table items for further process
		//blobmsg_format_xml_list_item(cur,blobmsg_data(pos),blobmsg_data_len(pos),false);
		size = blob_pad_len(pos);
		blobmsg_format_xml_list_item(cur,pos, blob_pad_len(pos),false);
	}
	return;
}
void blobmsg_format_xml_element( mxml_node_t **node, struct blob_attr *attr, bool array)
{
#define DEBUG_ON_OFF 1
	const char *data_str;
	char buf[32];
	void *data;
	int len;
	int str_size;
	mxml_node_t *cur;

#if DEBUG_ON_OFF 
	FILE *fp;
	fp = fopen("/tmp/blob_c_xml.log", "w+");
	if(!fp)
	{
		return;
	}
#endif 
	if (!blobmsg_check_attr(attr, false))
		return;

	if (blobmsg_name(attr)[0]) {
		if(!strcmp(blobmsg_name(attr), "ril_id"))
		{
			//for RIL response, no need RIL 
			return;
		}
		if(!strcmp(blobmsg_name(attr), "module_name"))
		{
			cur = mxmlNewElement(*node, blobmsg_data(attr));
			*node = cur;
			return;
		}
		else
		{
			fprintf(fp,"tag name %s\n",blobmsg_name(attr));
			cur = mxmlNewElement(*node, blobmsg_name(attr));
		}
	}

	data = blobmsg_data(attr);
	len = blobmsg_data_len(attr);

	data_str = buf;
	switch(blob_id(attr)) {
	case BLOBMSG_TYPE_UNSPEC:
		sprintf(buf, "null");
		break;
	case BLOBMSG_TYPE_BOOL:

		sprintf(buf, "%s", *(uint8_t *)data ? "true" : "false");
		fprintf(fp,"bool %s\n",buf);
		break;
	case BLOBMSG_TYPE_INT16:
		sprintf(buf, "%d", be16_to_cpu(*(uint16_t *)data));
		fprintf(fp,"INT16 %s\n",buf);
		break;
	case BLOBMSG_TYPE_INT32:
		sprintf(buf, "%d", (int32_t) be32_to_cpu(*(uint32_t *)data));
		fprintf(fp,"INT32 %s\n",buf);
		break;
	case BLOBMSG_TYPE_INT64:
		sprintf(buf, "%lld", (long long int) be64_to_cpu(*(uint64_t *)data));
		fprintf(fp,"INT64 %s\n",buf);
		break;
	case BLOBMSG_TYPE_STRING:
		data_str = data;
		fprintf(fp,"STRING %s\n",data_str);
		break;
	case BLOBMSG_TYPE_ARRAY:
		fprintf(fp,"ARRAY %p %p %u\n",*node, data, len);
		blobmsg_format_xml_list(cur, data, len, true);
		fclose(fp);
		return;
	case BLOBMSG_TYPE_TABLE:
		fprintf(fp,"TABLE %p %p %u\n",cur, data, len);
		blobmsg_format_xml_list_item(cur, data, len, false);
		fclose(fp);
		return;
	}
	fprintf(fp,"data_str %s\n",data_str);
	fclose(fp);
	mxmlNewText(cur, 0, data_str);
}

void blobmsg_format_xml_tree(mxml_node_t *node, struct blob_attr *attr,  int len, bool array)
{
	struct blob_attr *pos;
	int rem = len;

	mxml_node_t *cur;
	cur  = node;


	__blob_for_each_attr(pos, attr, rem)
	{
		blobmsg_format_xml_element(&cur, pos, array);
	}

}

