/*
 * 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 "talk/xmllite/xmlelement.h"

#include <ostream>
#include <sstream>
#include <string>
#include <vector>

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

namespace buzz {

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),
    first_attr_(NULL),
    last_attr_(NULL),
    first_child_(NULL),
    last_child_(NULL),
    cdata_(false) {
}

XmlElement::XmlElement(const XmlElement& elt) :
    XmlChild(),
    name_(elt.name_),
    first_attr_(NULL),
    last_attr_(NULL),
    first_child_(NULL),
    last_child_(NULL),
    cdata_(false) {

  // copy attributes
  XmlAttr* attr;
  XmlAttr ** plast_attr = &first_attr_;
  XmlAttr* newAttr = NULL;
  for (attr = elt.first_attr_; attr; attr = attr->NextAttr()) {
    newAttr = new XmlAttr(*attr);
    *plast_attr = newAttr;
    plast_attr = &(newAttr->next_attr_);
  }
  last_attr_ = newAttr;

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

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

  cdata_ = elt.cdata_;
}

XmlElement::XmlElement(const QName& name, bool useDefaultNs) :
  name_(name),
  first_attr_(useDefaultNs ? new XmlAttr(QN_XMLNS, name.Namespace()) : NULL),
  last_attr_(first_attr_),
  first_child_(NULL),
  last_child_(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 (first_child_ && first_child_->IsText() && last_child_ == first_child_) {
    return first_child_->AsText()->Text();
  }

  return std::string();
}

void XmlElement::SetBodyText(const std::string& text) {
  if (text.empty()) {
    ClearChildren();
  } else if (first_child_ == NULL) {
    AddText(text);
  } else if (first_child_->IsText() && last_child_ == first_child_) {
    first_child_->AsText()->SetText(text);
  } else {
    ClearChildren();
    AddText(text);
  }
}

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

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

const std::string XmlElement::Attr(const StaticQName& name) const {
  XmlAttr* attr;
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
    if (attr->name_ == name)
      return attr->value_;
  }
  return std::string();
}

const std::string XmlElement::Attr(const QName& name) const {
  XmlAttr* attr;
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
    if (attr->name_ == name)
      return attr->value_;
  }
  return std::string();
}

bool XmlElement::HasAttr(const StaticQName& name) const {
  XmlAttr* attr;
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
    if (attr->name_ == name)
      return true;
  }
  return false;
}

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

void XmlElement::SetAttr(const QName& name, const std::string& value) {
  XmlAttr* attr;
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
    if (attr->name_ == name)
      break;
  }
  if (!attr) {
    attr = new XmlAttr(name, value);
    if (last_attr_)
      last_attr_->next_attr_ = attr;
    else
      first_attr_ = attr;
    last_attr_ = attr;
    return;
  }
  attr->value_ = value;
}

void XmlElement::ClearAttr(const QName& name) {
  XmlAttr* attr;
  XmlAttr* last_attr = NULL;
  for (attr = first_attr_; attr; attr = attr->next_attr_) {
    if (attr->name_ == name)
      break;
    last_attr = attr;
  }
  if (!attr)
    return;
  if (!last_attr)
    first_attr_ = attr->next_attr_;
  else
    last_attr->next_attr_ = attr->next_attr_;
  if (last_attr_ == attr)
    last_attr_ = last_attr;
  delete attr;
}

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

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

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

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

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

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

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

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

XmlElement *
XmlElement::NextNamed(const StaticQName& name) {
  XmlChild* pChild;
  for (pChild = next_child_; pChild; pChild = pChild->next_child_) {
    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 = first_child_; pChild; pChild = pChild->next_child_) {
    if (!pChild->IsText() && pChild->AsElement()->Name() == name)
      return pChild->AsElement()->BodyText();
  }
  return std::string();
}

void XmlElement::InsertChildAfter(XmlChild* predecessor, XmlChild* next) {
  if (predecessor == NULL) {
    next->next_child_ = first_child_;
    first_child_ = next;
  }
  else {
    next->next_child_ = predecessor->next_child_;
    predecessor->next_child_ = next;
  }
}

void XmlElement::RemoveChildAfter(XmlChild* predecessor) {
  XmlChild* next;

  if (predecessor == NULL) {
    next = first_child_;
    first_child_ = next->next_child_;
  }
  else {
    next = predecessor->next_child_;
    predecessor->next_child_ = next->next_child_;
  }

  if (last_child_ == next)
    last_child_ = predecessor;

  delete next;
}

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

  XmlAttr ** pprev = last_attr_ ? &(last_attr_->next_attr_) : &first_attr_;
  last_attr_ = (*pprev = new XmlAttr(name, value));
}

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

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

  if (last_child_ && last_child_->IsText()) {
    last_child_->AsText()->AddParsedText(cstr, len);
    return;
  }
  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  last_child_ = *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 (last_child_ && last_child_->IsText()) {
    last_child_->AsText()->AddText(text);
    return;
  }
  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  last_child_ = *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->last_child_->AsElement();
  }
  element->AddText(text);
}

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

  XmlChild ** pprev = last_child_ ? &(last_child_->next_child_) : &first_child_;
  *pprev = child;
  last_child_ = child;
  child->next_child_ = NULL;
}

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

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* attr;
  for (attr = first_attr_; attr; ) {
    XmlAttr* to_delete = attr;
    attr = attr->next_attr_;
    delete to_delete;
  }
  first_attr_ = last_attr_ = NULL;
}

void XmlElement::ClearChildren() {
  XmlChild* pchild;
  for (pchild = first_child_; pchild; ) {
    XmlChild* to_delete = pchild;
    pchild = pchild->next_child_;
    delete to_delete;
  }
  first_child_ = last_child_ = NULL;
}

std::string XmlElement::Str() const {
  std::stringstream ss;
  XmlPrinter::PrintXml(&ss, this);
  return ss.str();
}

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

XmlElement::~XmlElement() {
  XmlAttr* attr;
  for (attr = first_attr_; attr; ) {
    XmlAttr* to_delete = attr;
    attr = attr->next_attr_;
    delete to_delete;
  }

  XmlChild* pchild;
  for (pchild = first_child_; pchild; ) {
    XmlChild* to_delete = pchild;
    pchild = pchild->next_child_;
    delete to_delete;
  }
}

}  // namespace buzz
