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

#include <base/logging.h>
#include <base/values.h>

#include "src/json_error_codes.h"
#include "src/states/error_codes.h"
#include "src/states/state_change_queue_interface.h"
#include "src/string_utils.h"
#include "src/utils.h"

namespace weave {

namespace {

const char kBaseStateDefs[] = R"({
  "base": {
    "firmwareVersion": "string",
    "localDiscoveryEnabled": "boolean",
    "localAnonymousAccessMaxRole": [ "none", "viewer", "user" ],
    "localPairingEnabled": "boolean",
    "network": {
      "properties": {
        "name": "string"
      }
    }
  }
})";

const char kBaseStateDefaults[] = R"({
  "base": {
    "firmwareVersion": "unknown",
    "localDiscoveryEnabled": false,
    "localAnonymousAccessMaxRole": "none",
    "localPairingEnabled": false
  }
})";
}

StateManager::StateManager(StateChangeQueueInterface* state_change_queue)
    : state_change_queue_(state_change_queue) {
  CHECK(state_change_queue_) << "State change queue not specified";
}

StateManager::~StateManager() {}

void StateManager::AddChangedCallback(const base::Closure& callback) {
  on_changed_.push_back(callback);
  callback.Run();  // Force to read current state.
}

void StateManager::Startup() {
  LOG(INFO) << "Initializing StateManager.";

  // Load standard device state definition.
  CHECK(LoadBaseStateDefinition(kBaseStateDefs, nullptr));

  // Load standard device state defaults.
  CHECK(SetPropertiesFromJson(kBaseStateDefaults, nullptr));

  for (const auto& cb : on_changed_)
    cb.Run();
}

std::unique_ptr<base::DictionaryValue> StateManager::GetState() const {
  std::unique_ptr<base::DictionaryValue> dict{new base::DictionaryValue};
  for (const auto& pair : packages_) {
    auto pkg_value = pair.second->GetValuesAsJson();
    CHECK(pkg_value);
    dict->SetWithoutPathExpansion(pair.first, pkg_value.release());
  }
  return dict;
}

bool StateManager::SetProperty(const std::string& name,
                               const base::Value& value,
                               ErrorPtr* error) {
  bool result = SetPropertyValue(name, value, base::Time::Now(), error);
  for (const auto& cb : on_changed_)
    cb.Run();
  return result;
}

std::unique_ptr<base::Value> StateManager::GetProperty(
    const std::string& name) const {
  auto parts = SplitAtFirst(name, ".", true);
  const std::string& package_name = parts.first;
  const std::string& property_name = parts.second;
  if (package_name.empty() || property_name.empty())
    return nullptr;

  const StatePackage* package = FindPackage(package_name);
  if (!package)
    return nullptr;

  return package->GetPropertyValue(property_name, nullptr);
}

bool StateManager::SetPropertyValue(const std::string& full_property_name,
                                    const base::Value& value,
                                    const base::Time& timestamp,
                                    ErrorPtr* error) {
  auto parts = SplitAtFirst(full_property_name, ".", true);
  const std::string& package_name = parts.first;
  const std::string& property_name = parts.second;
  const bool split = (full_property_name.find(".") != std::string::npos);

  if (full_property_name.empty() || (split && property_name.empty())) {
    Error::AddTo(error, FROM_HERE, errors::state::kDomain,
                 errors::state::kPropertyNameMissing,
                 "Property name is missing");
    return false;
  }
  if (!split || package_name.empty()) {
    Error::AddTo(error, FROM_HERE, errors::state::kDomain,
                 errors::state::kPackageNameMissing,
                 "Package name is missing in the property name");
    return false;
  }
  StatePackage* package = FindPackage(package_name);
  if (package == nullptr) {
    Error::AddToPrintf(error, FROM_HERE, errors::state::kDomain,
                       errors::state::kPropertyNotDefined,
                       "Unknown state property package '%s'",
                       package_name.c_str());
    return false;
  }
  if (!package->SetPropertyValue(property_name, value, error))
    return false;

  ValueMap prop_set{{full_property_name, package->GetProperty(property_name)}};
  state_change_queue_->NotifyPropertiesUpdated(timestamp, prop_set);
  return true;
}

std::pair<StateChangeQueueInterface::UpdateID, std::vector<StateChange>>
StateManager::GetAndClearRecordedStateChanges() {
  return std::make_pair(state_change_queue_->GetLastStateChangeId(),
                        state_change_queue_->GetAndClearRecordedStateChanges());
}

void StateManager::NotifyStateUpdatedOnServer(
    StateChangeQueueInterface::UpdateID id) {
  state_change_queue_->NotifyStateUpdatedOnServer(id);
}

bool StateManager::LoadStateDefinition(const base::DictionaryValue& dict,
                                       ErrorPtr* error) {
  for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
       iter.Advance()) {
    std::string package_name = iter.key();
    if (package_name.empty()) {
      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
                   errors::kInvalidPackageError, "State package name is empty");
      return false;
    }
    const base::DictionaryValue* package_dict = nullptr;
    if (!iter.value().GetAsDictionary(&package_dict)) {
      Error::AddToPrintf(error, FROM_HERE, errors::json::kDomain,
                         errors::json::kObjectExpected,
                         "State package '%s' must be an object",
                         package_name.c_str());
      return false;
    }
    StatePackage* package = FindOrCreatePackage(package_name);
    CHECK(package) << "Unable to create state package " << package_name;
    if (!package->AddSchemaFromJson(package_dict, error))
      return false;
  }

  return true;
}

bool StateManager::LoadStateDefinitionFromJson(const std::string& json,
                                               ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  if (!dict)
    return false;
  if (!LoadStateDefinition(*dict, error)) {
    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
                       errors::kSchemaError,
                       "Failed to load state definition: '%s'", json.c_str());
    return false;
  }
  return true;
}

bool StateManager::LoadBaseStateDefinition(const std::string& json,
                                           ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  if (!dict)
    return false;
  if (!LoadStateDefinition(*dict, error)) {
    Error::AddToPrintf(
        error, FROM_HERE, errors::kErrorDomain, errors::kSchemaError,
        "Failed to load base state definition: '%s'", json.c_str());
    return false;
  }
  return true;
}

bool StateManager::SetProperties(const base::DictionaryValue& dict,
                                 ErrorPtr* error) {
  base::Time timestamp = base::Time::Now();
  bool all_success = true;
  for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
       iter.Advance()) {
    if (iter.key().empty()) {
      Error::AddTo(error, FROM_HERE, errors::kErrorDomain,
                   errors::kInvalidPackageError, "State package name is empty");
      all_success = false;
      continue;
    }

    const base::DictionaryValue* package_dict = nullptr;
    if (!iter.value().GetAsDictionary(&package_dict)) {
      Error::AddToPrintf(error, FROM_HERE, errors::json::kDomain,
                         errors::json::kObjectExpected,
                         "State package '%s' must be an object",
                         iter.key().c_str());
      all_success = false;
      continue;
    }

    for (base::DictionaryValue::Iterator it_prop(*package_dict);
         !it_prop.IsAtEnd(); it_prop.Advance()) {
      if (!SetPropertyValue(iter.key() + "." + it_prop.key(), it_prop.value(),
                            timestamp, error)) {
        all_success = false;
        continue;
      }
    }
  }
  for (const auto& cb : on_changed_)
    cb.Run();
  return all_success;
}

bool StateManager::SetPropertiesFromJson(const std::string& json,
                                         ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  if (!dict)
    return false;
  if (!SetProperties(*dict, error)) {
    Error::AddToPrintf(error, FROM_HERE, errors::kErrorDomain,
                       errors::kSchemaError, "Failed to load defaults: '%s'",
                       json.c_str());
    return false;
  }
  return true;
}

StatePackage* StateManager::FindPackage(const std::string& package_name) {
  auto it = packages_.find(package_name);
  return (it != packages_.end()) ? it->second.get() : nullptr;
}

const StatePackage* StateManager::FindPackage(
    const std::string& package_name) const {
  auto it = packages_.find(package_name);
  return (it != packages_.end()) ? it->second.get() : nullptr;
}

StatePackage* StateManager::FindOrCreatePackage(
    const std::string& package_name) {
  StatePackage* package = FindPackage(package_name);
  if (package == nullptr) {
    std::unique_ptr<StatePackage> new_package{new StatePackage(package_name)};
    package = packages_.emplace(package_name, std::move(new_package))
                  .first->second.get();
  }
  return package;
}

}  // namespace weave
