// Copyright 2017 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fxcrt/xml/cxml_element.h"

#include "core/fxcrt/xml/cxml_content.h"
#include "core/fxcrt/xml/cxml_parser.h"

// static
std::unique_ptr<CXML_Element> CXML_Element::Parse(const void* pBuffer,
                                                  size_t size) {
  CXML_Parser parser;
  if (!parser.Init(static_cast<const uint8_t*>(pBuffer), size))
    return nullptr;
  return parser.ParseElement(nullptr, false);
}

CXML_Element::CXML_Element(const CXML_Element* pParent,
                           const CFX_ByteStringC& qSpace,
                           const CFX_ByteStringC& tagname)
    : m_pParent(pParent), m_QSpaceName(qSpace), m_TagName(tagname) {}

CXML_Element::~CXML_Element() {
  Empty();
}

void CXML_Element::Empty() {
  RemoveChildren();
}
void CXML_Element::RemoveChildren() {
  for (const ChildRecord& record : m_Children) {
    if (record.type == Content) {
      delete static_cast<CXML_Content*>(record.child);
    } else if (record.type == Element) {
      CXML_Element* child = static_cast<CXML_Element*>(record.child);
      child->RemoveChildren();
      delete child;
    }
  }
  m_Children.clear();
}
CFX_ByteString CXML_Element::GetTagName(bool bQualified) const {
  if (!bQualified || m_QSpaceName.IsEmpty()) {
    return m_TagName;
  }
  CFX_ByteString bsTag = m_QSpaceName;
  bsTag += ":";
  bsTag += m_TagName;
  return bsTag;
}

CFX_ByteString CXML_Element::GetNamespace(bool bQualified) const {
  return bQualified ? m_QSpaceName : GetNamespaceURI(m_QSpaceName);
}

CFX_ByteString CXML_Element::GetNamespaceURI(
    const CFX_ByteString& qName) const {
  const CFX_WideString* pwsSpace;
  const CXML_Element* pElement = this;
  do {
    if (qName.IsEmpty())
      pwsSpace = pElement->m_AttrMap.Lookup("", "xmlns");
    else
      pwsSpace = pElement->m_AttrMap.Lookup("xmlns", qName);
    if (pwsSpace)
      break;

    pElement = pElement->GetParent();
  } while (pElement);
  return pwsSpace ? pwsSpace->UTF8Encode() : CFX_ByteString();
}

void CXML_Element::GetAttrByIndex(int index,
                                  CFX_ByteString* space,
                                  CFX_ByteString* name,
                                  CFX_WideString* value) const {
  if (index < 0 || index >= m_AttrMap.GetSize())
    return;

  CXML_AttrItem& item = m_AttrMap.GetAt(index);
  *space = item.m_QSpaceName;
  *name = item.m_AttrName;
  *value = item.m_Value;
}

bool CXML_Element::HasAttr(const CFX_ByteStringC& name) const {
  CFX_ByteStringC bsSpace;
  CFX_ByteStringC bsName;
  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
  return !!m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
}

bool CXML_Element::GetAttrValue(const CFX_ByteStringC& name,
                                CFX_WideString& attribute) const {
  CFX_ByteStringC bsSpace;
  CFX_ByteStringC bsName;
  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
  return GetAttrValue(bsSpace, bsName, attribute);
}

bool CXML_Element::GetAttrValue(const CFX_ByteStringC& space,
                                const CFX_ByteStringC& name,
                                CFX_WideString& attribute) const {
  const CFX_WideString* pValue =
      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
  if (!pValue)
    return false;

  attribute = *pValue;
  return true;
}

bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& name,
                                  int& attribute) const {
  CFX_ByteStringC bsSpace;
  CFX_ByteStringC bsName;
  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
  const CFX_WideString* pwsValue =
      m_AttrMap.Lookup(CFX_ByteString(bsSpace), CFX_ByteString(bsName));
  if (!pwsValue)
    return false;

  attribute = pwsValue->GetInteger();
  return true;
}

bool CXML_Element::GetAttrInteger(const CFX_ByteStringC& space,
                                  const CFX_ByteStringC& name,
                                  int& attribute) const {
  const CFX_WideString* pwsValue =
      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
  if (!pwsValue)
    return false;

  attribute = pwsValue->GetInteger();
  return true;
}

bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& name,
                                float& attribute) const {
  CFX_ByteStringC bsSpace;
  CFX_ByteStringC bsName;
  FX_XML_SplitQualifiedName(name, bsSpace, bsName);
  return GetAttrFloat(bsSpace, bsName, attribute);
}

bool CXML_Element::GetAttrFloat(const CFX_ByteStringC& space,
                                const CFX_ByteStringC& name,
                                float& attribute) const {
  const CFX_WideString* pValue =
      m_AttrMap.Lookup(CFX_ByteString(space), CFX_ByteString(name));
  if (!pValue)
    return false;

  attribute = pValue->GetFloat();
  return true;
}

CXML_Element::ChildType CXML_Element::GetChildType(uint32_t index) const {
  return index < m_Children.size() ? m_Children[index].type : Invalid;
}

CFX_WideString CXML_Element::GetContent(uint32_t index) const {
  if (index < m_Children.size() && m_Children[index].type == Content) {
    CXML_Content* pContent =
        static_cast<CXML_Content*>(m_Children[index].child);
    if (pContent)
      return pContent->m_Content;
  }
  return CFX_WideString();
}

CXML_Element* CXML_Element::GetElement(uint32_t index) const {
  if (index < m_Children.size() && m_Children[index].type == Element)
    return static_cast<CXML_Element*>(m_Children[index].child);
  return nullptr;
}

uint32_t CXML_Element::CountElements(const CFX_ByteStringC& space,
                                     const CFX_ByteStringC& tag) const {
  int count = 0;
  for (const ChildRecord& record : m_Children) {
    if (record.type != Element)
      continue;

    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
        pKid->m_TagName == tag) {
      count++;
    }
  }
  return count;
}

CXML_Element* CXML_Element::GetElement(const CFX_ByteStringC& space,
                                       const CFX_ByteStringC& tag,
                                       int index) const {
  if (index < 0)
    return nullptr;

  for (const ChildRecord& record : m_Children) {
    if (record.type != Element)
      continue;

    CXML_Element* pKid = static_cast<CXML_Element*>(record.child);
    if ((space.IsEmpty() || pKid->m_QSpaceName == space) &&
        pKid->m_TagName == tag) {
      if (index-- == 0)
        return pKid;
    }
  }
  return nullptr;
}

uint32_t CXML_Element::FindElement(CXML_Element* pChild) const {
  int index = 0;
  for (const ChildRecord& record : m_Children) {
    if (record.type == Element &&
        static_cast<CXML_Element*>(record.child) == pChild) {
      return index;
    }
    ++index;
  }
  return 0xFFFFFFFF;
}

void CXML_Element::SetTag(const CFX_ByteStringC& qTagName) {
  ASSERT(!qTagName.IsEmpty());
  CFX_ByteStringC bsSpace;
  CFX_ByteStringC bsName;
  FX_XML_SplitQualifiedName(qTagName, bsSpace, bsName);
  m_QSpaceName = bsSpace;
  m_TagName = bsName;
}
