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

#include <string>

#include <base/bind.h>

#include "src/base_api_handler.h"
#include "src/commands/schema_constants.h"
#include "src/component_manager_impl.h"
#include "src/config.h"
#include "src/device_registration_info.h"
#include "src/privet/auth_manager.h"
#include "src/privet/privet_manager.h"
#include "src/string_utils.h"
#include "src/utils.h"

namespace weave {

DeviceManager::DeviceManager(provider::ConfigStore* config_store,
                             provider::TaskRunner* task_runner,
                             provider::HttpClient* http_client,
                             provider::Network* network,
                             provider::DnsServiceDiscovery* dns_sd,
                             provider::HttpServer* http_server,
                             provider::Wifi* wifi,
                             provider::Bluetooth* bluetooth)
    : config_{new Config{config_store}},
      component_manager_{new ComponentManagerImpl{task_runner}} {
  if (http_server) {
    auth_manager_.reset(new privet::AuthManager(
        config_.get(), http_server->GetHttpsCertificateFingerprint()));
  }

  device_info_.reset(new DeviceRegistrationInfo(
      config_.get(), component_manager_.get(), task_runner, http_client,
      network, auth_manager_.get()));
  base_api_handler_.reset(new BaseApiHandler{device_info_.get(), this});

  device_info_->Start();

  if (http_server) {
    StartPrivet(task_runner, network, dns_sd, http_server, wifi, bluetooth);
  } else {
    CHECK(!dns_sd);
  }
}

DeviceManager::~DeviceManager() {}

const Settings& DeviceManager::GetSettings() const {
  return device_info_->GetSettings();
}

void DeviceManager::AddSettingsChangedCallback(
    const SettingsChangedCallback& callback) {
  device_info_->GetMutableConfig()->AddOnChangedCallback(callback);
}

Config* DeviceManager::GetConfig() {
  return device_info_->GetMutableConfig();
}

void DeviceManager::StartPrivet(provider::TaskRunner* task_runner,
                                provider::Network* network,
                                provider::DnsServiceDiscovery* dns_sd,
                                provider::HttpServer* http_server,
                                provider::Wifi* wifi,
                                provider::Bluetooth* bluetooth) {
  privet_.reset(new privet::Manager{task_runner});
  privet_->Start(network, dns_sd, http_server, wifi, auth_manager_.get(),
                 device_info_.get(), component_manager_.get());
}

GcdState DeviceManager::GetGcdState() const {
  return device_info_->GetGcdState();
}

void DeviceManager::AddGcdStateChangedCallback(
    const GcdStateChangedCallback& callback) {
  device_info_->AddGcdStateChangedCallback(callback);
}

void DeviceManager::AddTraitDefinitionsFromJson(const std::string& json) {
  CHECK(component_manager_->LoadTraits(json, nullptr));
}

void DeviceManager::AddTraitDefinitions(const base::DictionaryValue& dict) {
  CHECK(component_manager_->LoadTraits(dict, nullptr));
}

const base::DictionaryValue& DeviceManager::GetTraits() const {
  return component_manager_->GetTraits();
}

void DeviceManager::AddTraitDefsChangedCallback(const base::Closure& callback) {
  component_manager_->AddTraitDefChangedCallback(callback);
}

bool DeviceManager::AddComponent(const std::string& name,
                                 const std::vector<std::string>& traits,
                                 ErrorPtr* error) {
  return component_manager_->AddComponent("", name, traits, error);
}

bool DeviceManager::RemoveComponent(const std::string& name, ErrorPtr* error) {
  return component_manager_->RemoveComponent("", name, error);
}

void DeviceManager::AddComponentTreeChangedCallback(
    const base::Closure& callback) {
  component_manager_->AddComponentTreeChangedCallback(callback);
}

const base::DictionaryValue& DeviceManager::GetComponents() const {
  return component_manager_->GetComponents();
}

bool DeviceManager::SetStatePropertiesFromJson(const std::string& component,
                                               const std::string& json,
                                               ErrorPtr* error) {
  return component_manager_->SetStatePropertiesFromJson(component, json, error);
}

bool DeviceManager::SetStateProperties(const std::string& component,
                                       const base::DictionaryValue& dict,
                                       ErrorPtr* error) {
  return component_manager_->SetStateProperties(component, dict, error);
}

const base::Value* DeviceManager::GetStateProperty(const std::string& component,
                                                   const std::string& name,
                                                   ErrorPtr* error) const {
  return component_manager_->GetStateProperty(component, name, error);
}

bool DeviceManager::SetStateProperty(const std::string& component,
                                     const std::string& name,
                                     const base::Value& value,
                                     ErrorPtr* error) {
  return component_manager_->SetStateProperty(component, name, value, error);
}

void DeviceManager::AddCommandHandler(const std::string& component,
                                      const std::string& command_name,
                                      const CommandHandlerCallback& callback) {
  component_manager_->AddCommandHandler(component, command_name, callback);
}

void DeviceManager::AddCommandDefinitionsFromJson(const std::string& json) {
  auto dict = LoadJsonDict(json, nullptr);
  CHECK(dict);
  AddCommandDefinitions(*dict);
}

void DeviceManager::AddCommandDefinitions(const base::DictionaryValue& dict) {
  CHECK(component_manager_->AddLegacyCommandDefinitions(dict, nullptr));
}

bool DeviceManager::AddCommand(const base::DictionaryValue& command,
                               std::string* id,
                               ErrorPtr* error) {
  auto command_instance = component_manager_->ParseCommandInstance(
      command, Command::Origin::kLocal, UserRole::kOwner, id, error);
  if (!command_instance)
    return false;
  component_manager_->AddCommand(std::move(command_instance));
  return true;
}

Command* DeviceManager::FindCommand(const std::string& id) {
  return component_manager_->FindCommand(id);
}

void DeviceManager::AddCommandHandler(const std::string& command_name,
                                      const CommandHandlerCallback& callback) {
  if (command_name.empty())
    return component_manager_->AddCommandHandler("", "", callback);

  auto trait = SplitAtFirst(command_name, ".", true).first;
  std::string component = component_manager_->FindComponentWithTrait(trait);
  CHECK(!component.empty());
  component_manager_->AddCommandHandler(component, command_name, callback);
}

void DeviceManager::AddStateChangedCallback(const base::Closure& callback) {
  component_manager_->AddStateChangedCallback(callback);
}

void DeviceManager::AddStateDefinitionsFromJson(const std::string& json) {
  auto dict = LoadJsonDict(json, nullptr);
  CHECK(dict);
  AddStateDefinitions(*dict);
}

void DeviceManager::AddStateDefinitions(const base::DictionaryValue& dict) {
  CHECK(component_manager_->AddLegacyStateDefinitions(dict, nullptr));
}

bool DeviceManager::SetStatePropertiesFromJson(const std::string& json,
                                               ErrorPtr* error) {
  auto dict = LoadJsonDict(json, error);
  return dict && SetStateProperties(*dict, error);
}

bool DeviceManager::SetStateProperties(const base::DictionaryValue& dict,
                                       ErrorPtr* error) {
  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    std::string component =
        component_manager_->FindComponentWithTrait(it.key());
    if (component.empty()) {
      Error::AddToPrintf(error, FROM_HERE, "unrouted_state",
                         "Unable to set property value because there is no "
                         "component supporting "
                         "trait '%s'",
                         it.key().c_str());
      return false;
    }
    base::DictionaryValue trait_state;
    trait_state.Set(it.key(), it.value().DeepCopy());
    if (!component_manager_->SetStateProperties(component, trait_state, error))
      return false;
  }
  return true;
}

const base::Value* DeviceManager::GetStateProperty(
    const std::string& name) const {
  auto trait = SplitAtFirst(name, ".", true).first;
  std::string component = component_manager_->FindComponentWithTrait(trait);
  if (component.empty())
    return nullptr;
  return component_manager_->GetStateProperty(component, name, nullptr);
}

bool DeviceManager::SetStateProperty(const std::string& name,
                                     const base::Value& value,
                                     ErrorPtr* error) {
  auto trait = SplitAtFirst(name, ".", true).first;
  std::string component = component_manager_->FindComponentWithTrait(trait);
  if (component.empty()) {
    Error::AddToPrintf(
        error, FROM_HERE, "unrouted_state",
        "Unable set value of state property '%s' because there is no component "
        "supporting trait '%s'",
        name.c_str(), trait.c_str());
    return false;
  }
  return component_manager_->SetStateProperty(component, name, value, error);
}

const base::DictionaryValue& DeviceManager::GetState() const {
  return component_manager_->GetLegacyState();
}

void DeviceManager::Register(const std::string& ticket_id,
                             const DoneCallback& callback) {
  device_info_->RegisterDevice(ticket_id, callback);
}

void DeviceManager::AddPairingChangedCallbacks(
    const PairingBeginCallback& begin_callback,
    const PairingEndCallback& end_callback) {
  if (privet_)
    privet_->AddOnPairingChangedCallbacks(begin_callback, end_callback);
}

std::unique_ptr<Device> Device::Create(provider::ConfigStore* config_store,
                                       provider::TaskRunner* task_runner,
                                       provider::HttpClient* http_client,
                                       provider::Network* network,
                                       provider::DnsServiceDiscovery* dns_sd,
                                       provider::HttpServer* http_server,
                                       provider::Wifi* wifi,
                                       provider::Bluetooth* bluetooth) {
  return std::unique_ptr<Device>{
      new DeviceManager{config_store, task_runner, http_client, network, dns_sd,
                        http_server, wifi, bluetooth}};
}

}  // namespace weave
