// 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 {

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.
}

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, std::move(pkg_value));
  }
  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::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
