/*
 * 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 <iostream>
#include <string>

#include "util/Maybe.h"
#include "util/Util.h"
#include "xml/XmlPullParser.h"
#include "xml/XmlUtil.h"

using android::StringPiece;

namespace aapt {
namespace xml {

constexpr char kXmlNamespaceSep = 1;

XmlPullParser::XmlPullParser(std::istream& in) : in_(in), empty_(), depth_(0) {
  parser_ = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
  XML_SetUserData(parser_, this);
  XML_SetElementHandler(parser_, StartElementHandler, EndElementHandler);
  XML_SetNamespaceDeclHandler(parser_, StartNamespaceHandler,
                              EndNamespaceHandler);
  XML_SetCharacterDataHandler(parser_, CharacterDataHandler);
  XML_SetCommentHandler(parser_, CommentDataHandler);
  event_queue_.push(EventData{Event::kStartDocument, 0, depth_++});
}

XmlPullParser::~XmlPullParser() { XML_ParserFree(parser_); }

XmlPullParser::Event XmlPullParser::Next() {
  const Event currentEvent = event();
  if (currentEvent == Event::kBadDocument ||
      currentEvent == Event::kEndDocument) {
    return currentEvent;
  }

  event_queue_.pop();
  while (event_queue_.empty()) {
    in_.read(buffer_, sizeof(buffer_) / sizeof(*buffer_));

    const bool done = in_.eof();
    if (in_.bad() && !done) {
      error_ = strerror(errno);
      event_queue_.push(EventData{Event::kBadDocument});
      continue;
    }

    if (XML_Parse(parser_, buffer_, in_.gcount(), done) == XML_STATUS_ERROR) {
      error_ = XML_ErrorString(XML_GetErrorCode(parser_));
      event_queue_.push(EventData{Event::kBadDocument});
      continue;
    }

    if (done) {
      event_queue_.push(EventData{Event::kEndDocument, 0, 0});
    }
  }

  Event next_event = event();

  // Record namespace prefixes and package names so that we can do our own
  // handling of references that use namespace aliases.
  if (next_event == Event::kStartNamespace ||
      next_event == Event::kEndNamespace) {
    Maybe<ExtractedPackage> result =
        ExtractPackageFromNamespace(namespace_uri());
    if (next_event == Event::kStartNamespace) {
      if (result) {
        package_aliases_.emplace_back(
            PackageDecl{namespace_prefix(), std::move(result.value())});
      }
    } else {
      if (result) {
        package_aliases_.pop_back();
      }
    }
  }

  return next_event;
}

XmlPullParser::Event XmlPullParser::event() const {
  return event_queue_.front().event;
}

const std::string& XmlPullParser::error() const { return error_; }

const std::string& XmlPullParser::comment() const {
  return event_queue_.front().data1;
}

size_t XmlPullParser::line_number() const {
  return event_queue_.front().line_number;
}

size_t XmlPullParser::depth() const { return event_queue_.front().depth; }

const std::string& XmlPullParser::text() const {
  if (event() != Event::kText) {
    return empty_;
  }
  return event_queue_.front().data1;
}

const std::string& XmlPullParser::namespace_prefix() const {
  const Event current_event = event();
  if (current_event != Event::kStartNamespace &&
      current_event != Event::kEndNamespace) {
    return empty_;
  }
  return event_queue_.front().data1;
}

const std::string& XmlPullParser::namespace_uri() const {
  const Event current_event = event();
  if (current_event != Event::kStartNamespace &&
      current_event != Event::kEndNamespace) {
    return empty_;
  }
  return event_queue_.front().data2;
}

Maybe<ExtractedPackage> XmlPullParser::TransformPackageAlias(
    const StringPiece& alias, const StringPiece& local_package) const {
  if (alias.empty()) {
    return ExtractedPackage{local_package.to_string(), false /* private */};
  }

  const auto end_iter = package_aliases_.rend();
  for (auto iter = package_aliases_.rbegin(); iter != end_iter; ++iter) {
    if (alias == iter->prefix) {
      if (iter->package.package.empty()) {
        return ExtractedPackage{local_package.to_string(), iter->package.private_namespace};
      }
      return iter->package;
    }
  }
  return {};
}

const std::string& XmlPullParser::element_namespace() const {
  const Event current_event = event();
  if (current_event != Event::kStartElement &&
      current_event != Event::kEndElement) {
    return empty_;
  }
  return event_queue_.front().data1;
}

const std::string& XmlPullParser::element_name() const {
  const Event current_event = event();
  if (current_event != Event::kStartElement &&
      current_event != Event::kEndElement) {
    return empty_;
  }
  return event_queue_.front().data2;
}

XmlPullParser::const_iterator XmlPullParser::begin_attributes() const {
  return event_queue_.front().attributes.begin();
}

XmlPullParser::const_iterator XmlPullParser::end_attributes() const {
  return event_queue_.front().attributes.end();
}

size_t XmlPullParser::attribute_count() const {
  if (event() != Event::kStartElement) {
    return 0;
  }
  return event_queue_.front().attributes.size();
}

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

void XMLCALL XmlPullParser::StartNamespaceHandler(void* user_data,
                                                  const char* prefix,
                                                  const char* uri) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);
  std::string namespace_uri = uri != nullptr ? uri : std::string();
  parser->namespace_uris_.push(namespace_uri);
  parser->event_queue_.push(
      EventData{Event::kStartNamespace,
                XML_GetCurrentLineNumber(parser->parser_), parser->depth_++,
                prefix != nullptr ? prefix : std::string(), namespace_uri});
}

void XMLCALL XmlPullParser::StartElementHandler(void* user_data,
                                                const char* name,
                                                const char** attrs) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);

  EventData data = {Event::kStartElement,
                    XML_GetCurrentLineNumber(parser->parser_),
                    parser->depth_++};
  SplitName(name, &data.data1, &data.data2);

  while (*attrs) {
    Attribute attribute;
    SplitName(*attrs++, &attribute.namespace_uri, &attribute.name);
    attribute.value = *attrs++;

    // Insert in sorted order.
    auto iter = std::lower_bound(data.attributes.begin(), data.attributes.end(),
                                 attribute);
    data.attributes.insert(iter, std::move(attribute));
  }

  // Move the structure into the queue (no copy).
  parser->event_queue_.push(std::move(data));
}

void XMLCALL XmlPullParser::CharacterDataHandler(void* user_data, const char* s,
                                                 int len) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);

  parser->event_queue_.push(EventData{Event::kText, XML_GetCurrentLineNumber(parser->parser_),
                                      parser->depth_, std::string(s, len)});
}

void XMLCALL XmlPullParser::EndElementHandler(void* user_data,
                                              const char* name) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);

  EventData data = {Event::kEndElement,
                    XML_GetCurrentLineNumber(parser->parser_),
                    --(parser->depth_)};
  SplitName(name, &data.data1, &data.data2);

  // Move the data into the queue (no copy).
  parser->event_queue_.push(std::move(data));
}

void XMLCALL XmlPullParser::EndNamespaceHandler(void* user_data,
                                                const char* prefix) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);

  parser->event_queue_.push(
      EventData{Event::kEndNamespace, XML_GetCurrentLineNumber(parser->parser_),
                --(parser->depth_), prefix != nullptr ? prefix : std::string(),
                parser->namespace_uris_.top()});
  parser->namespace_uris_.pop();
}

void XMLCALL XmlPullParser::CommentDataHandler(void* user_data,
                                               const char* comment) {
  XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(user_data);

  parser->event_queue_.push(EventData{Event::kComment,
                                      XML_GetCurrentLineNumber(parser->parser_),
                                      parser->depth_, comment});
}

Maybe<StringPiece> FindAttribute(const XmlPullParser* parser,
                                 const StringPiece& name) {
  auto iter = parser->FindAttribute("", name);
  if (iter != parser->end_attributes()) {
    return StringPiece(util::TrimWhitespace(iter->value));
  }
  return {};
}

Maybe<StringPiece> FindNonEmptyAttribute(const XmlPullParser* parser,
                                         const StringPiece& name) {
  auto iter = parser->FindAttribute("", name);
  if (iter != parser->end_attributes()) {
    StringPiece trimmed = util::TrimWhitespace(iter->value);
    if (!trimmed.empty()) {
      return trimmed;
    }
  }
  return {};
}

}  // namespace xml
}  // namespace aapt
