// Copyright 2015 The Weave 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 "src/privet/cloud_delegate.h"

#include <map>
#include <vector>

#include <base/bind.h>
#include <base/logging.h>
#include <base/memory/weak_ptr.h>
#include <base/values.h>
#include <weave/error.h>
#include <weave/provider/task_runner.h>

#include "src/backoff_entry.h"
#include "src/commands/command_manager.h"
#include "src/config.h"
#include "src/device_registration_info.h"
#include "src/privet/constants.h"
#include "src/states/state_manager.h"

namespace weave {
namespace privet {

namespace {

const BackoffEntry::Policy register_backoff_policy = {0,    1000, 2.0,  0.2,
                                                      5000, -1,   false};

const int kMaxDeviceRegistrationTimeMinutes = 5;

CommandInstance* ReturnNotFound(const std::string& command_id,
                                ErrorPtr* error) {
  Error::AddToPrintf(error, FROM_HERE, errors::kDomain, errors::kNotFound,
                     "Command not found, ID='%s'", command_id.c_str());
  return nullptr;
}

class CloudDelegateImpl : public CloudDelegate {
 public:
  CloudDelegateImpl(provider::TaskRunner* task_runner,
                    DeviceRegistrationInfo* device,
                    CommandManager* command_manager,
                    StateManager* state_manager)
      : task_runner_{task_runner},
        device_{device},
        command_manager_{command_manager},
        state_manager_{state_manager} {
    device_->GetMutableConfig()->AddOnChangedCallback(base::Bind(
        &CloudDelegateImpl::OnConfigChanged, weak_factory_.GetWeakPtr()));
    device_->AddGcdStateChangedCallback(base::Bind(
        &CloudDelegateImpl::OnRegistrationChanged, weak_factory_.GetWeakPtr()));

    command_manager_->AddCommandDefChanged(base::Bind(
        &CloudDelegateImpl::OnCommandDefChanged, weak_factory_.GetWeakPtr()));
    command_manager_->AddCommandAddedCallback(base::Bind(
        &CloudDelegateImpl::OnCommandAdded, weak_factory_.GetWeakPtr()));
    command_manager_->AddCommandRemovedCallback(base::Bind(
        &CloudDelegateImpl::OnCommandRemoved, weak_factory_.GetWeakPtr()));

    state_manager_->AddChangedCallback(base::Bind(
        &CloudDelegateImpl::OnStateChanged, weak_factory_.GetWeakPtr()));
  }

  ~CloudDelegateImpl() override = default;

  std::string GetDeviceId() const override {
    return device_->GetSettings().device_id;
  }

  std::string GetModelId() const override {
    CHECK_EQ(5u, device_->GetSettings().model_id.size());
    return device_->GetSettings().model_id;
  }

  std::string GetName() const override { return device_->GetSettings().name; }

  std::string GetDescription() const override {
    return device_->GetSettings().description;
  }

  std::string GetLocation() const override {
    return device_->GetSettings().location;
  }

  void UpdateDeviceInfo(const std::string& name,
                        const std::string& description,
                        const std::string& location) override {
    device_->UpdateDeviceInfo(name, description, location);
  }

  std::string GetOemName() const override {
    return device_->GetSettings().oem_name;
  }

  std::string GetModelName() const override {
    return device_->GetSettings().model_name;
  }

  AuthScope GetAnonymousMaxScope() const override {
    return device_->GetSettings().local_anonymous_access_role;
  }

  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,
             ErrorPtr* error) override {
    if (setup_state_.IsStatusEqual(SetupState::kInProgress)) {
      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();
    backoff_entry_.Reset();
    base::Time deadline = base::Time::Now();
    deadline += base::TimeDelta::FromMinutes(kMaxDeviceRegistrationTimeMinutes);
    task_runner_->PostDelayedTask(
        FROM_HERE,
        base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
                   setup_weak_factory_.GetWeakPtr(), ticket_id, deadline),
        {});
    // Return true because we initiated setup.
    return true;
  }

  std::string GetCloudId() const override {
    return connection_state_.status() > ConnectionState::kUnconfigured
               ? device_->GetSettings().cloud_id
               : "";
  }

  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 CommandDoneCallback& callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);
    CHECK_NE(user_info.user_id(), 0u);

    ErrorPtr error;
    UserRole role;
    std::string str_scope = EnumToString(user_info.scope());
    if (!StringToEnum(str_scope, &role)) {
      Error::AddToPrintf(&error, FROM_HERE, errors::kDomain,
                         errors::kInvalidParams, "Invalid role: '%s'",
                         str_scope.c_str());
      return callback.Run({}, std::move(error));
    }

    std::string id;
    if (!command_manager_->AddCommand(command, role, &id, &error))
      return callback.Run({}, std::move(error));

    command_owners_[id] = user_info.user_id();
    callback.Run(*command_manager_->FindCommand(id)->ToJson(), nullptr);
  }

  void GetCommand(const std::string& id,
                  const UserInfo& user_info,
                  const CommandDoneCallback& callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);
    ErrorPtr error;
    auto command = GetCommandInternal(id, user_info, &error);
    if (!command)
      return callback.Run({}, std::move(error));
    callback.Run(*command->ToJson(), nullptr);
  }

  void CancelCommand(const std::string& id,
                     const UserInfo& user_info,
                     const CommandDoneCallback& callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);
    ErrorPtr error;
    auto command = GetCommandInternal(id, user_info, &error);
    if (!command || !command->Cancel(&error))
      return callback.Run({}, std::move(error));
    callback.Run(*command->ToJson(), nullptr);
  }

  void ListCommands(const UserInfo& user_info,
                    const CommandDoneCallback& callback) override {
    CHECK(user_info.scope() != AuthScope::kNone);

    base::ListValue list_value;

    for (const auto& it : command_owners_) {
      if (CanAccessCommand(it.second, user_info, nullptr)) {
        list_value.Append(
            command_manager_->FindCommand(it.first)->ToJson().release());
      }
    }

    base::DictionaryValue commands_json;
    commands_json.Set("commands", list_value.DeepCopy());

    callback.Run(commands_json, nullptr);
  }

 private:
  void OnCommandAdded(Command* command) {
    // Set to 0 for any new unknown command.
    command_owners_.emplace(command->GetID(), 0);
  }

  void OnCommandRemoved(Command* command) {
    CHECK(command_owners_.erase(command->GetID()));
  }

  void OnConfigChanged(const Settings&) { NotifyOnDeviceInfoChanged(); }

  void OnRegistrationChanged(GcdState status) {
    if (status == GcdState::kUnconfigured ||
        status == GcdState::kInvalidCredentials) {
      connection_state_ = ConnectionState{ConnectionState::kUnconfigured};
    } else if (status == GcdState::kConnecting) {
      // TODO(vitalybuka): Find conditions for kOffline.
      connection_state_ = ConnectionState{ConnectionState::kConnecting};
    } else if (status == GcdState::kConnected) {
      connection_state_ = ConnectionState{ConnectionState::kOnline};
    } else {
      ErrorPtr error;
      Error::AddToPrintf(
          &error, FROM_HERE, errors::kDomain, errors::kInvalidState,
          "Unexpected registration status: %s", EnumToString(status).c_str());
      connection_state_ = ConnectionState{std::move(error)};
    }
    NotifyOnDeviceInfoChanged();
  }

  void OnStateChanged() {
    state_.Clear();
    auto state = state_manager_->GetState();
    CHECK(state);
    state_.MergeDictionary(state.get());
    NotifyOnStateChanged();
  }

  void OnCommandDefChanged() {
    command_defs_.Clear();
    auto commands = command_manager_->GetCommandDictionary().GetCommandsAsJson(
        [](const CommandDefinition* def) { return def->GetVisibility().local; },
        true, nullptr);
    CHECK(commands);
    command_defs_.MergeDictionary(commands.get());
    NotifyOnCommandDefsChanged();
  }

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

  void CallManagerRegisterDevice(const std::string& ticket_id,
                                 const base::Time& deadline) {
    ErrorPtr error;
    if (base::Time::Now() > deadline) {
      Error::AddTo(&error, FROM_HERE, errors::kDomain, errors::kInvalidState,
                   "Failed to register device");
      setup_state_ = SetupState{std::move(error)};
      return;
    }

    device_->RegisterDevice(
        ticket_id,
        base::Bind(&CloudDelegateImpl::RegisterDeviceDone,
                   setup_weak_factory_.GetWeakPtr(), ticket_id, deadline));
  }

  void RegisterDeviceDone(const std::string& ticket_id,
                          const base::Time& deadline,
                          ErrorPtr error) {
    if (error) {
      // Registration failed. Retry with backoff.
      backoff_entry_.InformOfRequest(false);
      return task_runner_->PostDelayedTask(
          FROM_HERE,
          base::Bind(&CloudDelegateImpl::CallManagerRegisterDevice,
                     setup_weak_factory_.GetWeakPtr(), ticket_id, deadline),
          backoff_entry_.GetTimeUntilRelease());
    }
    backoff_entry_.InformOfRequest(true);
    setup_state_ = SetupState(SetupState::kSuccess);
  }

  CommandInstance* GetCommandInternal(const std::string& command_id,
                                      const UserInfo& user_info,
                                      ErrorPtr* error) const {
    if (user_info.scope() != AuthScope::kOwner) {
      auto it = command_owners_.find(command_id);
      if (it == command_owners_.end())
        return ReturnNotFound(command_id, error);
      if (CanAccessCommand(it->second, user_info, error))
        return nullptr;
    }

    auto command = command_manager_->FindCommand(command_id);
    if (!command)
      return ReturnNotFound(command_id, error);

    return command;
  }

  bool CanAccessCommand(uint64_t owner_id,
                        const UserInfo& user_info,
                        ErrorPtr* error) const {
    CHECK(user_info.scope() != AuthScope::kNone);
    CHECK_NE(user_info.user_id(), 0u);

    if (user_info.scope() == AuthScope::kOwner ||
        owner_id == user_info.user_id()) {
      return true;
    }

    Error::AddTo(error, FROM_HERE, errors::kDomain, errors::kAccessDenied,
                 "Need to be owner of the command.");
    return false;
  }

  provider::TaskRunner* task_runner_{nullptr};
  DeviceRegistrationInfo* device_{nullptr};
  CommandManager* command_manager_{nullptr};
  StateManager* state_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_;

  // Backoff entry for retrying device registration.
  BackoffEntry backoff_entry_{&register_backoff_policy};

  // |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(
    provider::TaskRunner* task_runner,
    DeviceRegistrationInfo* device,
    CommandManager* command_manager,
    StateManager* state_manager) {
  return std::unique_ptr<CloudDelegateImpl>{new CloudDelegateImpl{
      task_runner, device, command_manager, state_manager}};
}

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 privet
}  // namespace weave
