// 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/access_api_handler.h"
#include "src/access_black_list_manager_impl.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});

  black_list_manager_.reset(new AccessBlackListManagerImpl{config_store});
  access_api_handler_.reset(
      new AccessApiHandler{this, black_list_manager_.get()});

  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 RegistrationData& registration_data,
                             const DoneCallback& callback) {
  device_info_->RegisterDevice(registration_data, 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
