/*
 * 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());
  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
