// Copyright (c) 2012 The Chromium 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 "dbus/property.h"

#include <stddef.h>

#include <memory>

#include "base/bind.h"
#include "base/logging.h"

#include "dbus/message.h"
#include "dbus/object_path.h"
#include "dbus/object_proxy.h"

namespace dbus {

//
// PropertyBase implementation.
//

PropertyBase::PropertyBase() : property_set_(nullptr), is_valid_(false) {}

PropertyBase::~PropertyBase() = default;

void PropertyBase::Init(PropertySet* property_set, const std::string& name) {
  DCHECK(!property_set_);
  property_set_ = property_set;
  is_valid_ = false;
  name_ = name;
}

//
// PropertySet implementation.
//

PropertySet::PropertySet(
    ObjectProxy* object_proxy,
    const std::string& interface,
    const PropertyChangedCallback& property_changed_callback)
    : object_proxy_(object_proxy),
      interface_(interface),
      property_changed_callback_(property_changed_callback),
      weak_ptr_factory_(this) {}

PropertySet::~PropertySet() = default;

void PropertySet::RegisterProperty(const std::string& name,
                                   PropertyBase* property) {
  property->Init(this, name);
  properties_map_[name] = property;
}

void PropertySet::ConnectSignals() {
  DCHECK(object_proxy_);
  object_proxy_->ConnectToSignal(
      kPropertiesInterface,
      kPropertiesChanged,
      base::Bind(&PropertySet::ChangedReceived,
                 weak_ptr_factory_.GetWeakPtr()),
      base::Bind(&PropertySet::ChangedConnected,
                 weak_ptr_factory_.GetWeakPtr()));
}


void PropertySet::ChangedReceived(Signal* signal) {
  DCHECK(signal);
  MessageReader reader(signal);

  std::string interface;
  if (!reader.PopString(&interface)) {
    LOG(WARNING) << "Property changed signal has wrong parameters: "
                 << "expected interface name: " << signal->ToString();
    return;
  }

  if (interface != this->interface())
    return;

  if (!UpdatePropertiesFromReader(&reader)) {
    LOG(WARNING) << "Property changed signal has wrong parameters: "
                 << "expected dictionary: " << signal->ToString();
  }

  if (!InvalidatePropertiesFromReader(&reader)) {
    LOG(WARNING) << "Property changed signal has wrong parameters: "
                 << "expected array to invalidate: " << signal->ToString();
  }
}

void PropertySet::ChangedConnected(const std::string& interface_name,
                                   const std::string& signal_name,
                                   bool success) {
  LOG_IF(WARNING, !success) << "Failed to connect to " << signal_name
                            << "signal.";
}


void PropertySet::Get(PropertyBase* property, GetCallback callback) {
  MethodCall method_call(kPropertiesInterface, kPropertiesGet);
  MessageWriter writer(&method_call);
  writer.AppendString(interface());
  writer.AppendString(property->name());

  DCHECK(object_proxy_);
  object_proxy_->CallMethod(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
                            base::BindOnce(&PropertySet::OnGet, GetWeakPtr(),
                                           property, std::move(callback)));
}

void PropertySet::OnGet(PropertyBase* property, GetCallback callback,
                        Response* response) {
  if (!response) {
    LOG(WARNING) << property->name() << ": Get: failed.";
    return;
  }

  MessageReader reader(response);
  if (property->PopValueFromReader(&reader)) {
    property->set_valid(true);
    NotifyPropertyChanged(property->name());
  } else {
    if (property->is_valid()) {
      property->set_valid(false);
      NotifyPropertyChanged(property->name());
    }
  }

  if (!callback.is_null())
    std::move(callback).Run(response);
}

bool PropertySet::GetAndBlock(PropertyBase* property) {
  MethodCall method_call(kPropertiesInterface, kPropertiesGet);
  MessageWriter writer(&method_call);
  writer.AppendString(interface());
  writer.AppendString(property->name());

  DCHECK(object_proxy_);
  std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
      &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));

  if (!response.get()) {
    LOG(WARNING) << property->name() << ": GetAndBlock: failed.";
    return false;
  }

  MessageReader reader(response.get());
  if (property->PopValueFromReader(&reader)) {
    property->set_valid(true);
    NotifyPropertyChanged(property->name());
  } else {
    if (property->is_valid()) {
      property->set_valid(false);
      NotifyPropertyChanged(property->name());
    }
  }
  return true;
}

void PropertySet::GetAll() {
  MethodCall method_call(kPropertiesInterface, kPropertiesGetAll);
  MessageWriter writer(&method_call);
  writer.AppendString(interface());

  DCHECK(object_proxy_);
  object_proxy_->CallMethod(&method_call,
                            ObjectProxy::TIMEOUT_USE_DEFAULT,
                            base::Bind(&PropertySet::OnGetAll,
                                       weak_ptr_factory_.GetWeakPtr()));
}

void PropertySet::OnGetAll(Response* response) {
  if (!response) {
    LOG(WARNING) << "GetAll request failed for: " << interface_;
    return;
  }

  MessageReader reader(response);
  if (!UpdatePropertiesFromReader(&reader)) {
    LOG(WARNING) << "GetAll response has wrong parameters: "
                 << "expected dictionary: " << response->ToString();
  }
}

void PropertySet::Set(PropertyBase* property, SetCallback callback) {
  MethodCall method_call(kPropertiesInterface, kPropertiesSet);
  MessageWriter writer(&method_call);
  writer.AppendString(interface());
  writer.AppendString(property->name());
  property->AppendSetValueToWriter(&writer);

  DCHECK(object_proxy_);
  object_proxy_->CallMethod(&method_call, ObjectProxy::TIMEOUT_USE_DEFAULT,
                            base::BindOnce(&PropertySet::OnSet, GetWeakPtr(),
                                           property, std::move(callback)));
}

bool PropertySet::SetAndBlock(PropertyBase* property) {
  MethodCall method_call(kPropertiesInterface, kPropertiesSet);
  MessageWriter writer(&method_call);
  writer.AppendString(interface());
  writer.AppendString(property->name());
  property->AppendSetValueToWriter(&writer);

  DCHECK(object_proxy_);
  std::unique_ptr<dbus::Response> response(object_proxy_->CallMethodAndBlock(
      &method_call, ObjectProxy::TIMEOUT_USE_DEFAULT));
  if (response.get())
    return true;
  return false;
}

void PropertySet::OnSet(PropertyBase* property,
                        SetCallback callback,
                        Response* response) {
  LOG_IF(WARNING, !response) << property->name() << ": Set: failed.";
  if (!callback.is_null())
    std::move(callback).Run(response);
}

bool PropertySet::UpdatePropertiesFromReader(MessageReader* reader) {
  DCHECK(reader);
  MessageReader array_reader(nullptr);
  if (!reader->PopArray(&array_reader))
    return false;

  while (array_reader.HasMoreData()) {
    MessageReader dict_entry_reader(nullptr);
    if (array_reader.PopDictEntry(&dict_entry_reader))
      UpdatePropertyFromReader(&dict_entry_reader);
  }

  return true;
}

bool PropertySet::UpdatePropertyFromReader(MessageReader* reader) {
  DCHECK(reader);

  std::string name;
  if (!reader->PopString(&name))
    return false;

  PropertiesMap::iterator it = properties_map_.find(name);
  if (it == properties_map_.end())
    return false;

  PropertyBase* property = it->second;
  if (property->PopValueFromReader(reader)) {
    property->set_valid(true);
    NotifyPropertyChanged(name);
    return true;
  } else {
    if (property->is_valid()) {
      property->set_valid(false);
      NotifyPropertyChanged(property->name());
    }
    return false;
  }
}

bool PropertySet::InvalidatePropertiesFromReader(MessageReader* reader) {
  DCHECK(reader);
  MessageReader array_reader(nullptr);
  if (!reader->PopArray(&array_reader))
    return false;

  while (array_reader.HasMoreData()) {
    std::string name;
    if (!array_reader.PopString(&name))
      return false;

    PropertiesMap::iterator it = properties_map_.find(name);
    if (it == properties_map_.end())
      continue;

    PropertyBase* property = it->second;
    if (property->is_valid()) {
      property->set_valid(false);
      NotifyPropertyChanged(property->name());
    }
  }

  return true;
}

void PropertySet::NotifyPropertyChanged(const std::string& name) {
  if (!property_changed_callback_.is_null())
    property_changed_callback_.Run(name);
}

//
// Property<Byte> specialization.
//

template <>
Property<uint8_t>::Property()
    : value_(0) {}

template <>
bool Property<uint8_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfByte(&value_);
}

template <>
void Property<uint8_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfByte(set_value_);
}

//
// Property<bool> specialization.
//

template <>
Property<bool>::Property() : value_(false) {
}

template <>
bool Property<bool>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfBool(&value_);
}

template <>
void Property<bool>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfBool(set_value_);
}

//
// Property<int16_t> specialization.
//

template <>
Property<int16_t>::Property()
    : value_(0) {}

template <>
bool Property<int16_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfInt16(&value_);
}

template <>
void Property<int16_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfInt16(set_value_);
}

//
// Property<uint16_t> specialization.
//

template <>
Property<uint16_t>::Property()
    : value_(0) {}

template <>
bool Property<uint16_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfUint16(&value_);
}

template <>
void Property<uint16_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfUint16(set_value_);
}

//
// Property<int32_t> specialization.
//

template <>
Property<int32_t>::Property()
    : value_(0) {}

template <>
bool Property<int32_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfInt32(&value_);
}

template <>
void Property<int32_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfInt32(set_value_);
}

//
// Property<uint32_t> specialization.
//

template <>
Property<uint32_t>::Property()
    : value_(0) {}

template <>
bool Property<uint32_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfUint32(&value_);
}

template <>
void Property<uint32_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfUint32(set_value_);
}

//
// Property<int64_t> specialization.
//

template <>
Property<int64_t>::Property()
    : value_(0), set_value_(0) {}

template <>
bool Property<int64_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfInt64(&value_);
}

template <>
void Property<int64_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfInt64(set_value_);
}

//
// Property<uint64_t> specialization.
//

template <>
Property<uint64_t>::Property()
    : value_(0) {}

template <>
bool Property<uint64_t>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfUint64(&value_);
}

template <>
void Property<uint64_t>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfUint64(set_value_);
}

//
// Property<double> specialization.
//

template <>
Property<double>::Property() : value_(0.0) {
}

template <>
bool Property<double>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfDouble(&value_);
}

template <>
void Property<double>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfDouble(set_value_);
}

//
// Property<std::string> specialization.
//

template <>
bool Property<std::string>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfString(&value_);
}

template <>
void Property<std::string>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfString(set_value_);
}

//
// Property<ObjectPath> specialization.
//

template <>
bool Property<ObjectPath>::PopValueFromReader(MessageReader* reader) {
  return reader->PopVariantOfObjectPath(&value_);
}

template <>
void Property<ObjectPath>::AppendSetValueToWriter(MessageWriter* writer) {
  writer->AppendVariantOfObjectPath(set_value_);
}

//
// Property<std::vector<std::string>> specialization.
//

template <>
bool Property<std::vector<std::string>>::PopValueFromReader(
    MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  if (!reader->PopVariant(&variant_reader))
    return false;

  value_.clear();
  return variant_reader.PopArrayOfStrings(&value_);
}

template <>
void Property<std::vector<std::string>>::AppendSetValueToWriter(
    MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  writer->OpenVariant("as", &variant_writer);
  variant_writer.AppendArrayOfStrings(set_value_);
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::vector<ObjectPath>> specialization.
//

template <>
bool Property<std::vector<ObjectPath>>::PopValueFromReader(
    MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  if (!reader->PopVariant(&variant_reader))
    return false;

  value_.clear();
  return variant_reader.PopArrayOfObjectPaths(&value_);
}

template <>
void Property<std::vector<ObjectPath>>::AppendSetValueToWriter(
    MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  writer->OpenVariant("ao", &variant_writer);
  variant_writer.AppendArrayOfObjectPaths(set_value_);
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::vector<uint8_t>> specialization.
//

template <>
bool Property<std::vector<uint8_t>>::PopValueFromReader(MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  if (!reader->PopVariant(&variant_reader))
    return false;

  value_.clear();
  const uint8_t* bytes = nullptr;
  size_t length = 0;
  if (!variant_reader.PopArrayOfBytes(&bytes, &length))
    return false;
  value_.assign(bytes, bytes + length);
  return true;
}

template <>
void Property<std::vector<uint8_t>>::AppendSetValueToWriter(
    MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  writer->OpenVariant("ay", &variant_writer);
  variant_writer.AppendArrayOfBytes(set_value_.data(), set_value_.size());
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::map<std::string, std::string>> specialization.
//

template <>
bool Property<std::map<std::string, std::string>>::PopValueFromReader(
    MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  MessageReader array_reader(nullptr);
  if (!reader->PopVariant(&variant_reader) ||
      !variant_reader.PopArray(&array_reader))
    return false;
  value_.clear();
  while (array_reader.HasMoreData()) {
    dbus::MessageReader dict_entry_reader(nullptr);
    if (!array_reader.PopDictEntry(&dict_entry_reader))
      return false;
    std::string key;
    std::string value;
    if (!dict_entry_reader.PopString(&key) ||
        !dict_entry_reader.PopString(&value))
      return false;
    value_[key] = value;
  }
  return true;
}

template <>
void Property<std::map<std::string, std::string>>::AppendSetValueToWriter(
    MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  MessageWriter dict_writer(nullptr);
  writer->OpenVariant("a{ss}", &variant_writer);
  variant_writer.OpenArray("{ss}", &dict_writer);
  for (const auto& pair : set_value_) {
    dbus::MessageWriter entry_writer(nullptr);
    dict_writer.OpenDictEntry(&entry_writer);
    entry_writer.AppendString(pair.first);
    entry_writer.AppendString(pair.second);
    dict_writer.CloseContainer(&entry_writer);
  }
  variant_writer.CloseContainer(&dict_writer);
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>
// specialization.
//

template <>
bool Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
    PopValueFromReader(MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  MessageReader array_reader(nullptr);
  if (!reader->PopVariant(&variant_reader) ||
      !variant_reader.PopArray(&array_reader))
    return false;

  value_.clear();
  while (array_reader.HasMoreData()) {
    dbus::MessageReader struct_reader(nullptr);
    if (!array_reader.PopStruct(&struct_reader))
      return false;

    std::pair<std::vector<uint8_t>, uint16_t> entry;
    const uint8_t* bytes = nullptr;
    size_t length = 0;
    if (!struct_reader.PopArrayOfBytes(&bytes, &length))
      return false;
    entry.first.assign(bytes, bytes + length);
    if (!struct_reader.PopUint16(&entry.second))
      return false;
    value_.push_back(entry);
  }
  return true;
}

template <>
void Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>::
    AppendSetValueToWriter(MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  MessageWriter array_writer(nullptr);
  writer->OpenVariant("a(ayq)", &variant_writer);
  variant_writer.OpenArray("(ayq)", &array_writer);
  for (const auto& pair : set_value_) {
    dbus::MessageWriter struct_writer(nullptr);
    array_writer.OpenStruct(&struct_writer);
    struct_writer.AppendArrayOfBytes(std::get<0>(pair).data(),
                                     std::get<0>(pair).size());
    struct_writer.AppendUint16(std::get<1>(pair));
    array_writer.CloseContainer(&struct_writer);
  }
  variant_writer.CloseContainer(&array_writer);
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::map<std::string, std::vector<uint8_t>>>
// specialization.
//

template <>
bool Property<std::map<std::string, std::vector<uint8_t>>>::PopValueFromReader(
    MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  MessageReader dict_reader(nullptr);
  if (!reader->PopVariant(&variant_reader) ||
      !variant_reader.PopArray(&dict_reader))
    return false;

  value_.clear();
  while (dict_reader.HasMoreData()) {
    MessageReader entry_reader(nullptr);
    if (!dict_reader.PopDictEntry(&entry_reader))
      return false;

    std::string key;
    if (!entry_reader.PopString(&key))
      return false;

    const uint8_t* bytes = nullptr;
    size_t length = 0;

    if (entry_reader.GetDataType() == Message::VARIANT) {
      // Make BlueZ happy since it wraps the array of bytes with a variant.
      MessageReader value_variant_reader(nullptr);
      if (!entry_reader.PopVariant(&value_variant_reader))
        return false;
      if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
        return false;
    } else {
      if (!entry_reader.PopArrayOfBytes(&bytes, &length))
        return false;
    }

    value_[key].assign(bytes, bytes + length);
  }
  return true;
}

template <>
void Property<std::map<std::string, std::vector<uint8_t>>>::
    AppendSetValueToWriter(MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  MessageWriter dict_writer(nullptr);

  writer->OpenVariant("a{sv}", &variant_writer);
  variant_writer.OpenArray("{sv}", &dict_writer);

  for (const auto& pair : set_value_) {
    MessageWriter entry_writer(nullptr);
    dict_writer.OpenDictEntry(&entry_writer);

    entry_writer.AppendString(pair.first);

    MessageWriter value_varient_writer(nullptr);
    entry_writer.OpenVariant("ay", &value_varient_writer);
    value_varient_writer.AppendArrayOfBytes(pair.second.data(),
                                            pair.second.size());
    entry_writer.CloseContainer(&value_varient_writer);

    dict_writer.CloseContainer(&entry_writer);
  }

  variant_writer.CloseContainer(&dict_writer);
  writer->CloseContainer(&variant_writer);
}

//
// Property<std::map<uint16_t, std::vector<uint8_t>>>
// specialization.
//

template <>
bool Property<std::map<uint16_t, std::vector<uint8_t>>>::PopValueFromReader(
    MessageReader* reader) {
  MessageReader variant_reader(nullptr);
  MessageReader dict_reader(nullptr);
  if (!reader->PopVariant(&variant_reader) ||
      !variant_reader.PopArray(&dict_reader))
    return false;

  value_.clear();
  while (dict_reader.HasMoreData()) {
    MessageReader entry_reader(nullptr);
    if (!dict_reader.PopDictEntry(&entry_reader))
      return false;

    uint16_t key;
    if (!entry_reader.PopUint16(&key))
      return false;

    const uint8_t* bytes = nullptr;
    size_t length = 0;

    if (entry_reader.GetDataType() == Message::VARIANT) {
      // Make BlueZ happy since it wraps the array of bytes with a variant.
      MessageReader value_variant_reader(nullptr);
      if (!entry_reader.PopVariant(&value_variant_reader))
        return false;
      if (!value_variant_reader.PopArrayOfBytes(&bytes, &length))
        return false;
    } else {
      if (!entry_reader.PopArrayOfBytes(&bytes, &length))
        return false;
    }

    value_[key].assign(bytes, bytes + length);
  }
  return true;
}

template <>
void Property<std::map<uint16_t, std::vector<uint8_t>>>::AppendSetValueToWriter(
    MessageWriter* writer) {
  MessageWriter variant_writer(nullptr);
  MessageWriter dict_writer(nullptr);

  writer->OpenVariant("a{qv}", &variant_writer);
  variant_writer.OpenArray("{qv}", &dict_writer);

  for (const auto& pair : set_value_) {
    MessageWriter entry_writer(nullptr);
    dict_writer.OpenDictEntry(&entry_writer);

    entry_writer.AppendUint16(pair.first);

    MessageWriter value_varient_writer(nullptr);
    entry_writer.OpenVariant("ay", &value_varient_writer);
    value_varient_writer.AppendArrayOfBytes(pair.second.data(),
                                            pair.second.size());
    entry_writer.CloseContainer(&value_varient_writer);

    dict_writer.CloseContainer(&entry_writer);
  }

  variant_writer.CloseContainer(&dict_writer);
  writer->CloseContainer(&variant_writer);
}

template class Property<uint8_t>;
template class Property<bool>;
template class Property<int16_t>;
template class Property<uint16_t>;
template class Property<int32_t>;
template class Property<uint32_t>;
template class Property<int64_t>;
template class Property<uint64_t>;
template class Property<double>;
template class Property<std::string>;
template class Property<ObjectPath>;
template class Property<std::vector<std::string>>;
template class Property<std::vector<ObjectPath>>;
template class Property<std::vector<uint8_t>>;
template class Property<std::map<std::string, std::string>>;
template class Property<std::vector<std::pair<std::vector<uint8_t>, uint16_t>>>;
template class Property<std::map<std::string, std::vector<uint8_t>>>;
template class Property<std::map<uint16_t, std::vector<uint8_t>>>;

}  // namespace dbus
