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

#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>

#include "src/commands/schema_constants.h"
#include "src/json_error_codes.h"
#include "src/string_utils.h"
#include "src/utils.h"

namespace weave {

namespace {
// Max of 100 state update events should be enough in the queue.
const size_t kMaxStateChangeQueueSize = 100;

const EnumToStringMap<UserRole>::Map kMap[] = {
    {UserRole::kViewer, commands::attributes::kCommand_Role_Viewer},
    {UserRole::kUser, commands::attributes::kCommand_Role_User},
    {UserRole::kOwner, commands::attributes::kCommand_Role_Owner},
    {UserRole::kManager, commands::attributes::kCommand_Role_Manager},
};
}  // anonymous namespace

template <>
LIBWEAVE_EXPORT EnumToStringMap<UserRole>::EnumToStringMap()
    : EnumToStringMap(kMap) {}

ComponentManagerImpl::ComponentManagerImpl(base::Clock* clock)
    : clock_{clock ? clock : &default_clock_} {}

ComponentManagerImpl::~ComponentManagerImpl() {}

bool ComponentManagerImpl::AddComponent(const std::string& path,
                                        const std::string& name,
                                        const std::vector<std::string>& traits,
                                        ErrorPtr* error) {
  base::DictionaryValue* root = &components_;
  if (!path.empty()) {
    root = FindComponentGraftNode(path, error);
    if (!root)
      return false;
  }
  if (root->GetWithoutPathExpansion(name, nullptr)) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidState,
                       "Component '%s' already exists at path '%s'",
                       name.c_str(), path.c_str());
    return false;
  }

  // Check to make sure the declared traits are already defined.
  for (const std::string& trait : traits) {
    if (!FindTraitDefinition(trait)) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidPropValue,
                         "Trait '%s' is undefined", trait.c_str());
      return false;
    }
  }
  std::unique_ptr<base::DictionaryValue> dict{new base::DictionaryValue};
  std::unique_ptr<base::ListValue> traits_list{new base::ListValue};
  traits_list->AppendStrings(traits);
  dict->Set("traits", traits_list.release());
  root->SetWithoutPathExpansion(name, dict.release());
  for (const auto& cb : on_componet_tree_changed_)
    cb.Run();
  return true;
}

bool ComponentManagerImpl::AddComponentArrayItem(
    const std::string& path,
    const std::string& name,
    const std::vector<std::string>& traits,
    ErrorPtr* error) {
  base::DictionaryValue* root = &components_;
  if (!path.empty()) {
    root = FindComponentGraftNode(path, error);
    if (!root)
      return false;
  }
  base::ListValue* array_value = nullptr;
  if (!root->GetListWithoutPathExpansion(name, &array_value)) {
    array_value = new base::ListValue;
    root->SetWithoutPathExpansion(name, array_value);
  }
  std::unique_ptr<base::DictionaryValue> dict{new base::DictionaryValue};
  std::unique_ptr<base::ListValue> traits_list{new base::ListValue};
  traits_list->AppendStrings(traits);
  dict->Set("traits", traits_list.release());
  array_value->Append(dict.release());
  for (const auto& cb : on_componet_tree_changed_)
    cb.Run();
  return true;
}

bool ComponentManagerImpl::RemoveComponent(const std::string& path,
                                           const std::string& name,
                                           ErrorPtr* error) {
  base::DictionaryValue* root = &components_;
  if (!path.empty()) {
    root = FindComponentGraftNode(path, error);
    if (!root)
      return false;
  }

  if (!root->RemoveWithoutPathExpansion(name, nullptr)) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidState,
                       "Component '%s' does not exist at path '%s'",
                       name.c_str(), path.c_str());
    return false;
  }

  for (const auto& cb : on_componet_tree_changed_)
    cb.Run();
  return true;
}

bool ComponentManagerImpl::RemoveComponentArrayItem(const std::string& path,
                                                    const std::string& name,
                                                    size_t index,
                                                    ErrorPtr* error) {
  base::DictionaryValue* root = &components_;
  if (!path.empty()) {
    root = FindComponentGraftNode(path, error);
    if (!root)
      return false;
  }

  base::ListValue* array_value = nullptr;
  if (!root->GetListWithoutPathExpansion(name, &array_value)) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidState,
                       "There is no component array named '%s' at path '%s'",
                       name.c_str(), path.c_str());
    return false;
  }

  if (!array_value->Remove(index, nullptr)) {
    Error::AddToPrintf(
        error, FROM_HERE, errors::commands::kInvalidState,
        "Component array '%s' at path '%s' does not have an element %zu",
        name.c_str(), path.c_str(), index);
    return false;
  }

  for (const auto& cb : on_componet_tree_changed_)
    cb.Run();
  return true;
}

void ComponentManagerImpl::AddComponentTreeChangedCallback(
    const base::Closure& callback) {
  on_componet_tree_changed_.push_back(callback);
  callback.Run();
}

bool ComponentManagerImpl::LoadTraits(const base::DictionaryValue& dict,
                                      ErrorPtr* error) {
  bool modified = false;
  bool result = true;
  // Check if any of the new traits are already defined. If so, make sure the
  // definition is exactly the same, or else this is an error.
  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    if (it.value().GetType() != base::Value::TYPE_DICTIONARY) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                         "Trait '%s' must be an object", it.key().c_str());
      result = false;
      break;
    }
    const base::DictionaryValue* existing_def = nullptr;
    if (traits_.GetDictionary(it.key(), &existing_def)) {
      if (!existing_def->Equals(&it.value())) {
        Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                           "Trait '%s' cannot be redefined", it.key().c_str());
        result = false;
        break;
      }
    } else {
      traits_.Set(it.key(), it.value().DeepCopy());
      modified = true;
    }
  }

  if (modified) {
    for (const auto& cb : on_trait_changed_)
      cb.Run();
  }
  return result;
}

bool ComponentManagerImpl::LoadTraits(const std::string& json,
                                      ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  if (!dict)
    return false;
  return LoadTraits(*dict, error);
}

void ComponentManagerImpl::AddTraitDefChangedCallback(
    const base::Closure& callback) {
  on_trait_changed_.push_back(callback);
  callback.Run();
}

void ComponentManagerImpl::AddCommand(
    std::unique_ptr<CommandInstance> command_instance) {
  command_queue_.Add(std::move(command_instance));
}

std::unique_ptr<CommandInstance> ComponentManagerImpl::ParseCommandInstance(
    const base::DictionaryValue& command,
    Command::Origin command_origin,
    UserRole role,
    std::string* id,
    ErrorPtr* error) {
  std::string command_id;
  auto command_instance =
      CommandInstance::FromJson(&command, command_origin, &command_id, error);
  // If we fail to validate the command definition, but there was a command ID
  // specified there, return it to the caller when requested. This will be
  // used to abort cloud commands.
  if (id)
    *id = command_id;

  if (!command_instance)
    return nullptr;

  UserRole minimal_role;
  if (!GetMinimalRole(command_instance->GetName(), &minimal_role, error))
    return nullptr;

  if (role < minimal_role) {
    Error::AddToPrintf(error, FROM_HERE, "access_denied",
                       "User role '%s' less than minimal: '%s'",
                       EnumToString(role).c_str(),
                       EnumToString(minimal_role).c_str());
    return nullptr;
  }

  std::string component_path = command_instance->GetComponent();
  if (component_path.empty()) {
    // Find the component to which to route this command. Get the trait name
    // from the command name and find the first component that has this trait.
    auto trait_name =
        SplitAtFirst(command_instance->GetName(), ".", true).first;
    component_path = FindComponentWithTrait(trait_name);
    if (component_path.empty()) {
      Error::AddToPrintf(
          error, FROM_HERE, "unrouted_command",
          "Unable route command '%s' because there is no component supporting"
          "trait '%s'",
          command_instance->GetName().c_str(), trait_name.c_str());
      return nullptr;
    }
    command_instance->SetComponent(component_path);
  }

  const base::DictionaryValue* component = FindComponent(component_path, error);
  if (!component)
    return nullptr;

  // Check that the command's trait is supported by the given component.
  auto pair = SplitAtFirst(command_instance->GetName(), ".", true);

  bool trait_supported = false;
  const base::ListValue* supported_traits = nullptr;
  if (component->GetList("traits", &supported_traits)) {
    for (const base::Value* value : *supported_traits) {
      std::string trait;
      CHECK(value->GetAsString(&trait));
      if (trait == pair.first) {
        trait_supported = true;
        break;
      }
    }
  }

  if (!trait_supported) {
    Error::AddToPrintf(error, FROM_HERE, "trait_not_supported",
                       "Component '%s' doesn't support trait '%s'",
                       component_path.c_str(), pair.first.c_str());
    return nullptr;
  }

  if (command_id.empty()) {
    command_id = std::to_string(++next_command_id_);
    command_instance->SetID(command_id);
    if (id)
      *id = command_id;
  }

  return command_instance;
}

CommandInstance* ComponentManagerImpl::FindCommand(const std::string& id) {
  return command_queue_.Find(id);
}

void ComponentManagerImpl::AddCommandAddedCallback(
    const CommandQueue::CommandCallback& callback) {
  command_queue_.AddCommandAddedCallback(callback);
}

void ComponentManagerImpl::AddCommandRemovedCallback(
    const CommandQueue::CommandCallback& callback) {
  command_queue_.AddCommandRemovedCallback(callback);
}

void ComponentManagerImpl::AddCommandHandler(
    const std::string& component_path,
    const std::string& command_name,
    const Device::CommandHandlerCallback& callback) {
  // If both component_path and command_name are empty, we are adding the
  // default handler for all commands.
  if (!component_path.empty() || !command_name.empty()) {
    CHECK(FindCommandDefinition(command_name)) << "Command undefined: "
                                               << command_name;
  }
  command_queue_.AddCommandHandler(component_path, command_name, callback);
}

const base::DictionaryValue* ComponentManagerImpl::FindComponent(
    const std::string& path,
    ErrorPtr* error) const {
  return FindComponentAt(&components_, path, error);
}

const base::DictionaryValue* ComponentManagerImpl::FindTraitDefinition(
    const std::string& name) const {
  const base::DictionaryValue* trait = nullptr;
  traits_.GetDictionaryWithoutPathExpansion(name, &trait);
  return trait;
}

const base::DictionaryValue* ComponentManagerImpl::FindCommandDefinition(
    const std::string& command_name) const {
  const base::DictionaryValue* definition = nullptr;
  std::vector<std::string> components = Split(command_name, ".", true, false);
  // Make sure the |command_name| came in form of trait_name.command_name.
  if (components.size() != 2)
    return definition;
  std::string key = base::StringPrintf("%s.commands.%s", components[0].c_str(),
                                       components[1].c_str());
  traits_.GetDictionary(key, &definition);
  return definition;
}

bool ComponentManagerImpl::GetMinimalRole(const std::string& command_name,
                                          UserRole* minimal_role,
                                          ErrorPtr* error) const {
  const base::DictionaryValue* command = FindCommandDefinition(command_name);
  if (!command) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidCommandName,
                       "Command definition for '%s' not found",
                       command_name.c_str());
    return false;
  }
  std::string value;
  // The JSON definition has been pre-validated already in LoadCommands, so
  // just using CHECKs here.
  CHECK(command->GetString(commands::attributes::kCommand_Role, &value));
  CHECK(StringToEnum(value, minimal_role));
  return true;
}

void ComponentManagerImpl::AddStateChangedCallback(
    const base::Closure& callback) {
  on_state_changed_.push_back(callback);
  callback.Run();  // Force to read current state.
}

bool ComponentManagerImpl::SetStateProperties(const std::string& component_path,
                                              const base::DictionaryValue& dict,
                                              ErrorPtr* error) {
  base::DictionaryValue* component =
      FindMutableComponent(component_path, error);
  if (!component)
    return false;

  base::DictionaryValue* state = nullptr;
  if (!component->GetDictionary("state", &state)) {
    state = new base::DictionaryValue;
    component->Set("state", state);
  }
  state->MergeDictionary(&dict);
  last_state_change_id_++;
  auto& queue = state_change_queues_[component_path];
  if (!queue)
    queue.reset(new StateChangeQueue{kMaxStateChangeQueueSize});
  base::Time timestamp = clock_->Now();
  queue->NotifyPropertiesUpdated(timestamp, dict);
  for (const auto& cb : on_state_changed_)
    cb.Run();
  return true;
}

bool ComponentManagerImpl::SetStatePropertiesFromJson(
    const std::string& component_path,
    const std::string& json,
    ErrorPtr* error) {
  std::unique_ptr<const base::DictionaryValue> dict = LoadJsonDict(json, error);
  return dict && SetStateProperties(component_path, *dict, error);
}

const base::Value* ComponentManagerImpl::GetStateProperty(
    const std::string& component_path,
    const std::string& name,
    ErrorPtr* error) const {
  const base::DictionaryValue* component = FindComponent(component_path, error);
  if (!component)
    return nullptr;
  auto pair = SplitAtFirst(name, ".", true);
  if (pair.first.empty()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                       "Empty state package in '%s'", name.c_str());
    return nullptr;
  }
  if (pair.second.empty()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                       "State property name not specified in '%s'",
                       name.c_str());
    return nullptr;
  }
  std::string key = base::StringPrintf("state.%s", name.c_str());
  const base::Value* value = nullptr;
  if (!component->Get(key, &value)) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                       "State property '%s' not found in component '%s'",
                       name.c_str(), component_path.c_str());
  }
  return value;
}

bool ComponentManagerImpl::SetStateProperty(const std::string& component_path,
                                            const std::string& name,
                                            const base::Value& value,
                                            ErrorPtr* error) {
  base::DictionaryValue dict;
  auto pair = SplitAtFirst(name, ".", true);
  if (pair.first.empty()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                       "Empty state package in '%s'", name.c_str());
    return false;
  }
  if (pair.second.empty()) {
    Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                       "State property name not specified in '%s'",
                       name.c_str());
    return false;
  }
  dict.Set(name, value.DeepCopy());
  return SetStateProperties(component_path, dict, error);
}

ComponentManager::StateSnapshot
ComponentManagerImpl::GetAndClearRecordedStateChanges() {
  StateSnapshot snapshot;
  snapshot.update_id = GetLastStateChangeId();
  for (auto& pair : state_change_queues_) {
    auto changes = pair.second->GetAndClearRecordedStateChanges();
    auto component = pair.first;
    auto conv = [component](weave::StateChange& change) {
      return ComponentStateChange{change.timestamp, component,
                                  std::move(change.changed_properties)};
    };
    std::transform(changes.begin(), changes.end(),
                   std::back_inserter(snapshot.state_changes), conv);
  }

  // Sort events by the timestamp.
  auto pred = [](const ComponentStateChange& lhs,
                 const ComponentStateChange& rhs) {
    return lhs.timestamp < rhs.timestamp;
  };
  std::sort(snapshot.state_changes.begin(), snapshot.state_changes.end(), pred);
  state_change_queues_.clear();
  return snapshot;
}

void ComponentManagerImpl::NotifyStateUpdatedOnServer(UpdateID id) {
  on_server_state_updated_.Notify(id);
}

ComponentManager::Token ComponentManagerImpl::AddServerStateUpdatedCallback(
    const base::Callback<void(UpdateID)>& callback) {
  if (state_change_queues_.empty())
    callback.Run(GetLastStateChangeId());
  return Token{on_server_state_updated_.Add(callback).release()};
}

std::string ComponentManagerImpl::FindComponentWithTrait(
    const std::string& trait) const {
  for (base::DictionaryValue::Iterator it(components_); !it.IsAtEnd();
       it.Advance()) {
    const base::ListValue* supported_traits = nullptr;
    const base::DictionaryValue* component = nullptr;
    CHECK(it.value().GetAsDictionary(&component));
    if (component->GetList("traits", &supported_traits)) {
      for (const base::Value* value : *supported_traits) {
        std::string supported_trait;
        CHECK(value->GetAsString(&supported_trait));
        if (trait == supported_trait)
          return it.key();
      }
    }
  }
  return std::string{};
}

bool ComponentManagerImpl::AddLegacyCommandDefinitions(
    const base::DictionaryValue& dict,
    ErrorPtr* error) {
  bool result = true;
  bool modified = false;
  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    const base::DictionaryValue* command_dict = nullptr;
    if (!it.value().GetAsDictionary(&command_dict)) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                         "Package '%s' must be an object", it.key().c_str());
      result = false;
      continue;
    }
    AddTraitToLegacyComponent(it.key());
    for (base::DictionaryValue::Iterator it_def(*command_dict);
         !it_def.IsAtEnd(); it_def.Advance()) {
      std::string key = base::StringPrintf("%s.commands.%s", it.key().c_str(),
                                           it_def.key().c_str());
      if (traits_.GetDictionary(key, nullptr)) {
        Error::AddToPrintf(error, FROM_HERE,
                           errors::commands::kInvalidPropValue,
                           "Redefining command '%s.%s'", it.key().c_str(),
                           it_def.key().c_str());
        result = false;
        continue;
      }
      traits_.Set(key, it_def.value().DeepCopy());
      modified = true;
    }
  }

  if (modified) {
    for (const auto& cb : on_trait_changed_)
      cb.Run();
  }
  return result;
}

bool ComponentManagerImpl::AddLegacyStateDefinitions(
    const base::DictionaryValue& dict,
    ErrorPtr* error) {
  bool result = true;
  bool modified = false;
  for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
    const base::DictionaryValue* state_dict = nullptr;
    if (!it.value().GetAsDictionary(&state_dict)) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                         "Package '%s' must be an object", it.key().c_str());
      result = false;
      continue;
    }
    AddTraitToLegacyComponent(it.key());
    for (base::DictionaryValue::Iterator it_def(*state_dict); !it_def.IsAtEnd();
         it_def.Advance()) {
      std::string key = base::StringPrintf("%s.state.%s", it.key().c_str(),
                                           it_def.key().c_str());
      if (traits_.GetDictionary(key, nullptr)) {
        Error::AddToPrintf(error, FROM_HERE,
                           errors::commands::kInvalidPropValue,
                           "Redefining state property '%s.%s'",
                           it.key().c_str(), it_def.key().c_str());
        result = false;
        continue;
      }
      traits_.Set(key, it_def.value().DeepCopy());
      modified = true;
    }
  }

  if (modified) {
    for (const auto& cb : on_trait_changed_)
      cb.Run();
  }
  return result;
}

const base::DictionaryValue& ComponentManagerImpl::GetLegacyState() const {
  legacy_state_.Clear();
  // Build state from components.
  for (base::DictionaryValue::Iterator it(components_); !it.IsAtEnd();
       it.Advance()) {
    const base::DictionaryValue* component_dict = nullptr;
    const base::DictionaryValue* component_state = nullptr;
    if (it.value().GetAsDictionary(&component_dict) &&
        component_dict->GetDictionary("state", &component_state)) {
      legacy_state_.MergeDictionary(component_state);
    }
  }
  return legacy_state_;
}

const base::DictionaryValue& ComponentManagerImpl::GetLegacyCommandDefinitions()
    const {
  legacy_command_defs_.Clear();
  // Build commandDefs from traits.
  for (base::DictionaryValue::Iterator it(traits_); !it.IsAtEnd();
       it.Advance()) {
    const base::DictionaryValue* trait_dict = nullptr;
    const base::DictionaryValue* trait_commands = nullptr;
    if (it.value().GetAsDictionary(&trait_dict) &&
        trait_dict->GetDictionary("commands", &trait_commands)) {
      base::DictionaryValue dict;
      dict.Set(it.key(), trait_commands->DeepCopy());
      legacy_command_defs_.MergeDictionary(&dict);
    }
  }
  return legacy_command_defs_;
}

void ComponentManagerImpl::AddTraitToLegacyComponent(const std::string& trait) {
  // First check if we already have a component supporting this trait.
  if (!FindComponentWithTrait(trait).empty())
    return;

  // If not, add this trait to the first component available.
  base::DictionaryValue* component = nullptr;
  base::DictionaryValue::Iterator it(components_);
  if (it.IsAtEnd()) {
    // No components at all. Create a new one with dummy name.
    // This normally wouldn't happen since libweave creates its own component
    // at startup.
    component = new base::DictionaryValue;
    components_.Set("__weave__", component);
  } else {
    CHECK(components_.GetDictionary(it.key(), &component));
  }
  base::ListValue* traits = nullptr;
  if (!component->GetList("traits", &traits)) {
    traits = new base::ListValue;
    component->Set("traits", traits);
  }
  traits->AppendString(trait);
}

base::DictionaryValue* ComponentManagerImpl::FindComponentGraftNode(
    const std::string& path,
    ErrorPtr* error) {
  base::DictionaryValue* root = nullptr;
  base::DictionaryValue* component = FindMutableComponent(path, error);
  if (component && !component->GetDictionary("components", &root)) {
    root = new base::DictionaryValue;
    component->Set("components", root);
  }
  return root;
}

base::DictionaryValue* ComponentManagerImpl::FindMutableComponent(
    const std::string& path,
    ErrorPtr* error) {
  return const_cast<base::DictionaryValue*>(
      FindComponentAt(&components_, path, error));
}

const base::DictionaryValue* ComponentManagerImpl::FindComponentAt(
    const base::DictionaryValue* root,
    const std::string& path,
    ErrorPtr* error) {
  auto parts = Split(path, ".", true, false);
  std::string root_path;
  for (size_t i = 0; i < parts.size(); i++) {
    auto element = SplitAtFirst(parts[i], "[", true);
    int array_index = -1;
    if (element.first.empty()) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                         "Empty path element at '%s'", root_path.c_str());
      return nullptr;
    }
    if (!element.second.empty()) {
      if (element.second.back() != ']') {
        Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                           "Invalid array element syntax '%s'",
                           parts[i].c_str());
        return nullptr;
      }
      element.second.pop_back();
      std::string index_str;
      base::TrimWhitespaceASCII(element.second, base::TrimPositions::TRIM_ALL,
                                &index_str);
      if (!base::StringToInt(index_str, &array_index) || array_index < 0) {
        Error::AddToPrintf(error, FROM_HERE,
                           errors::commands::kInvalidPropValue,
                           "Invalid array index '%s'", element.second.c_str());
        return nullptr;
      }
    }

    if (!root_path.empty()) {
      // We have processed at least one item in the path before, so now |root|
      // points to the actual parent component. We need the root to point to
      // the 'components' element containing child sub-components instead.
      if (!root->GetDictionary("components", &root)) {
        Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                           "Component '%s' does not exist at '%s'",
                           element.first.c_str(), root_path.c_str());
        return nullptr;
      }
    }

    const base::Value* value = nullptr;
    if (!root->GetWithoutPathExpansion(element.first, &value)) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                         "Component '%s' does not exist at '%s'",
                         element.first.c_str(), root_path.c_str());
      return nullptr;
    }

    if (value->GetType() == base::Value::TYPE_LIST && array_index < 0) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                         "Element '%s.%s' is an array", root_path.c_str(),
                         element.first.c_str());
      return nullptr;
    }
    if (value->GetType() == base::Value::TYPE_DICTIONARY && array_index >= 0) {
      Error::AddToPrintf(error, FROM_HERE, errors::commands::kTypeMismatch,
                         "Element '%s.%s' is not an array", root_path.c_str(),
                         element.first.c_str());
      return nullptr;
    }

    if (value->GetType() == base::Value::TYPE_DICTIONARY) {
      CHECK(value->GetAsDictionary(&root));
    } else {
      const base::ListValue* component_array = nullptr;
      CHECK(value->GetAsList(&component_array));
      const base::Value* component_value = nullptr;
      if (!component_array->Get(array_index, &component_value) ||
          !component_value->GetAsDictionary(&root)) {
        Error::AddToPrintf(error, FROM_HERE, errors::commands::kPropertyMissing,
                           "Element '%s.%s' does not contain item #%d",
                           root_path.c_str(), element.first.c_str(),
                           array_index);
        return nullptr;
      }
    }
    if (!root_path.empty())
      root_path += '.';
    root_path += parts[i];
  }
  return root;
}

}  // namespace weave
