config: implement group priority

Enable group priority.

Change-Id: I1777906e60d07420835ede904785071ee308c307
Signed-off-by: Alexander Hansen <alexander.hansen@9elements.com>
diff --git a/manager/grouplayout.hpp b/manager/grouplayout.hpp
new file mode 100644
index 0000000..fa932fa
--- /dev/null
+++ b/manager/grouplayout.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include "ledlayout.hpp"
+
+#include <string>
+#include <unordered_map>
+
+namespace phosphor
+{
+namespace led
+{
+/** @namespace Layout
+ *  @brief Depicts the LED and their mappings and group actions
+ */
+namespace Layout
+{
+
+/** @brief Name of the Group and its properties
+ */
+struct GroupLayout
+{
+    int priority = 0;
+    ActionSet actionSet;
+};
+
+struct CompareGroupLayout
+{
+    bool operator()(const Layout::GroupLayout* lhs,
+                    const Layout::GroupLayout* rhs) const
+    {
+        return lhs->priority < rhs->priority;
+    };
+};
+
+} // namespace Layout
+
+using GroupMap = std::unordered_map<std::string, Layout::GroupLayout>;
+
+} // namespace led
+} // namespace phosphor
diff --git a/manager/json-parser.hpp b/manager/json-parser.hpp
index 47f0d00..e92dfbc 100644
--- a/manager/json-parser.hpp
+++ b/manager/json-parser.hpp
@@ -1,5 +1,6 @@
 #include "config.h"
 
+#include "grouplayout.hpp"
 #include "json-config.hpp"
 #include "ledlayout.hpp"
 
@@ -129,10 +130,12 @@
     tmpPath /= groupName;
     auto objpath = tmpPath.string();
     auto members = entry.value("members", empty);
+    int priority = entry.value("Priority", 0);
 
     lg2::debug("config for '{GROUP}'", "GROUP", groupName);
 
     phosphor::led::ActionSet ledActions{};
+    phosphor::led::Layout::GroupLayout groupLayout{};
     for (const auto& member : members)
     {
         loadJsonConfigV1GroupMember(member, priorityMap, ledActions);
@@ -140,7 +143,10 @@
 
     // Generated an std::unordered_map of LedGroupNames to std::set of LEDs
     // containing the name and properties.
-    ledMap.emplace(objpath, ledActions);
+    groupLayout.actionSet = ledActions;
+    groupLayout.priority = priority;
+
+    ledMap.emplace(objpath, groupLayout);
 }
 
 /** @brief Load JSON config and return led map (JSON version 1)
diff --git a/manager/ledlayout.hpp b/manager/ledlayout.hpp
index 7fc896d..c11500f 100644
--- a/manager/ledlayout.hpp
+++ b/manager/ledlayout.hpp
@@ -51,7 +51,6 @@
 } // namespace Layout
 
 using ActionSet = std::set<Layout::LedAction>;
-using GroupMap = std::unordered_map<std::string, ActionSet>;
 
 } // namespace led
 } // namespace phosphor
diff --git a/manager/manager.cpp b/manager/manager.cpp
index ec02419..18d257b 100644
--- a/manager/manager.cpp
+++ b/manager/manager.cpp
@@ -37,16 +37,33 @@
 }
 
 // create the resulting new map from all currently asserted groups
-auto Manager::getNewMap(std::set<const ActionSet*> assertedGroups)
+static auto getNewMapWithGroupPriorities(
+    std::set<const Layout::GroupLayout*, Layout::CompareGroupLayout> sorted)
     -> std::map<LedName, Layout::LedAction>
 {
     std::map<LedName, Layout::LedAction> newState;
 
     // update the new map with the desired state
-    for (const auto it : assertedGroups)
+    for (const auto it : sorted)
     {
         // apply all led actions of that group to the map
-        for (auto action : *it)
+        for (Layout::LedAction action : it->actionSet)
+        {
+            newState[action.name] = action;
+        }
+    }
+    return newState;
+}
+
+static std::map<LedName, Layout::LedAction> getNewMapWithLEDPriorities(
+    std::set<const Layout::GroupLayout*> assertedGroups)
+{
+    std::map<LedName, Layout::LedAction> newState;
+    // update the new map with the desired state
+    for (const Layout::GroupLayout* it : assertedGroups)
+    {
+        // apply all led actions of that group to the map
+        for (Layout::LedAction action : it->actionSet)
         {
             applyGroupAction(newState, action);
         }
@@ -54,6 +71,38 @@
     return newState;
 }
 
+// create the resulting new map from all currently asserted groups
+std::map<LedName, Layout::LedAction>
+    Manager::getNewMap(std::set<const Layout::GroupLayout*> assertedGroups)
+{
+    std::map<LedName, Layout::LedAction> newState;
+
+    std::set<const Layout::GroupLayout*, Layout::CompareGroupLayout> sorted;
+
+    bool groupPriorities = false;
+
+    for (const Layout::GroupLayout* it : assertedGroups)
+    {
+        sorted.insert(it);
+
+        if (it->priority != 0)
+        {
+            groupPriorities = true;
+        }
+    }
+
+    if (groupPriorities)
+    {
+        newState = getNewMapWithGroupPriorities(sorted);
+    }
+    else
+    {
+        newState = getNewMapWithLEDPriorities(assertedGroups);
+    }
+
+    return newState;
+}
+
 // Assert -or- De-assert
 bool Manager::setGroupState(const std::string& path, bool assert,
                             ActionSet& ledsAssert, ActionSet& ledsDeAssert)
diff --git a/manager/manager.hpp b/manager/manager.hpp
index 24a6c17..ea37798 100644
--- a/manager/manager.hpp
+++ b/manager/manager.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "grouplayout.hpp"
 #include "ledlayout.hpp"
 #include "utils.hpp"
 
@@ -93,7 +94,7 @@
     }
 
     /* create the resulting map from all currently asserted groups */
-    static auto getNewMap(std::set<const ActionSet*> assertedGroups)
+    static auto getNewMap(std::set<const Layout::GroupLayout*> assertedGroups)
         -> std::map<LedName, Layout::LedAction>;
 
     /** @brief Given a group name, applies the action on the group
@@ -151,7 +152,7 @@
     DBusHandler dBusHandler;
 
     /** @brief Pointers to groups that are in asserted state */
-    std::set<const ActionSet*> assertedGroups;
+    std::set<const Layout::GroupLayout*> assertedGroups;
 
     /** Map of led name to current state */
     std::map<std::string, Layout::LedAction> ledStateMap;