// 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/dbus_signature.h"

#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <base/logging.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <dbus/dbus-protocol.h>

using base::StringPrintf;
using std::string;
using std::vector;

namespace chromeos_dbus_bindings {

std::string DBusType::GetOutArgType(Receiver receiver) const {
  return GetBaseType(receiver == Receiver::kAdaptor ? Direction::kAppend
                                                    : Direction::kExtract) +
         "*";
}

namespace {

// DBusType representing simple numeric types, such as int.
class Scalar : public DBusType {
 public:
  enum class Type {
    kBoolean,
    kByte,
    kDouble,
    kInt16,
    kInt32,
    kInt64,
    kUint16,
    kUint32,
    kUint64,
  };

  explicit Scalar(Type type) : type_(type) {}

  bool IsValidPropertyType() const override { return true; }

  std::string GetBaseType(Direction direction) const override {
    switch (type_) {
      case Type::kBoolean:
        return "bool";
      case Type::kByte:
        return "uint8_t";
      case Type::kDouble:
        return "double";
      case Type::kInt16:
        return "int16_t";
      case Type::kInt32:
        return "int32_t";
      case Type::kInt64:
        return "int64_t";
      case Type::kUint16:
        return "uint16_t";
      case Type::kUint32:
        return "uint32_t";
      case Type::kUint64:
        return "uint64_t";
    }
  }

  std::string GetInArgType(Receiver receiver) const override {
    return GetBaseType(receiver == Receiver::kAdaptor ? Direction::kExtract
                                                      : Direction::kAppend);
  }

  std::string GetCallbackArgType() const override {
    return GetBaseType(Direction::kExtract);
  }

 private:
  Type type_;

  DISALLOW_COPY_AND_ASSIGN(Scalar);
};

// DBusType representing argument types that correspond to C++ objects.
// Example would be brillo::Any or std::map.
class NonScalar : public DBusType {
 public:
  std::string GetInArgType(Receiver receiver) const override {
    return base::StringPrintf(
        "const %s&",
        GetBaseType(receiver == Receiver::kAdaptor ? Direction::kExtract
                                                   : Direction::kAppend)
            .c_str());
  }

  std::string GetCallbackArgType() const override {
    return base::StringPrintf("const %s&",
                              GetBaseType(Direction::kExtract).c_str());
  }
};

class SimpleNonScalar : public NonScalar {
 public:
  enum class Type {
    kObjectPath,
    kString,
    kVariant,
    kVariantDict,
  };

  explicit SimpleNonScalar(Type type) : type_(type) {}

  bool IsValidPropertyType() const override { return true; }

  std::string GetBaseType(Direction direction) const override {
    switch (type_) {
      case Type::kObjectPath:
        return "dbus::ObjectPath";
      case Type::kString:
        return "std::string";
      case Type::kVariant:
        return "brillo::Any";
      case Type::kVariantDict:
        return "brillo::VariantDictionary";
    }
  }

 private:
  Type type_;

  DISALLOW_COPY_AND_ASSIGN(SimpleNonScalar);
};

class FileDescriptor : public NonScalar {
 public:
  bool IsValidPropertyType() const override { return false; }

  std::string GetBaseType(Direction direction) const override {
    return direction == Direction::kExtract
               ? "base::ScopedFD"
               : "brillo::dbus_utils::FileDescriptor";
  }
};

class Array : public NonScalar {
 public:
  explicit Array(std::unique_ptr<DBusType> inner_type)
      : inner_type_(std::move(inner_type)) {}

  bool IsValidPropertyType() const override {
    return inner_type_->IsValidPropertyType();
  }

  std::string GetBaseType(Direction direction) const override {
    return base::StringPrintf("std::vector<%s>",
                              inner_type_->GetBaseType(direction).c_str());
  }

 private:
  std::unique_ptr<DBusType> inner_type_;

  DISALLOW_COPY_AND_ASSIGN(Array);
};

class Dict : public NonScalar {
 public:
  explicit Dict(std::unique_ptr<DBusType> key_type,
                std::unique_ptr<DBusType> value_type)
      : key_type_(std::move(key_type)), value_type_(std::move(value_type)) {}

  bool IsValidPropertyType() const override {
    return key_type_->IsValidPropertyType() &&
           value_type_->IsValidPropertyType();
  }

  std::string GetBaseType(Direction direction) const override {
    return base::StringPrintf("std::map<%s, %s>",
                              key_type_->GetBaseType(direction).c_str(),
                              value_type_->GetBaseType(direction).c_str());
  }

 private:
  std::unique_ptr<DBusType> key_type_;
  std::unique_ptr<DBusType> value_type_;

  DISALLOW_COPY_AND_ASSIGN(Dict);
};

class Struct : public NonScalar {
 public:
  explicit Struct(std::vector<std::unique_ptr<DBusType>>&& inner_types)
      : inner_types_(std::move(inner_types)) {}

  bool IsValidPropertyType() const override {
    for (const auto& child : inner_types_) {
      if (!child->IsValidPropertyType())
        return false;
    }
    return true;
  }

  std::string GetBaseType(Direction direction) const override {
    std::vector<std::string> child_types;
    for (const auto& child : inner_types_)
      child_types.push_back(child->GetBaseType(direction));
    return base::StringPrintf("std::tuple<%s>",
                              base::JoinString(child_types, ", ").c_str());
  }

 private:
  std::vector<std::unique_ptr<DBusType>> inner_types_;

  DISALLOW_COPY_AND_ASSIGN(Struct);
};

class ProtobufClass : public NonScalar {
 public:
  explicit ProtobufClass(std::string protobuf_class)
      : protobuf_class_(protobuf_class) {}

  bool IsValidPropertyType() const override {
    // Using protobuf class for property is not yet supported.
    return false;
  }

  std::string GetBaseType(Direction direction) const override {
    return protobuf_class_;
  }

 private:
  string protobuf_class_;

  DISALLOW_COPY_AND_ASSIGN(ProtobufClass);
};

}  // namespace

DBusSignature::DBusSignature() = default;

std::unique_ptr<DBusType> DBusSignature::Parse(const string& signature) {
  string::const_iterator end;
  auto type = GetTypenameForSignature(signature.begin(), signature.end(), &end);
  if (!type) {
    LOG(ERROR) << "Parse failed for signature " << signature;
    return nullptr;
  }

  if (end != signature.end()) {
    LOG(WARNING) << "A portion of signature " << signature
                 << " is left unparsed: " << string(end, signature.end());
  }

  return type;
}

std::unique_ptr<DBusType> DBusSignature::GetTypenameForSignature(
    string::const_iterator signature,
    string::const_iterator end,
    string::const_iterator* next) {
  DCHECK(next);
  if (signature == end) {
    LOG(ERROR) << "Signature is empty";
    return nullptr;
  }

  string::const_iterator cur = signature;
  int signature_value = *cur++;
  std::unique_ptr<DBusType> type;
  switch (signature_value) {
    case DBUS_STRUCT_BEGIN_CHAR:
      type = GetStructTypenameForSignature(cur, end, &cur);
      break;
    case DBUS_TYPE_ARRAY:
      type = GetArrayTypenameForSignature(cur, end, &cur);
      break;
    case DBUS_TYPE_BOOLEAN:
      type = std::make_unique<Scalar>(Scalar::Type::kBoolean);
      break;
    case DBUS_TYPE_BYTE:
      type = std::make_unique<Scalar>(Scalar::Type::kByte);
      break;
    case DBUS_TYPE_DOUBLE:
      type = std::make_unique<Scalar>(Scalar::Type::kDouble);
      break;
    case DBUS_TYPE_OBJECT_PATH:
      type =
          std::make_unique<SimpleNonScalar>(SimpleNonScalar::Type::kObjectPath);
      break;
    case DBUS_TYPE_INT16:
      type = std::make_unique<Scalar>(Scalar::Type::kInt16);
      break;
    case DBUS_TYPE_INT32:
      type = std::make_unique<Scalar>(Scalar::Type::kInt32);
      break;
    case DBUS_TYPE_INT64:
      type = std::make_unique<Scalar>(Scalar::Type::kInt64);
      break;
    case DBUS_TYPE_STRING:
      type = std::make_unique<SimpleNonScalar>(SimpleNonScalar::Type::kString);
      break;
    case DBUS_TYPE_UNIX_FD:
      type = std::make_unique<FileDescriptor>();
      break;
    case DBUS_TYPE_UINT16:
      type = std::make_unique<Scalar>(Scalar::Type::kUint16);
      break;
    case DBUS_TYPE_UINT32:
      type = std::make_unique<Scalar>(Scalar::Type::kUint32);
      break;
    case DBUS_TYPE_UINT64:
      type = std::make_unique<Scalar>(Scalar::Type::kUint64);
      break;
    case DBUS_TYPE_VARIANT:
      type = std::make_unique<SimpleNonScalar>(SimpleNonScalar::Type::kVariant);
      break;
    case DBUS_TYPE_CHROMEOS_PROTOBUF:
      type = std::make_unique<ProtobufClass>(string(cur, end));
      cur = end;
      break;
    default:
      LOG(ERROR) << "Unexpected token " << *signature;
      return nullptr;
  }

  *next = cur;
  return type;
}

bool DBusSignature::ParseChildTypes(
    string::const_iterator signature,
    string::const_iterator end,
    string::value_type end_char,
    string::const_iterator* next,
    vector<std::unique_ptr<DBusType>>* children) {
  DCHECK(next);
  DCHECK(children);
  string::const_iterator cur = signature;

  while (cur != end && *cur != end_char) {
    auto child = GetTypenameForSignature(cur, end, &cur);
    if (!child) {
      LOG(ERROR) << "Unable to decode child elements starting at "
                 << string(cur, end);
      return false;
    }

    children->push_back(std::move(child));
  }

  if (cur == end) {
    LOG(ERROR) << "At end of string while processing container type "
               << "starting at " << string(signature, end);
    return false;
  }

  DCHECK_EQ(end_char, *cur);
  *next = cur + 1;
  return true;
}

std::unique_ptr<DBusType> DBusSignature::GetArrayTypenameForSignature(
    string::const_iterator signature,
    string::const_iterator end,
    string::const_iterator* next) {
  DCHECK(next);
  if (signature == end) {
    LOG(ERROR) << "At end of string while reading array parameter";
    return nullptr;
  }

  if (*signature == DBUS_DICT_ENTRY_BEGIN_CHAR)
    return GetDictTypenameForSignature(signature, end, next);

  string::const_iterator cur = signature;
  auto child = GetTypenameForSignature(cur, end, &cur);
  if (!child) {
    LOG(ERROR) << "Unable to decode child element starting at "
               << string(cur, end);
    return nullptr;
  }

  *next = cur;
  return std::make_unique<Array>(std::move(child));
}

std::unique_ptr<DBusType> DBusSignature::GetDictTypenameForSignature(
    string::const_iterator signature,
    string::const_iterator end,
    string::const_iterator* next) {
  DCHECK(next);
  string::const_iterator cur = signature;

  // The dictionary entry type has to be at least 4 characters long:
  // two curly braces and two characters for the key and value types.
  if (end - cur < 4) {
    LOG(ERROR) << "Malformed dictionary at " << string(signature, end);
    return nullptr;
  }

  // Check for VariantDictionary, which is a special case.
  if (string(cur, cur + 4) == "{sv}") {
    *next = cur + 4;
    return std::make_unique<SimpleNonScalar>(
        SimpleNonScalar::Type::kVariantDict);
  }

  ++cur;

  vector<std::unique_ptr<DBusType>> children;
  if (!ParseChildTypes(cur, end, DBUS_DICT_ENTRY_END_CHAR, &cur, &children))
    return nullptr;

  if (children.size() != 2) {
    LOG(ERROR) << "Dict entry contains " << children.size()
               << " members starting at " << string(signature, end)
               << " but dict entries can only have 2 sub-types.";
    return nullptr;
  }

  *next = cur;
  return std::make_unique<Dict>(std::move(children[0]), std::move(children[1]));
}

std::unique_ptr<DBusType> DBusSignature::GetStructTypenameForSignature(
    string::const_iterator signature,
    string::const_iterator end,
    string::const_iterator* next) {
  DCHECK(next);

  if (signature == end) {
    LOG(ERROR) << "At end of string while reading struct parameter";
    return nullptr;
  }

  string::const_iterator cur = signature;
  vector<std::unique_ptr<DBusType>> children;
  if (!ParseChildTypes(cur, end, DBUS_STRUCT_END_CHAR, &cur, &children))
    return nullptr;

  *next = cur;
  return std::make_unique<Struct>(std::move(children));
}

}  // namespace chromeos_dbus_bindings
