/*$cb
 *    This file is a part of libopenmhp.
 *
 *    Copyright (C) 2005 Mikko Novaro <miknov@gmail.com>
 *
 *    See main header file (libopenmhp/openmhp.h) for licensing and
 *    contact information.
 $ce*/

#include "handler.hpp"
#include "../macros.h"
// #define DEBUG_HANDLER

/* Bridge functions for passing xml handling from libxml to
   cXMLHandler object. cXMLHandler object is passed in handler_obj
   argument. */

/* NOTE: The bridge function and the xmlSAXHandler struct were to be
   used with libxml's SAX parser. I couldn't, however, figure out how
   to make it react immediately to XML input arriving through a pipe,
   and decided to write my own parser. In spite of this, I'd like to
   switch back to libxml if someone pointed out how to use libxml in
   such a manner. */

/*
void startElementBridge(void *handler_obj,
		  const xmlChar *name,
		  const xmlChar **attrs)
{
  printf("bridge: start %s\n", (char*)name);
  cXMLHandler *handlerObj = (cXMLHandler*)handler_obj;
  handlerObj->StartElement(name, attrs);
}
*/

/*
void endElementBridge (void *handler_obj, const xmlChar *name) {
  printf("bridge: end %s\n", (char*)name);
  cXMLHandler *handlerObj = (cXMLHandler*)handler_obj;
  handlerObj->EndElement(name);
}
*/

/*
void charactersBridge (void *handler_obj, const xmlChar *ch, int len) {
  printf("bridge: chars (%i)\n", len);
  cXMLHandler *handlerObj = (cXMLHandler*)handler_obj;
  handlerObj->Characters(ch, len);
}
*/

/*
static void
my_warning(void *user_data, const char *msg, ...) {
  printf("XMLPARSER_WARNING: %s\n", msg);
}
*/

/*
static void
my_error(void *user_data, const char *msg, ...) {
  printf("XMLPARSER_ERROR: %s\n", msg);
}
*/

/*
static void
my_fatalError(void *user_data, const char *msg, ...) {
  printf("XMLPARSER_FATALERROR: %s\n", msg);
}
*/

// static xmlSAXHandler bridgeSAXHandlerStruct = {
//     NULL, /* internalSubset */
//     NULL, /* isStandalone */
//     NULL, /* hasInternalSubset */
//     NULL, /* hasExternalSubset */
//     NULL, /* resolveEntity */
//     NULL, /* getEntity */
//     NULL, /* entityDecl */
//     NULL, /* notationDecl */
//     NULL, /* attributeDecl */
//     NULL, /* elementDecl */
//     NULL, /* unparsedEntityDecl */
//     NULL, /* setDocumentLocator */
//     NULL, /* startDocument */
//     NULL, /* endDocument */
//     startElementBridge, /* startElement */
//     endElementBridge, /* endElement */
//     NULL, /* reference */
//     charactersBridge, /* characters */
//     NULL, /* ignorableWhitespace */
//     NULL, /* processingInstruction */
//     NULL, /* comment */
//     my_warning, /* xmlParserWarning */
//     my_error, /* xmlParserError */
//     my_fatalError, /* xmlParserError */
//     NULL, /* getParameterEntity */
//     NULL, /* cdataBlock; */
//     NULL, /* externalSubset; */
//     1,
//     NULL,
//     NULL, /* startElementNs */
//     NULL, /* endElementNs */
//     NULL  /* xmlStructuredErrorFunc */
// };


// ---------------------- cXMLHandler --------------------------

cXMLHandler::cXMLHandler(const char *fn) : cXMLParser(fn) {
  curNode = new xml::cRootElement("root");
}


cXMLHandler::~cXMLHandler() {
  xml::cXMLElement *rn = GetRootNode();
  delete rn;
  curNode = NULL;
}


xml::cXMLElement *cXMLHandler::GetElement(const char *name) {
  if (!strcmp(name, "imageupdate")) { return new xml::cImageUpdate(name); }
  if (!strcmp(name, "mhptoclient")) { return new xml::cMhpToClient(name); }
  if (!strcmp(name, "videoscale")) { return new xml::cVideoScale(name); }
  if (!strcmp(name, "videoposx")) { return new xml::cIntElem(name); }
  if (!strcmp(name, "videoposy")) { return new xml::cIntElem(name); }
  if (!strcmp(name, "videowidth")) { return new xml::cIntElem(name); }
  if (!strcmp(name, "videoheight")) { return new xml::cIntElem(name); }
  // Add new XML element object initializations here
  return NULL;
}

xml::cXMLElement *cXMLHandler::GetRootNode(void) {
  xml::cXMLElement *e = curNode;
  while (e->GetParentNode() != NULL) e = e->GetParentNode();
  return e;
}



void cXMLHandler::StartElement(const char *name, const char **attrs) {
#ifdef DEBUG_HANDLER
  DBG("cXMLHandler::StartElement: %s", name);
#endif
  xml::cXMLElement *elem = GetElement((const char*)name);
  if (elem == NULL) {
    ERR("element \"%s\" not found.", (const char*)name);
    exit(1);
  }
  curNode->AddChildNode(elem);
  curNode = elem;
  curNode->Start((const char*)name);
}

void cXMLHandler::EndElement(const char *name) {
#ifdef DEBUG_HANDLER
  DBG("cXMLHandler::EndElement: %s", name);
#endif
  curNode->End((const char*)name);
  curNode = curNode->GetParentNode();
}

void cXMLHandler::Characters(const char *ch, int len) {
  char *s = new char[len+1];
  strncpy(s, (char *)ch, len);
  s[len] = '\0';
#ifdef DEBUG_HANDLER
  DBG("cXMLHandler::Characters: (%i): %s\n", len, s);
#endif
  curNode->Characters(s, len);
  delete s;
}

void cXMLHandler::RunHandler() {
  Parse();
}
