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

#include "chromeos-dbus-bindings/xml_interface_parser.h"

#include <utility>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_util.h>
#include <chromeos/strings/string_utils.h>

using std::string;
using std::vector;

namespace chromeos_dbus_bindings {

// static
const char XmlInterfaceParser::kArgumentTag[] = "arg";
const char XmlInterfaceParser::kInterfaceTag[] = "interface";
const char XmlInterfaceParser::kMethodTag[] = "method";
const char XmlInterfaceParser::kNodeTag[] = "node";
const char XmlInterfaceParser::kSignalTag[] = "signal";
const char XmlInterfaceParser::kPropertyTag[] = "property";
const char XmlInterfaceParser::kAnnotationTag[] = "annotation";
const char XmlInterfaceParser::kDocStringTag[] = "tp:docstring";
const char XmlInterfaceParser::kNameAttribute[] = "name";
const char XmlInterfaceParser::kTypeAttribute[] = "type";
const char XmlInterfaceParser::kValueAttribute[] = "value";
const char XmlInterfaceParser::kDirectionAttribute[] = "direction";
const char XmlInterfaceParser::kAccessAttribute[] = "access";
const char XmlInterfaceParser::kArgumentDirectionIn[] = "in";
const char XmlInterfaceParser::kArgumentDirectionOut[] = "out";

const char XmlInterfaceParser::kTrue[] = "true";
const char XmlInterfaceParser::kFalse[] = "false";

const char XmlInterfaceParser::kMethodConst[] =
    "org.chromium.DBus.Method.Const";
const char XmlInterfaceParser::kMethodAsync[] =
    "org.freedesktop.DBus.GLib.Async";
const char XmlInterfaceParser::kMethodIncludeDBusMessage[] =
    "org.chromium.DBus.Method.IncludeDBusMessage";

const char XmlInterfaceParser::kMethodKind[] = "org.chromium.DBus.Method.Kind";
const char XmlInterfaceParser::kMethodKindSimple[] = "simple";
const char XmlInterfaceParser::kMethodKindNormal[] = "normal";
const char XmlInterfaceParser::kMethodKindAsync[] = "async";
const char XmlInterfaceParser::kMethodKindRaw[] = "raw";

namespace {

string GetElementPath(const vector<string>& path) {
  return chromeos::string_utils::Join("/", path);
}

}  // anonymous namespace

bool XmlInterfaceParser::ParseXmlInterfaceFile(
    const std::string& contents,
    const std::vector<std::string>& ignore_interfaces) {
  auto parser = XML_ParserCreate(nullptr);
  XML_SetUserData(parser, this);
  XML_SetElementHandler(parser,
                        &XmlInterfaceParser::HandleElementStart,
                        &XmlInterfaceParser::HandleElementEnd);
  XML_SetCharacterDataHandler(parser, &XmlInterfaceParser::HandleCharData);
  const int kIsFinal = XML_TRUE;

  element_path_.clear();
  XML_Status res = XML_Parse(parser,
                             contents.c_str(),
                             contents.size(),
                             kIsFinal);
  XML_ParserFree(parser);

  if (res != XML_STATUS_OK) {
    LOG(ERROR) << "XML parse failure";
    return false;
  }

  CHECK(element_path_.empty());

  if (!ignore_interfaces.empty()) {
    // Remove interfaces whose names are in |ignore_interfaces| list.
    auto condition = [&ignore_interfaces](const Interface& itf) {
      return std::find(ignore_interfaces.begin(), ignore_interfaces.end(),
                       itf.name) != ignore_interfaces.end();
    };
    auto p = std::remove_if(interfaces_.begin(), interfaces_.end(), condition);
    interfaces_.erase(p, interfaces_.end());
  }
  return true;
}

void XmlInterfaceParser::OnOpenElement(
    const string& element_name, const XmlAttributeMap& attributes) {
  string prev_element;
  if (!element_path_.empty())
    prev_element = element_path_.back();
  element_path_.push_back(element_name);
  if (element_name == kNodeTag) {
    CHECK(prev_element.empty() || prev_element == kNodeTag)
        << "Unexpected tag " << element_name << " inside " << prev_element;
    // 'name' attribute is optional for <node> element.
    string name;
    GetElementAttribute(attributes, element_path_, kNameAttribute, &name);
    base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
    node_names_.push_back(name);
  } else if (element_name == kInterfaceTag) {
    CHECK_EQ(kNodeTag, prev_element)
        << "Unexpected tag " << element_name << " inside " << prev_element;
    string interface_name = GetValidatedElementName(attributes, element_path_);
    Interface itf(interface_name,
                  std::vector<Interface::Method>{},
                  std::vector<Interface::Signal>{},
                  std::vector<Interface::Property>{});
    itf.path = node_names_.back();
    interfaces_.push_back(std::move(itf));
  } else if (element_name == kMethodTag) {
    CHECK_EQ(kInterfaceTag, prev_element)
        << "Unexpected tag " << element_name << " inside " << prev_element;
    interfaces_.back().methods.push_back(
        Interface::Method(GetValidatedElementName(attributes, element_path_)));
  } else if (element_name == kSignalTag) {
    CHECK_EQ(kInterfaceTag, prev_element)
        << "Unexpected tag " << element_name << " inside " << prev_element;
    interfaces_.back().signals.push_back(
        Interface::Signal(GetValidatedElementName(attributes, element_path_)));
  } else if (element_name == kPropertyTag) {
    CHECK_EQ(kInterfaceTag, prev_element)
        << "Unexpected tag " << element_name << " inside " << prev_element;
    interfaces_.back().properties.push_back(ParseProperty(attributes,
                                                          element_path_));
  } else if (element_name == kArgumentTag) {
    if (prev_element == kMethodTag) {
      AddMethodArgument(attributes);
    } else if (prev_element == kSignalTag) {
      AddSignalArgument(attributes);
    } else {
      LOG(FATAL) << "Unexpected tag " << element_name
                 << " inside " << prev_element;
    }
  } else if (element_name == kAnnotationTag) {
    string name = GetValidatedElementAttribute(attributes, element_path_,
                                               kNameAttribute);
    // Value is optional. Default to empty string if omitted.
    string value;
    GetElementAttribute(attributes, element_path_, kValueAttribute, &value);
    if (prev_element == kInterfaceTag) {
      // Parse interface annotations...
    } else if (prev_element == kMethodTag) {
      // Parse method annotations...
      Interface::Method& method = interfaces_.back().methods.back();
      if (name == kMethodConst) {
        CHECK(value == kTrue || value == kFalse);
        method.is_const = (value == kTrue);
      } else if (name == kMethodIncludeDBusMessage) {
        CHECK(value == kTrue || value == kFalse);
        method.include_dbus_message = (value == kTrue);
      } else if (name == kMethodAsync) {
        // Support GLib.Async annotation as well.
        method.kind = Interface::Method::Kind::kAsync;
      } else if (name == kMethodKind) {
        if (value == kMethodKindSimple) {
          method.kind = Interface::Method::Kind::kSimple;
        } else if (value == kMethodKindNormal) {
          method.kind = Interface::Method::Kind::kNormal;
        } else if (value == kMethodKindAsync) {
          method.kind = Interface::Method::Kind::kAsync;
        } else if (value == kMethodKindRaw) {
          method.kind = Interface::Method::Kind::kRaw;
        } else {
          LOG(FATAL) << "Invalid method kind: " << value;
        }
      }
    } else if (prev_element == kSignalTag) {
      // Parse signal annotations...
    } else if (prev_element == kPropertyTag) {
      // Parse property annotations...
    } else {
      LOG(FATAL) << "Unexpected tag " << element_name
                 << " inside " << prev_element;
    }
  } else if (element_name == kDocStringTag) {
    CHECK(!prev_element.empty() && prev_element != kNodeTag)
        << "Unexpected tag " << element_name << " inside " << prev_element;
  }
}

void XmlInterfaceParser::OnCharData(const std::string& content) {
  // Handle the text data only for <tp:docstring> element.
  if (element_path_.back() != kDocStringTag)
    return;

  CHECK_GT(element_path_.size(), 1u);
  string* doc_string_ptr = nullptr;
  string target_element = element_path_[element_path_.size() - 2];
  if (target_element == kInterfaceTag) {
    doc_string_ptr = &(interfaces_.back().doc_string);
  } else if (target_element == kMethodTag) {
    doc_string_ptr = &(interfaces_.back().methods.back().doc_string);
  } else if (target_element == kSignalTag) {
    doc_string_ptr = &(interfaces_.back().signals.back().doc_string);
  } else if (target_element == kPropertyTag) {
    doc_string_ptr = &(interfaces_.back().properties.back().doc_string);
  }

  // If <tp:docstring> is attached to elements we don't care about, do nothing.
  if (doc_string_ptr == nullptr)
    return;

  (*doc_string_ptr) += content;
}


void XmlInterfaceParser::AddMethodArgument(const XmlAttributeMap& attributes) {
  string argument_direction;
  vector<string> path = element_path_;
  path.push_back(kArgumentTag);
  bool is_direction_paramter_present = GetElementAttribute(
      attributes, path, kDirectionAttribute, &argument_direction);
  vector<Interface::Argument>* argument_list = nullptr;
  if (!is_direction_paramter_present ||
      argument_direction == kArgumentDirectionIn) {
    argument_list = &interfaces_.back().methods.back().input_arguments;
  } else if (argument_direction == kArgumentDirectionOut) {
    argument_list = &interfaces_.back().methods.back().output_arguments;
  } else {
    LOG(FATAL) << "Unknown method argument direction " << argument_direction;
  }
  argument_list->push_back(ParseArgument(attributes, element_path_));
}

void XmlInterfaceParser::AddSignalArgument(const XmlAttributeMap& attributes) {
  interfaces_.back().signals.back().arguments.push_back(
      ParseArgument(attributes, element_path_));
}

void XmlInterfaceParser::OnCloseElement(const string& element_name) {
  VLOG(1) << "Close Element " << element_name;
  CHECK(!element_path_.empty());
  CHECK_EQ(element_path_.back(), element_name);
  element_path_.pop_back();
  if (element_name == kNodeTag) {
    CHECK(!node_names_.empty());
    node_names_.pop_back();
  }
}

// static
bool XmlInterfaceParser::GetElementAttribute(
    const XmlAttributeMap& attributes,
    const vector<string>& element_path,
    const string& element_key,
    string* element_value) {
  if (attributes.find(element_key) == attributes.end()) {
    return false;
  }
  *element_value = attributes.find(element_key)->second;
  VLOG(1) << "Got " << GetElementPath(element_path) << " element with "
          << element_key << " = " << *element_value;
  return true;
}

// static
string XmlInterfaceParser::GetValidatedElementAttribute(
    const XmlAttributeMap& attributes,
    const vector<string>& element_path,
    const string& element_key) {
  string element_value;
  CHECK(GetElementAttribute(attributes,
                            element_path,
                            element_key,
                            &element_value))
      << GetElementPath(element_path) << " does not contain a " << element_key
      << " attribute";
  CHECK(!element_value.empty()) << GetElementPath(element_path) << " "
                                << element_key << " attribute is empty";
  return element_value;
}

// static
string XmlInterfaceParser::GetValidatedElementName(
    const XmlAttributeMap& attributes,
    const vector<string>& element_path) {
  return GetValidatedElementAttribute(attributes, element_path, kNameAttribute);
}

// static
Interface::Argument XmlInterfaceParser::ParseArgument(
    const XmlAttributeMap& attributes, const vector<string>& element_path) {
  vector<string> path = element_path;
  path.push_back(kArgumentTag);
  string argument_name;
  // Since the "name" field is optional, use the un-validated variant.
  GetElementAttribute(attributes, path, kNameAttribute, &argument_name);

  string argument_type = GetValidatedElementAttribute(
      attributes, path, kTypeAttribute);
  return Interface::Argument(argument_name, argument_type);
}

// static
Interface::Property XmlInterfaceParser::ParseProperty(
    const XmlAttributeMap& attributes,
    const std::vector<std::string>& element_path) {
  vector<string> path = element_path;
  path.push_back(kPropertyTag);
  string property_name = GetValidatedElementName(attributes, path);
  string property_type = GetValidatedElementAttribute(attributes, path,
                                                      kTypeAttribute);
  string property_access = GetValidatedElementAttribute(attributes, path,
                                                        kAccessAttribute);
  return Interface::Property(property_name, property_type, property_access);
}

// static
void XmlInterfaceParser::HandleElementStart(void* user_data,
                                            const XML_Char* element,
                                            const XML_Char** attr) {
  XmlAttributeMap attributes;
  if (attr != nullptr) {
    for (size_t n = 0; attr[n] != nullptr && attr[n+1] != nullptr; n += 2) {
      auto key = attr[n];
      auto value = attr[n + 1];
      attributes.insert(std::make_pair(key, value));
    }
  }
  auto parser = reinterpret_cast<XmlInterfaceParser*>(user_data);
  parser->OnOpenElement(element, attributes);
}

// static
void XmlInterfaceParser::HandleElementEnd(void* user_data,
                                          const XML_Char* element) {
  auto parser = reinterpret_cast<XmlInterfaceParser*>(user_data);
  parser->OnCloseElement(element);
}

// static
void XmlInterfaceParser::HandleCharData(void* user_data,
                                        const char *content,
                                        int length) {
  auto parser = reinterpret_cast<XmlInterfaceParser*>(user_data);
  parser->OnCharData(string(content, length));
}

}  // namespace chromeos_dbus_bindings
