// 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 "buffet/privet/cloud_delegate.h"

#include <map>
#include <vector>

#include <base/bind.h>
#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/logging.h>
#include <base/memory/weak_ptr.h>
#include <base/message_loop/message_loop.h>
#include <base/values.h>
#include <chromeos/errors/error.h>
#include <chromeos/variant_dictionary.h>
#include <dbus/bus.h>

#include "buffet/dbus-proxies.h"
#include "buffet/privet/constants.h"

namespace privetd {

namespace {

using chromeos::ErrorPtr;
using chromeos::VariantDictionary;
using org::chromium::Buffet::ManagerProxy;
using org::chromium::Buffet::ObjectManagerProxy;

const int kMaxSetupRetries = 5;
const int kFirstRetryTimeoutSec = 1;

class CloudDelegateImpl : public CloudDelegate {
 public:
  CloudDelegateImpl(const scoped_refptr<dbus::Bus>& bus,
                    bool is_gcd_setup_enabled)
      : object_manager_{bus}, is_gcd_setup_enabled_(is_gcd_setup_enabled) {
    object_manager_.SetManagerAddedCallback(base::Bind(
        &CloudDelegateImpl::OnManagerAdded, weak_factory_.GetWeakPtr()));
    object_manager_.SetManagerRemovedCallback(base::Bind(
        &CloudDelegateImpl::OnManagerRemoved, weak_factory_.GetWeakPtr()));
    object_manager_.SetCommandRemovedCallback(base::Bind(
        &CloudDelegateImpl::OnCommandRemoved, weak_factory_.GetWeakPtr()));
  }

  ~CloudDelegateImpl() override = default;

  bool GetModelId(std::string* id, chromeos::ErrorPtr* error) const override {
    if (!IsManagerReady(error))
      return false;
    if (manager_->model_id().size() != 5) {
      chromeos::Error::AddToPrintf(
          error, FROM_HERE, errors::kDomain, errors::kInvalidState,
          "Model ID is invalid: %s", manager_->model_id().c_str());
      return false;
    }
    *id = manager_->model_id();
    return true;
  }

  bool GetName(std::string* name, chromeos::ErrorPtr* error) const override {
    if (!IsManagerReady(error))
      return false;
    *name = manager_->name();
    return true;
  }

  std::string GetDescription() const override {
    return manager_ ? manager_->description() : std::string{};
  }

  std::string GetLocation() const override {
    return manager_ ? manager_->location() : std::string{};
  }

  void UpdateDeviceInfo(const std::string& name,
                        const std::string& description,
                        const std::string& location,
                        const base::Closure& success_callback,
                        const ErrorCallback& error_callback) override {
    chromeos::ErrorPtr error;
    if (!IsManagerReady(&error))
      return error_callback.Run(error.get());

    if (name == manager_->name() && description == manager_->description() &&
        location == manager_->location()) {
      return success_callback.Run();
    }

    manager_->UpdateDeviceInfoAsync(name, description, location,
                                    success_callback, error_callback);
  }

  std::string GetOemName() const override {
    return manager_ ? manager_->oem_name() : std::string{};
  }

  std::string GetModelName() const override {
    return manager_ ? manager_->model_name() : std::string{};
  }

  std::set<std::string> GetServices() const override {
    std::set<std::string> result;
    for (base::DictionaryValue::Iterator it{command_defs_}; !it.IsAtEnd();
         it.Advance()) {
      result.emplace(it.key());
    }
    return result;
  }

  AuthScope GetAnonymousMaxScope() const override {
    if (manager_) {
      AuthScope scope;
      if (StringToAuthScope(manager_->anonymous_access_role(), &scope))
        return scope;
    }
    return AuthScope::kNone;
  }

  const ConnectionState& GetConnectionState() const override {
    return connection_state_;
  }

  const SetupState& GetSetupState() const override { return setup_state_; }

  bool Setup(const std::string& ticket_id,
             const std::string& user,
             chromeos::ErrorPtr* error) override {
    if (!is_gcd_setup_enabled_) {
      chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
                             errors::kSetupUnavailable,
                             "GCD setup unavailible");
      return false;
    }
    if (!object_manager_.GetManagerProxy()) {
      chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
                             errors::kDeviceBusy, "Buffet is not ready");
      return false;
    }
    if (setup_state_.IsStatusEqual(SetupState::kInProgress)) {
      chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
                             errors::kDeviceBusy, "Setup in progress");
      return false;
    }
    VLOG(1) << "GCD Setup started. ticket_id: " << ticket_id
            << ", user:" << user;
    setup_state_ = SetupState(SetupState::kInProgress);
    setup_weak_factory_.InvalidateWeakPtrs();
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE, base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
                              setup_weak_factory_.GetWeakPtr(), ticket_id, 0),
        base::TimeDelta::FromSeconds(kSetupDelaySeconds));
    // Return true because we tried setup.
    return true;
  }

  std::string GetCloudId() const override {
    return manager_ ? manager_->device_id() : std::string{};
  }

  const base::DictionaryValue& GetState() const override { return state_; }

  const base::DictionaryValue& GetCommandDef() const override {
    return command_defs_;
  }

  void AddCommand(const base::DictionaryValue& command,
                  const UserInfo& user_info,
                  const SuccessCallback& success_callback,
                  const ErrorCallback& error_callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);

    chromeos::ErrorPtr error;
    if (!IsManagerReady(&error))
      return error_callback.Run(error.get());

    std::string command_str;
    base::JSONWriter::Write(&command, &command_str);
    manager_->AddCommandAsync(
        command_str, AuthScopeToString(user_info.scope()),
        base::Bind(&CloudDelegateImpl::OnAddCommandSucceeded,
                   weak_factory_.GetWeakPtr(), success_callback,
                   error_callback),
        error_callback);
  }

  void GetCommand(const std::string& id,
                  const UserInfo& user_info,
                  const SuccessCallback& success_callback,
                  const ErrorCallback& error_callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);
    chromeos::ErrorPtr error;
    if (!CanAccessCommand(id, user_info)) {
      chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
                             errors::kAccessDenied,
                             "Need to be owner of the command.");
      return error_callback.Run(error.get());
    }

    GetCommandInternal(id, success_callback, error_callback);
  }

  void CancelCommand(const std::string& id,
                     const UserInfo& user_info,
                     const SuccessCallback& success_callback,
                     const ErrorCallback& error_callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);
    chromeos::ErrorPtr error;
    if (!CanAccessCommand(id, user_info)) {
      chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
                             errors::kAccessDenied,
                             "Need to be owner of the command.");
      return error_callback.Run(error.get());
    }

    for (auto command : object_manager_.GetCommandInstances()) {
      if (command->id() == id) {
        return command->CancelAsync(
            base::Bind(&CloudDelegateImpl::GetCommandInternal,
                       weak_factory_.GetWeakPtr(), id, success_callback,
                       error_callback),
            error_callback);
      }
    }

    chromeos::Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
                                 errors::kNotFound,
                                 "Command not found, ID='%s'", id.c_str());
    error_callback.Run(error.get());
  }

  void ListCommands(const UserInfo& user_info,
                    const SuccessCallback& success_callback,
                    const ErrorCallback& error_callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);

    std::vector<org::chromium::Buffet::CommandProxy*> commands{
        object_manager_.GetCommandInstances()};

    auto ids = std::make_shared<std::vector<std::string>>();
    for (auto command : commands) {
      if (CanAccessCommand(command->id(), user_info))
        ids->push_back(command->id());
    }

    GetNextCommand(ids, std::make_shared<base::ListValue>(), success_callback,
                   error_callback, base::DictionaryValue{});
  }

 private:
  void GetCommandInternal(const std::string& id,
                          const SuccessCallback& success_callback,
                          const ErrorCallback& error_callback) {
    chromeos::ErrorPtr error;
    if (!IsManagerReady(&error))
      return error_callback.Run(error.get());
    manager_->GetCommandAsync(
        id, base::Bind(&CloudDelegateImpl::OnGetCommandSucceeded,
                       weak_factory_.GetWeakPtr(), success_callback,
                       error_callback),
        error_callback);
  }

  void OnManagerAdded(ManagerProxy* manager) {
    manager_ = manager;
    manager_->SetPropertyChangedCallback(
        base::Bind(&CloudDelegateImpl::OnManagerPropertyChanged,
                   weak_factory_.GetWeakPtr()));
    // Read all initial values.
    OnManagerPropertyChanged(manager, std::string{});
  }

  void OnCommandRemoved(const dbus::ObjectPath& object_path) {
    command_owners_.erase(object_manager_.GetCommandProxy(object_path)->id());
  }

  void OnManagerPropertyChanged(ManagerProxy* manager,
                                const std::string& property_name) {
    CHECK_EQ(manager_, manager);

    if (property_name.empty() || property_name == ManagerProxy::StatusName()) {
      OnStatusPropertyChanged();
    }

    if (property_name.empty() ||
        property_name == ManagerProxy::DeviceIdName() ||
        property_name == ManagerProxy::OemNameName() ||
        property_name == ManagerProxy::ModelNameName() ||
        property_name == ManagerProxy::ModelIdName() ||
        property_name == ManagerProxy::NameName() ||
        property_name == ManagerProxy::DescriptionName() ||
        property_name == ManagerProxy::LocationName() ||
        property_name == ManagerProxy::AnonymousAccessRoleName()) {
      NotifyOnDeviceInfoChanged();
    }

    if (property_name.empty() || property_name == ManagerProxy::StateName()) {
      OnStatePropertyChanged();
    }

    if (property_name.empty() ||
        property_name == ManagerProxy::CommandDefsName()) {
      OnCommandDefsPropertyChanged();
    }
  }

  void OnStatusPropertyChanged() {
    const std::string& status = manager_->status();
    if (status == "unconfigured") {
      connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
    } else if (status == "connecting") {
      // TODO(vitalybuka): Find conditions for kOffline.
      connection_state_ = ConnectionState{ConnectionState::kConnecting};
    } else if (status == "connected") {
      connection_state_ = ConnectionState{ConnectionState::kOnline};
    } else {
      chromeos::ErrorPtr error;
      chromeos::Error::AddToPrintf(
          &error, FROM_HERE, errors::kDomain, errors::kInvalidState,
          "Unexpected buffet status: %s", status.c_str());
      connection_state_ = ConnectionState{std::move(error)};
    }
    NotifyOnDeviceInfoChanged();
  }

  void OnStatePropertyChanged() {
    state_.Clear();
    std::unique_ptr<base::Value> value{
        base::JSONReader::Read(manager_->state())};
    const base::DictionaryValue* state{nullptr};
    if (value && value->GetAsDictionary(&state))
      state_.MergeDictionary(state);
    NotifyOnStateChanged();
  }

  void OnCommandDefsPropertyChanged() {
    command_defs_.Clear();
    std::unique_ptr<base::Value> value{
        base::JSONReader::Read(manager_->command_defs())};
    const base::DictionaryValue* defs{nullptr};
    if (value && value->GetAsDictionary(&defs))
      command_defs_.MergeDictionary(defs);
    NotifyOnCommandDefsChanged();
  }

  void OnManagerRemoved(const dbus::ObjectPath& path) {
    manager_ = nullptr;
    connection_state_ = ConnectionState(ConnectionState::kDisabled);
    state_.Clear();
    command_defs_.Clear();
    command_owners_.clear();
    NotifyOnDeviceInfoChanged();
    NotifyOnCommandDefsChanged();
    NotifyOnStateChanged();
  }

  void RetryRegister(const std::string& ticket_id,
                     int retries,
                     chromeos::Error* error) {
    if (retries >= kMaxSetupRetries) {
      chromeos::ErrorPtr new_error{error ? error->Clone() : nullptr};
      chromeos::Error::AddTo(&new_error, FROM_HERE, errors::kDomain,
                             errors::kInvalidState,
                             "Failed to register device");
      setup_state_ = SetupState{std::move(new_error)};
      return;
    }
    base::MessageLoop::current()->PostDelayedTask(
        FROM_HERE,
        base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
                   setup_weak_factory_.GetWeakPtr(), ticket_id, retries + 1),
        base::TimeDelta::FromSeconds(kFirstRetryTimeoutSec << retries));
  }

  void OnRegisterSuccess(const std::string& device_id) {
    VLOG(1) << "Device registered: " << device_id;
    setup_state_ = SetupState(SetupState::kSuccess);
  }

  void CallManagerRegisterDevice(const std::string& ticket_id, int retries) {
    auto manager_proxy = object_manager_.GetManagerProxy();
    if (!manager_proxy) {
      LOG(ERROR) << "Couldn't register because Buffet was offline.";
      RetryRegister(ticket_id, retries, nullptr);
      return;
    }
    manager_proxy->RegisterDeviceAsync(
        ticket_id, base::Bind(&CloudDelegateImpl::OnRegisterSuccess,
                              setup_weak_factory_.GetWeakPtr()),
        base::Bind(&CloudDelegateImpl::RetryRegister,
                   setup_weak_factory_.GetWeakPtr(), ticket_id, retries));
  }

  void OnAddCommandSucceeded(const SuccessCallback& success_callback,
                             const ErrorCallback& error_callback,
                             const std::string& id) {
    GetCommandInternal(id, success_callback, error_callback);
  }

  void OnGetCommandSucceeded(const SuccessCallback& success_callback,
                             const ErrorCallback& error_callback,
                             const std::string& json_command) {
    std::unique_ptr<base::Value> value{base::JSONReader::Read(json_command)};
    base::DictionaryValue* command{nullptr};
    if (!value || !value->GetAsDictionary(&command)) {
      chromeos::ErrorPtr error;
      chromeos::Error::AddTo(&error, FROM_HERE, errors::kDomain,
                             errors::kInvalidFormat,
                             "Buffet returned invalid JSON");
      return error_callback.Run(error.get());
    }
    success_callback.Run(*command);
  }

  void GetNextCommandSkipError(
      const std::shared_ptr<std::vector<std::string>>& ids,
      const std::shared_ptr<base::ListValue>& commands,
      const SuccessCallback& success_callback,
      const ErrorCallback& error_callback,
      chromeos::Error*) {
    // Ignore if we can't get some commands. Maybe they were removed.
    GetNextCommand(ids, commands, success_callback, error_callback,
                   base::DictionaryValue{});
  }

  void GetNextCommand(const std::shared_ptr<std::vector<std::string>>& ids,
                      const std::shared_ptr<base::ListValue>& commands,
                      const SuccessCallback& success_callback,
                      const ErrorCallback& error_callback,
                      const base::DictionaryValue& json) {
    if (!json.empty())
      commands->Append(json.DeepCopy());

    if (ids->empty()) {
      base::DictionaryValue commands_json;
      commands_json.Set("commands", commands->DeepCopy());
      return success_callback.Run(commands_json);
    }

    std::string next_id = ids->back();
    ids->pop_back();

    auto on_success = base::Bind(&CloudDelegateImpl::GetNextCommand,
                                 weak_factory_.GetWeakPtr(), ids, commands,
                                 success_callback, error_callback);

    auto on_error = base::Bind(&CloudDelegateImpl::GetNextCommandSkipError,
                               weak_factory_.GetWeakPtr(), ids, commands,
                               success_callback, error_callback);

    GetCommandInternal(next_id, on_success, on_error);
  }

  bool IsManagerReady(chromeos::ErrorPtr* error) const {
    if (!manager_) {
      chromeos::Error::AddTo(error, FROM_HERE, errors::kDomain,
                             errors::kDeviceBusy, "Buffet is not ready");
      return false;
    }
    return true;
  }

  bool CanAccessCommand(const std::string& command_id,
                        const UserInfo& user_info) const {
    if (user_info.scope() == AuthScope::kOwner)
      return true;
    auto it = command_owners_.find(command_id);
    return it != command_owners_.end() && it->second == user_info.user_id();
  }

  ObjectManagerProxy object_manager_;

  bool is_gcd_setup_enabled_{false};

  ManagerProxy* manager_{nullptr};

  // Primary state of GCD.
  ConnectionState connection_state_{ConnectionState::kDisabled};

  // State of the current or last setup.
  SetupState setup_state_{SetupState::kNone};

  // Current device state.
  base::DictionaryValue state_;

  // Current commands definitions.
  base::DictionaryValue command_defs_;

  // Map of command IDs to user IDs.
  std::map<std::string, uint64_t> command_owners_;

  // |setup_weak_factory_| tracks the lifetime of callbacks used in connection
  // with a particular invocation of Setup().
  base::WeakPtrFactory<CloudDelegateImpl> setup_weak_factory_{this};
  // |weak_factory_| tracks the lifetime of |this|.
  base::WeakPtrFactory<CloudDelegateImpl> weak_factory_{this};
};

}  // namespace

CloudDelegate::CloudDelegate() {
}

CloudDelegate::~CloudDelegate() {
}

// static
std::unique_ptr<CloudDelegate> CloudDelegate::CreateDefault(
    const scoped_refptr<dbus::Bus>& bus,
    bool is_gcd_setup_enabled) {
  return std::unique_ptr<CloudDelegateImpl>{
      new CloudDelegateImpl{bus, is_gcd_setup_enabled}};
}

void CloudDelegate::NotifyOnDeviceInfoChanged() {
  FOR_EACH_OBSERVER(Observer, observer_list_, OnDeviceInfoChanged());
}

void CloudDelegate::NotifyOnCommandDefsChanged() {
  FOR_EACH_OBSERVER(Observer, observer_list_, OnCommandDefsChanged());
}

void CloudDelegate::NotifyOnStateChanged() {
  FOR_EACH_OBSERVER(Observer, observer_list_, OnStateChanged());
}

}  // namespace privetd
