fixing Set on report properties

Setting valid value for property which is incorrect for current
configuration will result in OK response, but will change ErrorMessages
property. ErrorMessages will contain information about error type and
property name.

Tested:
- Change interval from 1000 to 0 for periodic report changes status from
  Enabled to Disabled.
- Change interval from 0 to 1000 for periodic report changes status from
  Disabled to Enabled.

Signed-off-by: Krzysztof Grobelny <krzysztof.grobelny@intel.com>
Signed-off-by: Szymon Dompke <szymon.dompke@intel.com>
Change-Id: I34add1ed0308b3da0850b1db6a67a217d11b6956
diff --git a/src/state.hpp b/src/state.hpp
new file mode 100644
index 0000000..91a7daf
--- /dev/null
+++ b/src/state.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include <bitset>
+
+enum class ReportFlags
+{
+    enabled,
+    valid
+};
+
+enum class StateEvent
+{
+    active,
+    inactive,
+    activated,
+    deactivated
+};
+
+template <class T>
+concept boolean = std::is_same_v<T, bool>;
+
+template <class Flags, class Object, Flags... Keys>
+class State
+{
+  public:
+    explicit State(Object& object) : object(object)
+    {}
+
+    template <Flags... Indexes>
+    StateEvent set(boolean auto... values)
+    {
+        static_assert(sizeof...(Indexes) == sizeof...(values));
+
+        const bool previous = flags.all();
+
+        (flags.set(indexOf<0, Indexes, Keys...>(), values), ...);
+
+        if (previous != flags.all())
+        {
+            if (flags.all())
+            {
+                object.activate();
+                return StateEvent::activated;
+            }
+            else
+            {
+                object.deactivate();
+                return StateEvent::deactivated;
+            }
+        }
+
+        return flags.all() ? StateEvent::active : StateEvent::inactive;
+    }
+
+    template <Flags Index>
+    bool get() const
+    {
+        return flags.test(indexOf<0, Index, Keys...>());
+    }
+
+    bool isActive() const
+    {
+        return flags.all();
+    }
+
+  private:
+    template <size_t Index, Flags flag, Flags it, Flags... list>
+    static constexpr size_t indexOf()
+    {
+        if constexpr (flag == it)
+        {
+            return Index;
+        }
+        else
+        {
+            return indexOf<Index + 1, flag, list...>();
+        }
+    }
+
+    Object& object;
+    std::bitset<sizeof...(Keys)> flags{0};
+};