/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice, 
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products 
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <string>
#include <iostream>
#include <vector>
#include <sstream>

#include "talk/base/common.h"
#include "talk/xmllite/xmlelement.h"
#include "talk/xmllite/qname.h"
#include "talk/xmllite/xmlparser.h"
#include "talk/xmllite/xmlbuilder.h"
#include "talk/xmllite/xmlprinter.h"
#include "talk/xmllite/xmlconstants.h"

namespace buzz {

const QName QN_EMPTY(true, STR_EMPTY, STR_EMPTY);
const QName QN_XMLNS(true, STR_EMPTY, STR_XMLNS);


XmlChild::~XmlChild() {
}

bool
XmlText::IsTextImpl() const {
  return true;
}

XmlElement *
XmlText::AsElementImpl() const {
  return NULL;
}

XmlText *
XmlText::AsTextImpl() const {
  return const_cast<XmlText *>(this);
}

void
XmlText::SetText(const std::string & text) {
  text_ = text;
}

void
XmlText::AddParsedText(const char * buf, int len) {
  text_.append(buf, len);
}

void
XmlText::AddText(const std::string & text) {
  text_ += text;
}

XmlText::~XmlText() {
}

XmlElement::XmlElement(const QName & name) :
    name_(name),
    pFirstAttr_(NULL),
    pLastAttr_(NULL),
    pFirstChild_(NULL),
    pLastChild_(NULL),
    cdata_(false) {
}

XmlElement::XmlElement(const XmlElement & elt) :
    XmlChild(),
    name_(elt.name_),
    pFirstAttr_(NULL),
    pLastAttr_(NULL),
    pFirstChild_(NULL),
    pLastChild_(NULL),
    cdata_(false) {

  // copy attributes
  XmlAttr * pAttr;
  XmlAttr ** ppLastAttr = &pFirstAttr_;
  XmlAttr * newAttr = NULL;
  for (pAttr = elt.pFirstAttr_; pAttr; pAttr = pAttr->NextAttr()) {
    newAttr = new XmlAttr(*pAttr);
    *ppLastAttr = newAttr;
    ppLastAttr = &(newAttr->pNextAttr_);
  }
  pLastAttr_ = newAttr;

  // copy children
  XmlChild * pChild;
  XmlChild ** ppLast = &pFirstChild_;
  XmlChild * newChild = NULL;

  for (pChild = elt.pFirstChild_; pChild; pChild = pChild->NextChild()) {
    if (pChild->IsText()) {
      newChild = new XmlText(*(pChild->AsText()));
    } else {
      newChild = new XmlElement(*(pChild->AsElement()));
    }
    *ppLast = newChild;
    ppLast = &(newChild->pNextChild_);
  }
  pLastChild_ = newChild;

  cdata_ = elt.cdata_;
}

XmlElement::XmlElement(const QName & name, bool useDefaultNs) :
  name_(name),
  pFirstAttr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
  pLastAttr_(pFirstAttr_),
  pFirstChild_(NULL),
  pLastChild_(NULL),
  cdata_(false) {
}

bool
XmlElement::IsTextImpl() const {
  return false;
}

XmlElement *
XmlElement::AsElementImpl() const {
  return const_cast<XmlElement *>(this);
}

XmlText *
XmlElement::AsTextImpl() const {
  return NULL;
}

const std::string &
XmlElement::BodyText() const {
  if (pFirstChild_ && pFirstChild_->IsText() && pLastChild_ == pFirstChild_) {
    return pFirstChild_->AsText()->Text();
  }

  return STR_EMPTY;
}

void
XmlElement::SetBodyText(const std::string & text) {
  if (text == STR_EMPTY) {
    ClearChildren();
  } else if (pFirstChild_ == NULL) {
    AddText(text);
  } else if (pFirstChild_->IsText() && pLastChild_ == pFirstChild_) {
    pFirstChild_->AsText()->SetText(text);
  } else {
    ClearChildren();
    AddText(text);
  }
}

const QName &
XmlElement::FirstElementName() const {
  const XmlElement * element = FirstElement();
  if (element == NULL)
    return QN_EMPTY;
  return element->Name();
}

XmlAttr *
XmlElement::FirstAttr() {
  return pFirstAttr_;
}

const std::string &
XmlElement::Attr(const QName & name) const {
  XmlAttr * pattr;
  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
    if (pattr->name_ == name)
      return pattr->value_;
  }
  return STR_EMPTY;
}

bool
XmlElement::HasAttr(const QName & name) const {
  XmlAttr * pattr;
  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
    if (pattr->name_ == name)
      return true;
  }
  return false;
}

void
XmlElement::SetAttr(const QName & name, const std::string & value) {
  XmlAttr * pattr;
  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
    if (pattr->name_ == name)
      break;
  }
  if (!pattr) {
    pattr = new XmlAttr(name, value);
    if (pLastAttr_)
      pLastAttr_->pNextAttr_ = pattr;
    else
      pFirstAttr_ = pattr;
    pLastAttr_ = pattr;
    return;
  }
  pattr->value_ = value;
}

void
XmlElement::ClearAttr(const QName & name) {
  XmlAttr * pattr;
  XmlAttr *pLastAttr = NULL;
  for (pattr = pFirstAttr_; pattr; pattr = pattr->pNextAttr_) {
    if (pattr->name_ == name)
      break;
    pLastAttr = pattr;
  }
  if (!pattr)
    return;
  if (!pLastAttr)
    pFirstAttr_ = pattr->pNextAttr_;
  else
    pLastAttr->pNextAttr_ = pattr->pNextAttr_;
  if (pLastAttr_ == pattr)
    pLastAttr_ = pLastAttr;
  delete pattr;
}

XmlChild *
XmlElement::FirstChild() {
  return pFirstChild_;
}

XmlElement *
XmlElement::FirstElement() {
  XmlChild * pChild;
  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText())
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement *
XmlElement::NextElement() {
  XmlChild * pChild;
  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText())
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement *
XmlElement::FirstWithNamespace(const std::string & ns) {
  XmlChild * pChild;
  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement *
XmlElement::NextWithNamespace(const std::string & ns) {
  XmlChild * pChild;
  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText() && pChild->AsElement()->Name().Namespace() == ns)
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement *
XmlElement::FirstNamed(const QName & name) {
  XmlChild * pChild;
  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement *
XmlElement::NextNamed(const QName & name) {
  XmlChild * pChild;
  for (pChild = pNextChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
      return pChild->AsElement();
  }
  return NULL;
}

XmlElement* XmlElement::FindOrAddNamedChild(const QName& name) {
  XmlElement* child = FirstNamed(name);
  if (!child) {
    child = new XmlElement(name);
    AddElement(child);
  }

  return child;
}

const std::string &
XmlElement::TextNamed(const QName & name) const {
  XmlChild * pChild;
  for (pChild = pFirstChild_; pChild; pChild = pChild->pNextChild_) {
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
      return pChild->AsElement()->BodyText();
  }
  return STR_EMPTY;
}

void
XmlElement::InsertChildAfter(XmlChild * pPredecessor, XmlChild * pNext) {
  if (pPredecessor == NULL) {
    pNext->pNextChild_ = pFirstChild_;
    pFirstChild_ = pNext;
  }
  else {
    pNext->pNextChild_ = pPredecessor->pNextChild_;
    pPredecessor->pNextChild_ = pNext;
  }
}

void
XmlElement::RemoveChildAfter(XmlChild * pPredecessor) {
  XmlChild * pNext;

  if (pPredecessor == NULL) {
    pNext = pFirstChild_;
    pFirstChild_ = pNext->pNextChild_;
  }
  else {
    pNext = pPredecessor->pNextChild_;
    pPredecessor->pNextChild_ = pNext->pNextChild_;
  }

  if (pLastChild_ == pNext)
    pLastChild_ = pPredecessor;

  delete pNext;
}

void
XmlElement::AddAttr(const QName & name, const std::string & value) {
  ASSERT(!HasAttr(name));

  XmlAttr ** pprev = pLastAttr_ ? &(pLastAttr_->pNextAttr_) : &pFirstAttr_;
  pLastAttr_ = (*pprev = new XmlAttr(name, value));
}

void
XmlElement::AddAttr(const QName & name, const std::string & value,
                         int depth) {
  XmlElement * element = this;
  while (depth--) {
    element = element->pLastChild_->AsElement();
  }
  element->AddAttr(name, value);
}

void
XmlElement::AddParsedText(const char * cstr, int len) {
  if (len == 0)
    return;

  if (pLastChild_ && pLastChild_->IsText()) {
    pLastChild_->AsText()->AddParsedText(cstr, len);
    return;
  }
  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
  pLastChild_ = *pprev = new XmlText(cstr, len);
}

void
XmlElement::AddCDATAText(const char * buf, int len) {
  cdata_ = true;
  AddParsedText(buf, len);
}

void
XmlElement::AddText(const std::string & text) {
  if (text == STR_EMPTY)
    return;

  if (pLastChild_ && pLastChild_->IsText()) {
    pLastChild_->AsText()->AddText(text);
    return;
  }
  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
  pLastChild_ = *pprev = new XmlText(text);
}

void
XmlElement::AddText(const std::string & text, int depth) {
  // note: the first syntax is ambigious for msvc 6
  // XmlElement * pel(this);
  XmlElement * element = this;
  while (depth--) {
    element = element->pLastChild_->AsElement();
  }
  element->AddText(text);
}

void
XmlElement::AddElement(XmlElement *pelChild) {
  if (pelChild == NULL)
    return;

  XmlChild ** pprev = pLastChild_ ? &(pLastChild_->pNextChild_) : &pFirstChild_;
  pLastChild_ = *pprev = pelChild;
  pelChild->pNextChild_ = NULL;
}

void
XmlElement::AddElement(XmlElement *pelChild, int depth) {
  XmlElement * element = this;
  while (depth--) {
    element = element->pLastChild_->AsElement();
  }
  element->AddElement(pelChild);
}

void
XmlElement::ClearNamedChildren(const QName & name) {
  XmlChild * prev_child = NULL;
  XmlChild * next_child;
  XmlChild * child;
  for (child = FirstChild(); child; child = next_child) {
    next_child = child->NextChild();
    if (!child->IsText() && child->AsElement()->Name() == name)
    {
      RemoveChildAfter(prev_child);
      continue;
    }
    prev_child = child;
  }
}

void
XmlElement::ClearAttributes() {
  XmlAttr * pattr;
  for (pattr = pFirstAttr_; pattr; ) {
    XmlAttr * pToDelete = pattr;
    pattr = pattr->pNextAttr_;
    delete pToDelete;
  }
  pFirstAttr_ = pLastAttr_ = NULL;
}

void
XmlElement::ClearChildren() {
  XmlChild * pchild;
  for (pchild = pFirstChild_; pchild; ) {
    XmlChild * pToDelete = pchild;
    pchild = pchild->pNextChild_;
    delete pToDelete;
  }
  pFirstChild_ = pLastChild_ = NULL;
}

std::string
XmlElement::Str() const {
  std::stringstream ss;
  Print(&ss, NULL, 0);
  return ss.str();
}

XmlElement *
XmlElement::ForStr(const std::string & str) {
  XmlBuilder builder;
  XmlParser::ParseXml(&builder, str);
  return builder.CreateElement();
}

void
XmlElement::Print(
    std::ostream * pout, std::string xmlns[], int xmlnsCount) const {
  XmlPrinter::PrintXml(pout, this, xmlns, xmlnsCount);
}

XmlElement::~XmlElement() {
  XmlAttr * pattr;
  for (pattr = pFirstAttr_; pattr; ) {
    XmlAttr * pToDelete = pattr;
    pattr = pattr->pNextAttr_;
    delete pToDelete;
  }

  XmlChild * pchild;
  for (pchild = pFirstChild_; pchild; ) {
    XmlChild * pToDelete = pchild;
    pchild = pchild->pNextChild_;
    delete pToDelete;
  }
}

}
