#pragma once

#include "libxml/parser.h"
#include "libxml/xmlwriter.h"

#include "log.h"

#define XML_NODE_START  1
#define XML_NODE_TEXT   3

/* Check if node n is of name s. */
#define xml_isNode(n,s) \
  ((n!=NULL) && ((n)->type==XML_NODE_START) && \
  (strcmp((char*)(n)->name, s)==0))

/* Get the next node. */
#define xml_nextNode(n) \
  ((n!=NULL) && ((n = n->next) != NULL))

/* Get the property s of node n. This mallocs. */
#define xml_nodeProp(n,s) (char*)xmlGetProp(n, (xmlChar*)s)

/* Get data different ways. */
#define xml_get(n)      ((char*)(n)->children->content)
#define xml_getInt(n)   (atoi((char*)(n)->children->content))
#define xml_getLong(n)  (atoi((char*)(n)->children->content))
#define xml_getFloat(n) (atof((char*)(n)->children->content))

/* Reader crap. */
#define xmlr_int(n,s,i) \
  if(xml_isNode(n,s)) { i = xml_getInt(n);    continue; }
#define xmlr_long(n,s,l) \
  if(xml_isNode(n,s)) { l = xml_getLong(n);   continue; }
#define xmlr_float(n,s,f) \
  if(xml_isNode(n,s)) { f = xml_getFloat(n);  continue; }
#define xmlr_str(n,s,str) \
  if(xml_isNode(n,s)) { str = xml_get(n);     continue; }
#define xmlr_strd(n,s,str) \
  if(xml_isNode(n,s)) { str = strdup(xml_get(n)); continue; }
#define xmlr_attr(n,s,a) \
  a = xml_nodeProp(n,s)

/* Writer crap. */

/* Encompassing element. */
#define xmlw_startElem(w, str) \
  if(xmlTextWriterStartElement(w, (xmlChar*)str) < 0) { \
	ERR("xmlw: Unable to create start element"); return -1; }

#define xmlw_endElem(w) \
  if(xmlTextWriterEndElement(w) < 0) { \
	ERR("xmlw: Unable to create end element"); return -1; }

/* Other stuff. */
#define xmlw_elem(w, n, str, args...) \
  if(xmlTextWriterWriteFormatElement(w, (xmlChar*)n, str, ## args) < 0) { \
	ERR("xmlw: Unable to write format element"); return -1; }

#define xmlw_raw(w,b,l) \
  if(xmlTextWriterWriteRawLen(w, (xmlChar*)b, l) < 0) { \
	ERR("xmlw: unable to write raw element"); return -1; }

#define xmlw_attr(w, str, val...) \
  if(xmlTextWriterWriteFormatAttribute(w, (xmlChar*)str, ## val) < 0) { \
	ERR("xmlw: Unable to write element attribute"); return -1; }

#define xmlw_str(w, str, val...) \
  if(xmlTextWriterWriteFormatString(w, str, ## val) < 0) { \
	ERR("xmlw: Unable to write element data"); return -1; }

/* Document level. */
#define xmlw_start(w) \
  if(xmlTextWriterStartDocument(writer, NULL, "UTF-8", NULL) < 0) { \
	ERR("xmlw: Unable to start document"); return -1; }

#define xmlw_done(w) \
  if(xmlTextWriterEndDocument(w) < 0) { \
	ERR("xmlw: Unable to end document"); return -1; }