// 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 char kMinimalRole[] = "minimalRole";

const EnumToStringMap<UserRole>::Map kMap[] = {
    {UserRole::kViewer, "viewer"},
    {UserRole::kUser, "user"},
    {UserRole::kOwner, "owner"},
    {UserRole::kManager, "manager"},
};
}  // anonymous namespace

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

ComponentManagerImpl::ComponentManagerImpl(provider::TaskRunner* task_runner,
                                           base::Clock* clock)
    : clock_{clock ? clock : &default_clock_},
      command_queue_{task_runner, 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)) {
    return Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidState,
                              "Component '%s' already exists at path '%s'",
                              name.c_str(), path.c_str());
  }

  // Check to make sure the declared traits are already defined.
  for (const std::string& trait : traits) {
    if (!FindTraitDefinition(trait)) {
      return Error::AddToPrintf(error, FROM_HERE,
                                errors::commands::kInvalidPropValue,
                                "Trait '%s' is undefined", trait.c_str());
    }
  }
  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)) {
    return Error::AddToPrintf(error, FROM_HERE, errors::commands::kInvalidState,
                              "Component '%s' does not exist at path '%s'",
                              name.c_str(), path.c_str());
  }

  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)) {
    return Error::AddToPrintf(
        error, FROM_HERE, errors::commands::kInvalidState,
        "There is no component array named '%s' at path '%s'", name.c_str(),
        path.c_str());
  }

  if (!array_value->Remove(index, nullptr)) {
    return 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);
  }

  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) {
    return Error::AddToPrintf(error, FROM_HERE, "access_denied",
                              "User role '%s' less than minimal: '%s'",
                              EnumToString(role).c_str(),
                              EnumToString(minimal_role).c_str());
  }

  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()) {
      return 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());
    }
    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) {
    return Error::AddToPrintf(error, FROM_HERE, "trait_not_supported",
                              "Component '%s' doesn't support trait '%s'",
                              component_path.c_str(), pair.first.c_str());
  }

  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) {
    return Error::AddToPrintf(
        error, FROM_HERE, errors::commands::kInvalidCommandName,
        "Command definition for '%s' not found", command_name.c_str());
  }
  std::string value;
  // The JSON definition has been pre-validated already in LoadCommands, so
  // just using CHECKs here.
  CHECK(command->GetString(kMinimalRole, &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()) {
    return Error::AddToPrintf(error, FROM_HERE,
                              errors::commands::kPropertyMissing,
                              "Empty state package in '%s'", name.c_str());
  }
  if (pair.second.empty()) {
    return Error::AddToPrintf(
        error, FROM_HERE, errors::commands::kPropertyMissing,
        "State property name not specified in '%s'", name.c_str());
  }
  std::string key = base::StringPrintf("state.%s", name.c_str());
  const base::Value* value = nullptr;
  if (!component->Get(key, &value)) {
    return 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()) {
    return Error::AddToPrintf(error, FROM_HERE,
                              errors::commands::kPropertyMissing,
                              "Empty state package in '%s'", name.c_str());
  }
  if (pair.second.empty()) {
    return Error::AddToPrintf(
        error, FROM_HERE, errors::commands::kPropertyMissing,
        "State property name not specified in '%s'", name.c_str());
  }
  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()) {
      return Error::AddToPrintf(
          error, FROM_HERE, errors::commands::kPropertyMissing,
          "Empty path element at '%s'", root_path.c_str());
    }
    if (!element.second.empty()) {
      if (element.second.back() != ']') {
        return Error::AddToPrintf(
            error, FROM_HERE, errors::commands::kPropertyMissing,
            "Invalid array element syntax '%s'", parts[i].c_str());
      }
      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) {
        return Error::AddToPrintf(
            error, FROM_HERE, errors::commands::kInvalidPropValue,
            "Invalid array index '%s'", element.second.c_str());
      }
    }

    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)) {
        return Error::AddToPrintf(error, FROM_HERE,
                                  errors::commands::kPropertyMissing,
                                  "Component '%s' does not exist at '%s'",
                                  element.first.c_str(), root_path.c_str());
      }
    }

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

    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)) {
        return 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);
      }
    }
    if (!root_path.empty())
      root_path += '.';
    root_path += parts[i];
  }
  return root;
}

}  // namespace weave
