/*$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 "element.hpp"
#include "../xlet.hpp"
#include "../event.hpp"
#include "../macros.h"

using namespace xml;

// #define DEBUG_ELEM

cXMLElement::cXMLElement(const char *elemName) {
  parentNode = NULL;
  pcData = new std::string("");
  childNodes = new std::list<cXMLElement*>;
  name = new char[strlen(elemName)+1];
  strcpy(name, elemName);
}

cXMLElement::~cXMLElement() {
  // delete nodes in the child tree
  std::list<cXMLElement*>::iterator child;
  for (child = childNodes->begin(); child != childNodes->end(); child++) {
    delete (*child);
  }
  delete childNodes;
  delete pcData;
  delete name;
}

// return a pointer to element's name
const char *cXMLElement::GetName() {
  return name;
}

void cXMLElement::AddChildNode(cXMLElement *elem) {
  childNodes->push_back(elem);
  elem->SetParentNode(this);
}

void cXMLElement::SetParentNode(cXMLElement *elem) {
  parentNode = elem;
}

// return a pointer to parent node
cXMLElement *cXMLElement::GetParentNode() {
  return parentNode;
}

// return a pointer to child node
cXMLElement *cXMLElement::GetChildNode(const char *elemName, int index) {
  int cnt = 0;
  std::list<cXMLElement*>::iterator child;
  for (child = childNodes->begin(); child != childNodes->end(); child++) {
    if (!strcmp(elemName, (*child)->GetName())) {
      if (cnt == index) return *child;
      cnt++;
    }
  }
  return NULL;
}

// return a copy of pc-data
char *cXMLElement::GetData() {
  const char *tmp = pcData->c_str();
  char *ret = new char[sizeof(tmp)];
  return strcpy(ret, tmp);
}


void cXMLElement::Characters(const char *ch, int len) {
#ifdef DEBUG_ELEM
  DBG("cXMLElement::Characters: %s", ch);
#endif
  std::string tmp(ch);
  pcData->append(tmp);
}

void cXMLElement::Start(const char *name) {
#ifdef DEBUG_ELEM
  DBG("cXMLElement::Start: %s", name);
#endif
}

void cXMLElement::End(const char *name) {
#ifdef DEBUG_ELEM
  DBG("cXMLElement::End: %s", name);
#endif
}


// ----------------- ACTUAL ELEMENT CLASSES -----------------------------

// ---- Root

cRootElement::cRootElement(const char *elemName) : cXMLElement(elemName) {
}

// ---- IntElem

cIntElem::cIntElem(const char *elemName) : cXMLElement(elemName) {}
int cIntElem::GetDataInt() {
  char* data = GetData();
  int val = atoi(data);
  delete data;
  return val;
}

// ---- VideoScale

cVideoScale::cVideoScale(const char *elemName) : cXMLElement(elemName) {}

void cVideoScale::End(const char *name) {
  int width = ((xml::cIntElem*)(GetChildNode("videowidth")))->GetDataInt();
  int height = ((xml::cIntElem*)(GetChildNode("videoheight")))->GetDataInt();
  int posx = ((xml::cIntElem*)(GetChildNode("videoposx")))->GetDataInt();
  int posy = ((xml::cIntElem*)(GetChildNode("videoposy")))->GetDataInt();
  cVideoScaleEvent *event = new cVideoScaleEvent(posx, posy, width, height);
  cXlet::GetActiveInstance()->NotifyEvent(VIDEO_SCALE, event);
  delete event;
}

// ---- MhpToClient

cMhpToClient::cMhpToClient(const char *elemName) : cXMLElement(elemName) {}
void cMhpToClient::End(const char *elemName) {
  // End of communication.
}

// ---- ImageUpdate

cImageUpdate::cImageUpdate(const char *elemName) : cIntElem(elemName) {}

void cImageUpdate::End(const char *elemName) {
  cImageUpdateEvent *event = new cImageUpdateEvent(GetDataInt());
  cXlet::GetActiveInstance()->NotifyEvent(IMAGE_UPDATE, event);
  delete event;
}

