// 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>

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";

const char XmlInterfaceParser::kArgumentProtobufClass[] =
    "org.chromium.DBus.Argument.ProtobufClass";

namespace {

string GetElementPath(const vector<string>& path) {
  return base::JoinString(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 if (prev_element == kArgumentTag) {
      // Retrieve protobuf type if any.
      if (name == kArgumentProtobufClass) {
        CHECK_EQ(last_arg_->type, "ay");
        last_arg_->type = string(kProtobufType) + value;
      }
    } 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_));
  last_arg_ = &argument_list->back();
}

void XmlInterfaceParser::AddSignalArgument(const XmlAttributeMap& attributes) {
  vector<Interface::Argument>* argument_list =
      &interfaces_.back().signals.back().arguments;
  argument_list->push_back(ParseArgument(attributes, element_path_));
  last_arg_ = &argument_list->back();
}

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
