/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "XmlDom.h"

#include <expat.h>

#include <memory>
#include <stack>
#include <string>
#include <tuple>

#include "android-base/logging.h"

#include "ResourceUtils.h"
#include "trace/TraceBuffer.h"
#include "XmlPullParser.h"
#include "util/Util.h"

using ::android::InputStream;
using ::android::StringPiece;
using ::android::StringPiece16;

namespace aapt {
namespace xml {

constexpr char kXmlNamespaceSep = 1;

struct Stack {
  std::unique_ptr<xml::Element> root;
  std::stack<xml::Element*> node_stack;
  std::unique_ptr<xml::Element> pending_element;
  std::string pending_comment;
  std::unique_ptr<xml::Text> last_text_node;
};

// Extracts the namespace and name of an expanded element or attribute name.
static void SplitName(const char* name, std::string* out_ns, std::string* out_name) {
  const char* p = name;
  while (*p != 0 && *p != kXmlNamespaceSep) {
    p++;
  }

  if (*p == 0) {
    out_ns->clear();
    out_name->assign(name);
  } else {
    out_ns->assign(name, (p - name));
    out_name->assign(p + 1);
  }
}

static void FinishPendingText(Stack* stack) {
  if (stack->last_text_node != nullptr) {
    if (!stack->last_text_node->text.empty()) {
      CHECK(!stack->node_stack.empty());
      stack->node_stack.top()->AppendChild(std::move(stack->last_text_node));
    } else {
      // Drop an empty text node.
    }
    stack->last_text_node = nullptr;
  }
}

static void XMLCALL StartNamespaceHandler(void* user_data, const char* prefix, const char* uri) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
  FinishPendingText(stack);

  NamespaceDecl decl;
  decl.line_number = XML_GetCurrentLineNumber(parser);
  decl.column_number = XML_GetCurrentColumnNumber(parser);
  decl.prefix = prefix ? prefix : "";
  decl.uri = uri ? uri : "";

  if (stack->pending_element == nullptr) {
    stack->pending_element = util::make_unique<Element>();
  }
  stack->pending_element->namespace_decls.push_back(std::move(decl));
}

static void XMLCALL EndNamespaceHandler(void* user_data, const char* /*prefix*/) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
  FinishPendingText(stack);
}

static bool less_attribute(const Attribute& lhs, const Attribute& rhs) {
  return std::tie(lhs.namespace_uri, lhs.name, lhs.value) <
         std::tie(rhs.namespace_uri, rhs.name, rhs.value);
}

static void XMLCALL StartElementHandler(void* user_data, const char* name, const char** attrs) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
  FinishPendingText(stack);

  std::unique_ptr<Element> el;
  if (stack->pending_element != nullptr) {
    el = std::move(stack->pending_element);
  } else {
    el = util::make_unique<Element>();
  }

  el->line_number = XML_GetCurrentLineNumber(parser);
  el->column_number = XML_GetCurrentColumnNumber(parser);
  el->comment = std::move(stack->pending_comment);

  SplitName(name, &el->namespace_uri, &el->name);

  while (*attrs) {
    Attribute attribute;
    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
    attribute.value = *attrs++;
    el->attributes.push_back(std::move(attribute));
  }

  // Sort the attributes.
  std::sort(el->attributes.begin(), el->attributes.end(), less_attribute);

  // Add to the stack.
  Element* this_el = el.get();
  if (!stack->node_stack.empty()) {
    stack->node_stack.top()->AppendChild(std::move(el));
  } else {
    stack->root = std::move(el);
  }
  stack->node_stack.push(this_el);
}

static void XMLCALL EndElementHandler(void* user_data, const char* name) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
  FinishPendingText(stack);

  CHECK(!stack->node_stack.empty());
  // stack->nodeStack.top()->comment = std::move(stack->pendingComment);
  stack->node_stack.pop();
}

static void XMLCALL CharacterDataHandler(void* user_data, const char* s, int len) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));

  const StringPiece str(s, len);
  if (str.empty()) {
    return;
  }

  // See if we can just append the text to a previous text node.
  if (stack->last_text_node != nullptr) {
    stack->last_text_node->text.append(str.data(), str.size());
    return;
  }

  stack->last_text_node = util::make_unique<Text>();
  stack->last_text_node->line_number = XML_GetCurrentLineNumber(parser);
  stack->last_text_node->column_number = XML_GetCurrentColumnNumber(parser);
  stack->last_text_node->text.assign(str);
}

static void XMLCALL CommentDataHandler(void* user_data, const char* comment) {
  XML_Parser parser = reinterpret_cast<XML_Parser>(user_data);
  Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
  FinishPendingText(stack);

  if (!stack->pending_comment.empty()) {
    stack->pending_comment += '\n';
  }
  stack->pending_comment += comment;
}

std::unique_ptr<XmlResource> Inflate(InputStream* in, android::IDiagnostics* diag,
                                     const android::Source& source) {
  Stack stack;

  std::unique_ptr<std::remove_pointer<XML_Parser>::type, decltype(XML_ParserFree)*> parser = {
      XML_ParserCreateNS(nullptr, kXmlNamespaceSep), XML_ParserFree};
  XML_SetUserData(parser.get(), &stack);
  XML_UseParserAsHandlerArg(parser.get());
  XML_SetElementHandler(parser.get(), StartElementHandler, EndElementHandler);
  XML_SetNamespaceDeclHandler(parser.get(), StartNamespaceHandler, EndNamespaceHandler);
  XML_SetCharacterDataHandler(parser.get(), CharacterDataHandler);
  XML_SetCommentHandler(parser.get(), CommentDataHandler);

  const char* buffer = nullptr;
  size_t buffer_size = 0;
  while (in->Next(reinterpret_cast<const void**>(&buffer), &buffer_size)) {
    if (XML_Parse(parser.get(), buffer, buffer_size, false) == XML_STATUS_ERROR) {
      diag->Error(android::DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
      return {};
    }
  }

  if (in->HadError()) {
    diag->Error(android::DiagMessage(source) << in->GetError());
    return {};
  } else {
    // Finish off the parsing.
    if (XML_Parse(parser.get(), nullptr, 0u, true) == XML_STATUS_ERROR) {
      diag->Error(android::DiagMessage(source.WithLine(XML_GetCurrentLineNumber(parser.get())))
                  << XML_ErrorString(XML_GetErrorCode(parser.get())));
      return {};
    }
  }
  return util::make_unique<XmlResource>(ResourceFile{{}, {}, ResourceFile::Type::kUnknown, source},
                                        android::StringPool{}, std::move(stack.root));
}

static void CopyAttributes(Element* el, android::ResXMLParser* parser,
                           android::StringPool* out_pool) {
  const size_t attr_count = parser->getAttributeCount();
  if (attr_count > 0) {
    el->attributes.reserve(attr_count);
    for (size_t i = 0; i < attr_count; i++) {
      Attribute attr;
      size_t len;
      const char16_t* str16 = parser->getAttributeNamespace(i, &len);
      if (str16) {
        attr.namespace_uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
      }

      str16 = parser->getAttributeName(i, &len);
      if (str16) {
        attr.name = android::util::Utf16ToUtf8(StringPiece16(str16, len));
      }

      uint32_t res_id = parser->getAttributeNameResID(i);
      if (res_id > 0) {
        attr.compiled_attribute = AaptAttribute(::aapt::Attribute(), {res_id});
      }

      str16 = parser->getAttributeStringValue(i, &len);
      if (str16) {
        attr.value = android::util::Utf16ToUtf8(StringPiece16(str16, len));
      }

      android::Res_value res_value;
      if (parser->getAttributeValue(i, &res_value) > 0) {
        // Only compile the value if it is not a string, or it is a string that differs from
        // the raw attribute value.
        int32_t raw_value_idx = parser->getAttributeValueStringID(i);
        if (res_value.dataType != android::Res_value::TYPE_STRING || raw_value_idx < 0 ||
            static_cast<uint32_t>(raw_value_idx) != res_value.data) {
          attr.compiled_value = ResourceUtils::ParseBinaryResValue(
              ResourceType::kAnim, {}, parser->getStrings(), res_value, out_pool);
        }
      }

      el->attributes.push_back(std::move(attr));
    }
  }
}

std::unique_ptr<XmlResource> Inflate(const void* data, size_t len, std::string* out_error) {
  TRACE_CALL();
  // We import the android namespace because on Windows NO_ERROR is a macro, not
  // an enum, which causes errors when qualifying it with android::
  using namespace android;

  std::unique_ptr<XmlResource> xml_resource = util::make_unique<XmlResource>();

  std::stack<Element*> node_stack;
  std::unique_ptr<Element> pending_element;

  ResXMLTree tree;
  if (tree.setTo(data, len) != NO_ERROR) {
    if (out_error != nullptr) {
      *out_error = "failed to initialize ResXMLTree";
    }
    return {};
  }

  ResXMLParser::event_code_t code;
  while ((code = tree.next()) != ResXMLParser::BAD_DOCUMENT && code != ResXMLParser::END_DOCUMENT) {
    std::unique_ptr<Node> new_node;
    switch (code) {
      case ResXMLParser::START_NAMESPACE: {
        NamespaceDecl decl;
        decl.line_number = tree.getLineNumber();

        size_t len;
        const char16_t* str16 = tree.getNamespacePrefix(&len);
        if (str16) {
          decl.prefix = android::util::Utf16ToUtf8(StringPiece16(str16, len));
        }

        str16 = tree.getNamespaceUri(&len);
        if (str16) {
          decl.uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
        }

        if (pending_element == nullptr) {
          pending_element = util::make_unique<Element>();
        }
        // pending_element is not nullptr
        // NOLINTNEXTLINE(bugprone-use-after-move)
        pending_element->namespace_decls.push_back(std::move(decl));
        break;
      }

      case ResXMLParser::START_TAG: {
        std::unique_ptr<Element> el;
        if (pending_element != nullptr) {
          el = std::move(pending_element);
        } else {
          el = util::make_unique<Element>();
        }
        el->line_number = tree.getLineNumber();

        size_t len;
        const char16_t* str16 = tree.getElementNamespace(&len);
        if (str16) {
          el->namespace_uri = android::util::Utf16ToUtf8(StringPiece16(str16, len));
        }

        str16 = tree.getElementName(&len);
        if (str16) {
          el->name = android::util::Utf16ToUtf8(StringPiece16(str16, len));
        }

        Element* this_el = el.get();
        CopyAttributes(el.get(), &tree, &xml_resource->string_pool);

        if (!node_stack.empty()) {
          node_stack.top()->AppendChild(std::move(el));
        } else {
          xml_resource->root = std::move(el);
        }
        node_stack.push(this_el);
        break;
      }

      case ResXMLParser::TEXT: {
        std::unique_ptr<Text> text = util::make_unique<Text>();
        text->line_number = tree.getLineNumber();
        size_t len;
        const char16_t* str16 = tree.getText(&len);
        if (str16) {
          text->text = android::util::Utf16ToUtf8(StringPiece16(str16, len));
        }
        CHECK(!node_stack.empty());
        node_stack.top()->AppendChild(std::move(text));
        break;
      }

      case ResXMLParser::END_NAMESPACE:
        break;

      case ResXMLParser::END_TAG:
        CHECK(!node_stack.empty());
        node_stack.pop();
        break;

      default:
        LOG(FATAL) << "unhandled XML chunk type";
        break;
    }
  }
  return xml_resource;
}

std::unique_ptr<XmlResource> XmlResource::Clone() const {
  std::unique_ptr<XmlResource> cloned = util::make_unique<XmlResource>(file);
  CloningValueTransformer cloner(&cloned->string_pool);
  if (root != nullptr) {
    cloned->root = root->CloneElement([&](const xml::Element& src, xml::Element* dst) {
      dst->attributes.reserve(src.attributes.size());
      for (const xml::Attribute& attr : src.attributes) {
        xml::Attribute cloned_attr;
        cloned_attr.name = attr.name;
        cloned_attr.namespace_uri = attr.namespace_uri;
        cloned_attr.value = attr.value;
        cloned_attr.compiled_attribute = attr.compiled_attribute;
        if (attr.compiled_value != nullptr) {
          cloned_attr.compiled_value = attr.compiled_value->Transform(cloner);
        }
        dst->attributes.push_back(std::move(cloned_attr));
      }
    });
  }
  return cloned;
}

Element* FindRootElement(Node* node) {
  if (node == nullptr) {
    return nullptr;
  }

  while (node->parent != nullptr) {
    node = node->parent;
  }
  return NodeCast<Element>(node);
}

void Element::AppendChild(std::unique_ptr<Node> child) {
  child->parent = this;
  children.push_back(std::move(child));
}

void Element::InsertChild(size_t index, std::unique_ptr<Node> child) {
  child->parent = this;
  children.insert(children.begin() + index, std::move(child));
}

Attribute* Element::FindAttribute(StringPiece ns, StringPiece name) {
  return const_cast<Attribute*>(static_cast<const Element*>(this)->FindAttribute(ns, name));
}

const Attribute* Element::FindAttribute(StringPiece ns, StringPiece name) const {
  for (const auto& attr : attributes) {
    if (ns == attr.namespace_uri && name == attr.name) {
      return &attr;
    }
  }
  return nullptr;
}

void Element::RemoveAttribute(StringPiece ns, StringPiece name) {
  auto new_attr_end = std::remove_if(attributes.begin(), attributes.end(),
    [&](const Attribute& attr) -> bool {
      return ns == attr.namespace_uri && name == attr.name;
    });

  attributes.erase(new_attr_end, attributes.end());
}

Attribute* Element::FindOrCreateAttribute(StringPiece ns, StringPiece name) {
  Attribute* attr = FindAttribute(ns, name);
  if (attr == nullptr) {
    attributes.push_back(Attribute{std::string(ns), std::string(name)});
    attr = &attributes.back();
  }
  return attr;
}

Element* Element::FindChild(StringPiece ns, StringPiece name) {
  return FindChildWithAttribute(ns, name, {}, {}, {});
}

const Element* Element::FindChild(StringPiece ns, StringPiece name) const {
  return FindChildWithAttribute(ns, name, {}, {}, {});
}

Element* Element::FindChildWithAttribute(StringPiece ns, StringPiece name, StringPiece attr_ns,
                                         StringPiece attr_name, StringPiece attr_value) {
  return const_cast<Element*>(static_cast<const Element*>(this)->FindChildWithAttribute(
      ns, name, attr_ns, attr_name, attr_value));
}

const Element* Element::FindChildWithAttribute(StringPiece ns, StringPiece name,
                                               StringPiece attr_ns, StringPiece attr_name,
                                               StringPiece attr_value) const {
  for (const auto& child : children) {
    if (const Element* el = NodeCast<Element>(child.get())) {
      if (ns == el->namespace_uri && name == el->name) {
        if (attr_ns.empty() && attr_name.empty()) {
          return el;
        }

        const Attribute* attr = el->FindAttribute(attr_ns, attr_name);
        if (attr && attr_value == attr->value) {
          return el;
        }
      }
    }
  }
  return nullptr;
}

std::vector<Element*> Element::GetChildElements() {
  std::vector<Element*> elements;
  for (auto& child_node : children) {
    if (Element* child = NodeCast<Element>(child_node.get())) {
      elements.push_back(child);
    }
  }
  return elements;
}

std::unique_ptr<Node> Element::Clone(const ElementCloneFunc& el_cloner) const {
  auto el = util::make_unique<Element>();
  el->namespace_decls = namespace_decls;
  el->comment = comment;
  el->line_number = line_number;
  el->column_number = column_number;
  el->name = name;
  el->namespace_uri = namespace_uri;
  el->attributes.reserve(attributes.size());
  el_cloner(*this, el.get());
  el->children.reserve(children.size());
  el->flag = flag;
  for (const std::unique_ptr<xml::Node>& child : children) {
    el->AppendChild(child->Clone(el_cloner));
  }
  return std::move(el);
}

std::unique_ptr<Element> Element::CloneElement(const ElementCloneFunc& el_cloner) const {
  return std::unique_ptr<Element>(static_cast<Element*>(Clone(el_cloner).release()));
}

void Element::Accept(Visitor* visitor) {
  visitor->BeforeVisitElement(this);
  visitor->Visit(this);
  visitor->AfterVisitElement(this);
}

void Element::Accept(ConstVisitor* visitor) const {
  visitor->BeforeVisitElement(this);
  visitor->Visit(this);
  visitor->AfterVisitElement(this);
}

std::unique_ptr<Node> Text::Clone(const ElementCloneFunc&) const {
  auto t = util::make_unique<Text>();
  t->comment = comment;
  t->line_number = line_number;
  t->column_number = column_number;
  t->text = text;
  return std::move(t);
}

void Text::Accept(Visitor* visitor) {
  visitor->Visit(this);
}

void Text::Accept(ConstVisitor* visitor) const {
  visitor->Visit(this);
}

void PackageAwareVisitor::BeforeVisitElement(Element* el) {
  std::vector<PackageDecl> decls;
  for (const NamespaceDecl& decl : el->namespace_decls) {
    if (std::optional<ExtractedPackage> maybe_package = ExtractPackageFromNamespace(decl.uri)) {
      decls.push_back(PackageDecl{decl.prefix, std::move(maybe_package.value())});
    }
  }
  package_decls_.push_back(std::move(decls));
}

void PackageAwareVisitor::AfterVisitElement(Element* el) {
  package_decls_.pop_back();
}

std::optional<ExtractedPackage> PackageAwareVisitor::TransformPackageAlias(
    StringPiece alias) const {
  if (alias.empty()) {
    return ExtractedPackage{{}, false /*private*/};
  }

  const auto rend = package_decls_.rend();
  for (auto iter = package_decls_.rbegin(); iter != rend; ++iter) {
    const std::vector<PackageDecl>& decls = *iter;
    const auto rend2 = decls.rend();
    for (auto iter2 = decls.rbegin(); iter2 != rend2; ++iter2) {
      const PackageDecl& decl = *iter2;
      if (alias == decl.prefix) {
        if (decl.package.package.empty()) {
          return ExtractedPackage{{}, decl.package.private_namespace};
        }
        return decl.package;
      }
    }
  }
  return {};
}

}  // namespace xml
}  // namespace aapt
