// 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 "chromeos/dbus/modem_messaging_client.h"

#include <map>
#include <memory>
#include <utility>

#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/values.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_proxy.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

// A class which makes method calls for SMS services via the
// org.freedesktop.ModemManager1.Messaging object.
class ModemMessagingProxy {
 public:
  typedef ModemMessagingClient::SmsReceivedHandler SmsReceivedHandler;
  typedef ModemMessagingClient::ListCallback ListCallback;
  typedef ModemMessagingClient::DeleteCallback DeleteCallback;

  ModemMessagingProxy(dbus::Bus* bus,
           const std::string& service_name,
           const dbus::ObjectPath& object_path)
      : proxy_(bus->GetObjectProxy(service_name, object_path)),
        service_name_(service_name),
        weak_ptr_factory_(this) {
    proxy_->ConnectToSignal(
        modemmanager::kModemManager1MessagingInterface,
        modemmanager::kSMSAddedSignal,
        base::Bind(&ModemMessagingProxy::OnSmsAdded,
                   weak_ptr_factory_.GetWeakPtr()),
        base::Bind(&ModemMessagingProxy::OnSignalConnected,
                   weak_ptr_factory_.GetWeakPtr()));
  }
  virtual ~ModemMessagingProxy() {}

  // Sets SmsReceived signal handler.
  void SetSmsReceivedHandler(const SmsReceivedHandler& handler) {
    DCHECK(sms_received_handler_.is_null());
    sms_received_handler_ = handler;
  }

  // Resets SmsReceived signal handler.
  void ResetSmsReceivedHandler() {
    sms_received_handler_.Reset();
  }

  // Calls Delete method.
  void Delete(const dbus::ObjectPath& message_path,
              const DeleteCallback& callback) {
    dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface,
                                 modemmanager::kSMSDeleteFunction);
    dbus::MessageWriter writer(&method_call);
    writer.AppendObjectPath(message_path);
    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
                       base::Bind(&ModemMessagingProxy::OnDelete,
                                  weak_ptr_factory_.GetWeakPtr(),
                                  callback));
  }

  // Calls List method.
  virtual void List(const ListCallback& callback) {
    dbus::MethodCall method_call(modemmanager::kModemManager1MessagingInterface,
                                 modemmanager::kSMSListFunction);
    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
                       base::Bind(&ModemMessagingProxy::OnList,
                                  weak_ptr_factory_.GetWeakPtr(),
                                  callback));
  }

 private:
  // Handles SmsAdded signal.
  void OnSmsAdded(dbus::Signal* signal) {
    dbus::ObjectPath message_path;
    bool complete = false;
    dbus::MessageReader reader(signal);
    if (!reader.PopObjectPath(&message_path) ||
        !reader.PopBool(&complete)) {
      LOG(ERROR) << "Invalid signal: " << signal->ToString();
      return;
    }
    if (!sms_received_handler_.is_null()) {
      sms_received_handler_.Run(message_path, complete);
    }
  }

  // Handles responses of Delete method calls.
  void OnDelete(const DeleteCallback& callback, dbus::Response* response) {
    if (!response)
      return;
    callback.Run();
  }

  // Handles responses of List method calls.
  void OnList(const ListCallback& callback, dbus::Response* response) {
    if (!response)
      return;
    dbus::MessageReader reader(response);
    std::vector<dbus::ObjectPath> sms_paths;
    if (!reader.PopArrayOfObjectPaths(&sms_paths))
      LOG(WARNING) << "Invalid response: " << response->ToString();
    callback.Run(sms_paths);
  }

  // Handles the result of signal connection setup.
  void OnSignalConnected(const std::string& interface,
                         const std::string& signal,
                         bool succeeded) {
    LOG_IF(ERROR, !succeeded) << "Connect to " << interface << " "
                              << signal << " failed.";
  }

  dbus::ObjectProxy* proxy_;
  std::string service_name_;
  SmsReceivedHandler sms_received_handler_;

  // Note: This should remain the last member so it'll be destroyed and
  // invalidate its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<ModemMessagingProxy> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(ModemMessagingProxy);
};

class CHROMEOS_EXPORT ModemMessagingClientImpl : public ModemMessagingClient {
 public:
  ModemMessagingClientImpl() : bus_(NULL) {}

  void SetSmsReceivedHandler(const std::string& service_name,
                             const dbus::ObjectPath& object_path,
                             const SmsReceivedHandler& handler) override {
    GetProxy(service_name, object_path)->SetSmsReceivedHandler(handler);
  }

  void ResetSmsReceivedHandler(const std::string& service_name,
                               const dbus::ObjectPath& object_path) override {
    GetProxy(service_name, object_path)->ResetSmsReceivedHandler();
  }

  void Delete(const std::string& service_name,
              const dbus::ObjectPath& object_path,
              const dbus::ObjectPath& sms_path,
              const DeleteCallback& callback) override {
    GetProxy(service_name, object_path)->Delete(sms_path, callback);
  }

  void List(const std::string& service_name,
            const dbus::ObjectPath& object_path,
            const ListCallback& callback) override {
    GetProxy(service_name, object_path)->List(callback);
  }

 protected:
  void Init(dbus::Bus* bus) override { bus_ = bus; };

 private:
  using ProxyMap = std::map<std::pair<std::string, std::string>,
                            std::unique_ptr<ModemMessagingProxy>>;

  // Returns a SMSProxy for the given service name and object path.
  ModemMessagingProxy* GetProxy(const std::string& service_name,
                                const dbus::ObjectPath& object_path) {
    const ProxyMap::key_type key(service_name, object_path.value());
    ProxyMap::const_iterator it = proxies_.find(key);
    if (it != proxies_.end())
      return it->second.get();

    // There is no proxy for the service_name and object_path, create it.
    std::unique_ptr<ModemMessagingProxy> proxy(
        new ModemMessagingProxy(bus_, service_name, object_path));
    ModemMessagingProxy* proxy_ptr = proxy.get();
    proxies_[key] = std::move(proxy);
    return proxy_ptr;
  }

  dbus::Bus* bus_;
  ProxyMap proxies_;

  DISALLOW_COPY_AND_ASSIGN(ModemMessagingClientImpl);
};

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// ModemMessagingClient

ModemMessagingClient::ModemMessagingClient() {}

ModemMessagingClient::~ModemMessagingClient() {}


// static
ModemMessagingClient* ModemMessagingClient::Create() {
  return new ModemMessagingClientImpl();
}


}  // namespace chromeos
