Add support for state updates on ComponentManager

Implemented state support functionality from StateManager. Now the
ComponentManager object can replace StateManager, StatePackage,
CommandDictionary and CommandManager classes.

Most implementation was borrowed/adapted from existing StateManager
and StatePackage classes. And the interfaces were made compatible
with those two classes so the new ComponentManager can be used as
a drop-in replacement of the old classes.

BUG: 25841719
Change-Id: Ib981de1cf44c47a95594c56d78ac211812b3fa44
Reviewed-on: https://weave-review.googlesource.com/1780
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/src/component_manager.h b/src/component_manager.h
index d9de8ea..2deaa30 100644
--- a/src/component_manager.h
+++ b/src/component_manager.h
@@ -5,21 +5,49 @@
 #ifndef LIBWEAVE_SRC_COMPONENT_MANAGER_H_
 #define LIBWEAVE_SRC_COMPONENT_MANAGER_H_
 
+#include <map>
 #include <memory>
 
+#include <base/callback_list.h>
+#include <base/time/clock.h>
 #include <base/values.h>
 #include <weave/error.h>
 
 #include "src/commands/command_dictionary.h"
 #include "src/commands/command_queue.h"
+#include "src/states/state_change_queue.h"
 
 namespace weave {
 
 class CommandInstance;
 
+// A simple notification record event to track component state changes.
+// The |timestamp| records the time of the state change.
+// |changed_properties| contains a property set with the new property values
+// which were updated at the time the event was recorded.
+struct ComponentStateChange {
+  ComponentStateChange(base::Time time,
+                       const std::string& path,
+                       std::unique_ptr<base::DictionaryValue> properties)
+      : timestamp{time}, component{path},
+        changed_properties{std::move(properties)} {}
+  base::Time timestamp;
+  std::string component;
+  std::unique_ptr<base::DictionaryValue> changed_properties;
+};
+
 class ComponentManager final {
  public:
+  using UpdateID = uint64_t;
+  using Token =
+      std::unique_ptr<base::CallbackList<void(UpdateID)>::Subscription>;
+  struct StateSnapshot {
+    UpdateID update_id;
+    std::vector<ComponentStateChange> state_changes;
+  };
+
   ComponentManager();
+  explicit ComponentManager(base::Clock* clock);
   ~ComponentManager();
 
   // Loads trait definition schema.
@@ -30,7 +58,7 @@
   bool LoadTraits(const std::string& json, ErrorPtr* error);
 
   // Sets callback which is called when new trait definitions are added.
-  void AddTraitDefChanged(const base::Closure& callback);
+  void AddTraitDefChangedCallback(const base::Closure& callback);
 
   // Adds a new component instance to device.
   // |path| is a path to the parent component (or empty string if a root-level
@@ -51,6 +79,9 @@
                              const std::vector<std::string>& traits,
                              ErrorPtr* error);
 
+  // Sets callback which is called when new components are added.
+  void AddComponentTreeChangedCallback(const base::Closure& callback);
+
   // Adds a new command instance to the command queue. The command specified in
   // |command_instance| must be fully initialized and have its name, component,
   // id populated.
@@ -102,11 +133,49 @@
   // Returns the full JSON dictionary containing component instances.
   const base::DictionaryValue& GetComponents() const { return components_; }
 
+  // Component state manipulation methods.
+  bool SetStateProperties(const std::string& component_path,
+                          const base::DictionaryValue& dict,
+                          ErrorPtr* error);
+  bool SetStatePropertiesFromJson(const std::string& component_path,
+                                  const std::string& json,
+                                  ErrorPtr* error);
+  const base::Value* GetStateProperty(const std::string& component_path,
+                                      const std::string& name,
+                                      ErrorPtr* error) const;
+  bool SetStateProperty(const std::string& component_path,
+                        const std::string& name,
+                        const base::Value& value,
+                        ErrorPtr* error);
+
+  void AddStateChangedCallback(const base::Closure& callback);
+
+  // Returns the recorded state changes since last time this method was called.
+  StateSnapshot GetAndClearRecordedStateChanges();
+
+  // Called to notify that the state patch with |id| has been successfully sent
+  // to the server and processed.
+  void NotifyStateUpdatedOnServer(UpdateID id);
+
+  // Returns an ID of last state change update. Each SetStatePropertyNNN()
+  // invocation increments this value by 1.
+  UpdateID GetLastStateChangeId() const { return last_state_change_id_; }
+
+  // Subscribes for device state update notifications from cloud server.
+  // The |callback| will be called every time a state patch with given ID is
+  // successfully received and processed by Weave server.
+  // Returns a subscription token. As soon as this token is destroyed, the
+  // respective callback is removed from the callback list.
+  Token AddServerStateUpdatedCallback(
+      const base::Callback<void(UpdateID)>& callback);
+
  private:
   // A helper method to find a JSON element of component at |path| to add new
   // sub-components to.
   base::DictionaryValue* FindComponentGraftNode(const std::string& path,
                                                 ErrorPtr* error);
+  base::DictionaryValue* FindMutableComponent(const std::string& path,
+                                              ErrorPtr* error);
 
   // Helper method to find a sub-component given a root node and a relative path
   // from the root to the target component.
@@ -115,13 +184,22 @@
       const std::string& path,
       ErrorPtr* error);
 
-
+  base::Clock* clock_{nullptr};
   base::DictionaryValue traits_;  // Trait definitions.
   base::DictionaryValue components_;  // Component instances.
   CommandQueue command_queue_;  // Command queue containing command instances.
-  std::vector<base::Callback<void()>> on_trait_changed_;
+  std::vector<base::Closure> on_trait_changed_;
+  std::vector<base::Closure> on_componet_tree_changed_;
+  std::vector<base::Closure> on_state_changed_;
   uint32_t next_command_id_{0};
 
+  std::map<std::string, std::unique_ptr<StateChangeQueue>> state_change_queues_;
+  // An ID of last state change update. Each NotifyPropertiesUpdated()
+  // invocation increments this value by 1.
+  UpdateID last_state_change_id_{0};
+  // Callback list for state change queue event sinks.
+  base::CallbackList<void(UpdateID)> on_server_state_updated_;
+
   DISALLOW_COPY_AND_ASSIGN(ComponentManager);
 };