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

#include <base/logging.h>
#include <base/values.h>
#include <weave/provider/config_store.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(provider::ConfigStore* config_store) {
  LOG(INFO) << "Initializing StateManager.";

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

  // Load component-specific device state definitions.
  for (const auto& state_def : config_store->LoadStateDefs())
    CHECK(LoadStateDefinition(state_def, nullptr));

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

  // Load component-specific device state defaults.
  for (const auto& json : config_store->LoadStateDefaults())
    CHECK(LoadStateDefaults(json, 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::SetProperties(const base::DictionaryValue& property_set,
                                 ErrorPtr* error) {
  base::Time timestamp = base::Time::Now();
  bool all_success = true;
  for (base::DictionaryValue::Iterator it(property_set); !it.IsAtEnd();
       it.Advance()) {
    if (!SetPropertyValue(it.key(), it.value(), timestamp, error)) {
      // Remember that an error occurred but keep going and update the rest of
      // the properties if possible.
      all_success = false;
    }
  }
  for (const auto& cb : on_changed_)
    cb.Run();
  return all_success;
}

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) {
  base::DictionaryValue::Iterator iter(dict);
  while (!iter.IsAtEnd()) {
    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;
    iter.Advance();
  }

  return true;
}

bool StateManager::LoadStateDefinition(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::LoadStateDefaults(const base::DictionaryValue& dict,
                                     ErrorPtr* error) {
  base::DictionaryValue::Iterator iter(dict);
  while (!iter.IsAtEnd()) {
    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 = FindPackage(package_name);
    if (package == nullptr) {
      Error::AddToPrintf(error, FROM_HERE, errors::json::kDomain,
                         errors::json::kObjectExpected,
                         "Providing values for undefined state package '%s'",
                         package_name.c_str());
      return false;
    }
    if (!package->AddValuesFromJson(package_dict, error))
      return false;
    iter.Advance();
  }
  return true;
}

bool StateManager::LoadStateDefaults(const std::string& json, ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  if (!dict)
    return false;
  if (!LoadStateDefaults(*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
