[Feature]Microwave oven mode cluster implementation (#30441)

* [Feature]Microwave oven mode cluster implementation

* Restyled by clang-format

* Restyled by gn

* remove the restriction that limits usage only to endpoint 1 for microwave oven cluster

* use static delegate instead of new

* Restyled by clang-format

* to shutdown the microwave oven mode cluster instance

* use dynamic allocate to new deleget and use endpoint

* Restyled by clang-format

* sync all-clusters-app.matter

* return fail status when receiving command ChangeToMode by microwave mode

* remove supported command interface from mode base

---------

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
index 799391e..0557d67 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
@@ -3116,6 +3116,40 @@
   command ModifyEnabledAlarms(ModifyEnabledAlarmsRequest): DefaultSuccess = 1;
 }
 
+/** Attributes and commands for selecting a mode from a list of supported options. */
+provisional server cluster MicrowaveOvenMode = 94 {
+  revision 1;
+
+  enum ModeTag : enum16 {
+    kNormal = 16384;
+    kDefrost = 16385;
+  }
+
+  bitmap Feature : bitmap32 {
+    kOnOff = 0x1;
+  }
+
+  struct ModeTagStruct {
+    optional vendor_id mfgCode = 0;
+    enum16 value = 1;
+  }
+
+  struct ModeOptionStruct {
+    char_string<64> label = 0;
+    int8u mode = 1;
+    ModeTagStruct modeTags[] = 2;
+  }
+
+  readonly attribute ModeOptionStruct supportedModes[] = 0;
+  readonly attribute int8u currentMode = 1;
+  readonly attribute command_id generatedCommandList[] = 65528;
+  readonly attribute command_id acceptedCommandList[] = 65529;
+  readonly attribute event_id eventList[] = 65530;
+  readonly attribute attrib_id attributeList[] = 65531;
+  readonly attribute bitmap32 featureMap = 65532;
+  readonly attribute int16u clusterRevision = 65533;
+}
+
 /** This cluster supports remotely monitoring and, where supported, changing the operational state of any device where a state machine is a part of the operation. */
 server cluster OperationalState = 96 {
   revision 1; // NOTE: Default/not specifically set
@@ -6189,6 +6223,17 @@
     handle command ModifyEnabledAlarms;
   }
 
+  server cluster MicrowaveOvenMode {
+    callback attribute supportedModes;
+    callback attribute currentMode;
+    callback attribute generatedCommandList;
+    callback attribute acceptedCommandList;
+    callback attribute eventList;
+    callback attribute attributeList;
+    callback attribute featureMap default = 0;
+    ram      attribute clusterRevision default = 1;
+  }
+
   server cluster OperationalState {
     emits event OperationalError;
     emits event OperationCompletion;
diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
index fe400ec..08a758e 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
@@ -10522,6 +10522,145 @@
           ]
         },
         {
+          "name": "Microwave Oven Mode",
+          "code": 94,
+          "mfgCode": null,
+          "define": "MICROWAVE_OVEN_MODE_CLUSTER",
+          "side": "server",
+          "enabled": 1,
+          "apiMaturity": "provisional",
+          "attributes": [
+            {
+              "name": "SupportedModes",
+              "code": 0,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "CurrentMode",
+              "code": 1,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "GeneratedCommandList",
+              "code": 65528,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AcceptedCommandList",
+              "code": 65529,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AttributeList",
+              "code": 65531,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "FeatureMap",
+              "code": 65532,
+              "mfgCode": null,
+              "side": "server",
+              "type": "bitmap32",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "0",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "ClusterRevision",
+              "code": 65533,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "RAM",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            }
+          ]
+        },
+        {
           "name": "Operational State",
           "code": 96,
           "mfgCode": null,
diff --git a/examples/all-clusters-app/all-clusters-common/include/microwave-oven-mode.h b/examples/all-clusters-app/all-clusters-common/include/microwave-oven-mode.h
new file mode 100644
index 0000000..dd5d5b4
--- /dev/null
+++ b/examples/all-clusters-app/all-clusters-common/include/microwave-oven-mode.h
@@ -0,0 +1,72 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <app/clusters/mode-base-server/mode-base-server.h>
+#include <app/util/af.h>
+#include <app/util/config.h>
+#include <cstring>
+#include <utility>
+
+namespace chip {
+namespace app {
+namespace Clusters {
+
+namespace MicrowaveOvenMode {
+
+const uint8_t ModeNormal  = 0;
+const uint8_t ModeDefrost = 1;
+
+/// This is an application level delegate to handle MicrowaveOvenMode commands according to the specific business logic.
+class ExampleMicrowaveOvenModeDelegate : public ModeBase::Delegate
+{
+private:
+    using ModeTagStructType              = detail::Structs::ModeTagStruct::Type;
+    ModeTagStructType modeTagsNormal[1]  = { { .value = to_underlying(ModeTag::kNormal) } };
+    ModeTagStructType modeTagsDefrost[1] = { { .value = to_underlying(ModeTag::kDefrost) } };
+
+    const detail::Structs::ModeOptionStruct::Type kModeOptions[2] = {
+        detail::Structs::ModeOptionStruct::Type{ .label    = CharSpan::fromCharString("Normal"),
+                                                 .mode     = ModeNormal,
+                                                 .modeTags = DataModel::List<const ModeTagStructType>(modeTagsNormal) },
+        detail::Structs::ModeOptionStruct::Type{ .label    = CharSpan::fromCharString("Defrost"),
+                                                 .mode     = ModeDefrost,
+                                                 .modeTags = DataModel::List<const ModeTagStructType>(modeTagsDefrost) }
+    };
+
+    CHIP_ERROR Init() override;
+    void HandleChangeToMode(uint8_t mode, ModeBase::Commands::ChangeToModeResponse::Type & response) override;
+
+    CHIP_ERROR GetModeLabelByIndex(uint8_t modeIndex, MutableCharSpan & label) override;
+    CHIP_ERROR GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) override;
+    CHIP_ERROR GetModeTagsByIndex(uint8_t modeIndex, DataModel::List<ModeTagStructType> & tags) override;
+
+public:
+    ~ExampleMicrowaveOvenModeDelegate() override = default;
+};
+
+ModeBase::Instance * Instance();
+
+void Shutdown();
+
+} // namespace MicrowaveOvenMode
+
+} // namespace Clusters
+} // namespace app
+} // namespace chip
diff --git a/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp b/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp
new file mode 100644
index 0000000..a7ab998
--- /dev/null
+++ b/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp
@@ -0,0 +1,106 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#include <app-common/zap-generated/attributes/Accessors.h>
+#include <microwave-oven-mode.h>
+
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::MicrowaveOvenMode;
+using chip::Protocols::InteractionModel::Status;
+template <typename T>
+using List              = chip::app::DataModel::List<T>;
+using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type;
+
+static ExampleMicrowaveOvenModeDelegate * gMicrowaveOvenModeDelegate = nullptr;
+static ModeBase::Instance * gMicrowaveOvenModeInstance               = nullptr;
+
+CHIP_ERROR ExampleMicrowaveOvenModeDelegate::Init()
+{
+    return CHIP_NO_ERROR;
+}
+
+// todo refactor code by making a parent class for all ModeInstance classes to reduce flash usage.
+void ExampleMicrowaveOvenModeDelegate::HandleChangeToMode(uint8_t NewMode,
+                                                          ModeBase::Commands::ChangeToModeResponse::Type & response)
+{
+    response.status = to_underlying(ModeBase::StatusCode::kGenericFailure);
+}
+
+CHIP_ERROR ExampleMicrowaveOvenModeDelegate::GetModeLabelByIndex(uint8_t modeIndex, chip::MutableCharSpan & label)
+{
+    if (modeIndex >= ArraySize(kModeOptions))
+    {
+        return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+    }
+    return chip::CopyCharSpanToMutableCharSpan(kModeOptions[modeIndex].label, label);
+}
+
+CHIP_ERROR ExampleMicrowaveOvenModeDelegate::GetModeValueByIndex(uint8_t modeIndex, uint8_t & value)
+{
+    if (modeIndex >= ArraySize(kModeOptions))
+    {
+        return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+    }
+    value = kModeOptions[modeIndex].mode;
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ExampleMicrowaveOvenModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List<ModeTagStructType> & tags)
+{
+    if (modeIndex >= ArraySize(kModeOptions))
+    {
+        return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
+    }
+
+    if (tags.size() < kModeOptions[modeIndex].modeTags.size())
+    {
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+
+    std::copy(kModeOptions[modeIndex].modeTags.begin(), kModeOptions[modeIndex].modeTags.end(), tags.begin());
+    tags.reduce_size(kModeOptions[modeIndex].modeTags.size());
+
+    return CHIP_NO_ERROR;
+}
+
+ModeBase::Instance * MicrowaveOvenMode::Instance()
+{
+    return gMicrowaveOvenModeInstance;
+}
+
+void MicrowaveOvenMode::Shutdown()
+{
+    if (gMicrowaveOvenModeInstance != nullptr)
+    {
+        delete gMicrowaveOvenModeInstance;
+        gMicrowaveOvenModeInstance = nullptr;
+    }
+    if (gMicrowaveOvenModeDelegate != nullptr)
+    {
+        delete gMicrowaveOvenModeDelegate;
+        gMicrowaveOvenModeDelegate = nullptr;
+    }
+}
+
+void emberAfMicrowaveOvenModeClusterInitCallback(chip::EndpointId endpointId)
+{
+    VerifyOrDie(gMicrowaveOvenModeDelegate == nullptr && gMicrowaveOvenModeInstance == nullptr);
+    gMicrowaveOvenModeDelegate = new MicrowaveOvenMode::ExampleMicrowaveOvenModeDelegate;
+    gMicrowaveOvenModeInstance =
+        new ModeBase::Instance(gMicrowaveOvenModeDelegate, endpointId, MicrowaveOvenMode::Id, chip::to_underlying(Feature::kOnOff));
+    gMicrowaveOvenModeInstance->Init();
+}
diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn
index 215f79f..cfe028c 100644
--- a/examples/all-clusters-app/linux/BUILD.gn
+++ b/examples/all-clusters-app/linux/BUILD.gn
@@ -30,6 +30,7 @@
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-controls-delegate-impl.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/laundry-washer-mode.cpp",
+    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/microwave-oven-mode.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/operational-state-delegate-impl.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/resource-monitoring-delegates.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/rvc-modes.cpp",
diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp
index b477555..004827d 100644
--- a/examples/all-clusters-app/linux/main-common.cpp
+++ b/examples/all-clusters-app/linux/main-common.cpp
@@ -23,6 +23,7 @@
 #include "include/tv-callbacks.h"
 #include "laundry-washer-controls-delegate-impl.h"
 #include "laundry-washer-mode.h"
+#include "microwave-oven-mode.h"
 #include "operational-state-delegate-impl.h"
 #include "resource-monitoring-delegates.h"
 #include "rvc-modes.h"
@@ -226,6 +227,7 @@
     Clusters::LaundryWasherMode::Shutdown();
     Clusters::RvcCleanMode::Shutdown();
     Clusters::RvcRunMode::Shutdown();
+    Clusters::MicrowaveOvenMode::Shutdown();
     Clusters::RefrigeratorAndTemperatureControlledCabinetMode::Shutdown();
     Clusters::HepaFilterMonitoring::Shutdown();
     Clusters::ActivatedCarbonFilterMonitoring::Shutdown();
diff --git a/src/app/clusters/mode-base-server/mode-base-server.cpp b/src/app/clusters/mode-base-server/mode-base-server.cpp
index 2b9cc23..2a86f1e 100644
--- a/src/app/clusters/mode-base-server/mode-base-server.cpp
+++ b/src/app/clusters/mode-base-server/mode-base-server.cpp
@@ -51,6 +51,15 @@
 
 Instance::~Instance()
 {
+    Shutdown();
+}
+
+void Instance::Shutdown()
+{
+    if (!IsInList())
+    {
+        return;
+    }
     UnregisterThisInstance();
     chip::app::InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this);
     unregisterAttributeAccessOverride(this);
@@ -289,21 +298,6 @@
     }
 }
 
-// List the commands supported by this instance.
-CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster,
-                                               CommandHandlerInterface::CommandIdCallback callback, void * context)
-{
-    callback(ModeBase::Commands::ChangeToMode::Id, context);
-    return CHIP_NO_ERROR;
-}
-
-// List the commands generated by this instance.
-CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)
-{
-    callback(ModeBase::Commands::ChangeToModeResponse::Id, context);
-    return CHIP_NO_ERROR;
-}
-
 // Implements the read functionality for complex attributes.
 CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
 {
diff --git a/src/app/clusters/mode-base-server/mode-base-server.h b/src/app/clusters/mode-base-server/mode-base-server.h
index ef88ee8..256670d 100644
--- a/src/app/clusters/mode-base-server/mode-base-server.h
+++ b/src/app/clusters/mode-base-server/mode-base-server.h
@@ -121,6 +121,9 @@
      */
     bool IsSupportedMode(uint8_t mode);
 
+    // Unregisters this instance if already registered.
+    void Shutdown();
+
 private:
     Delegate * mDelegate;
 
@@ -139,8 +142,6 @@
 
     // CommandHandlerInterface
     void InvokeCommand(HandlerContext & ctx) override;
-    CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
-    CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override;
 
     // AttributeAccessInterface
     CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp
index 1add789..9d618dc 100644
--- a/src/app/util/util.cpp
+++ b/src/app/util/util.cpp
@@ -160,6 +160,7 @@
 void MatterDishwasherAlarmPluginServerInitCallback() {}
 void MatterBooleanSensorConfigurationPluginServerInitCallback() {}
 void MatterValveConfigurationAndControlPluginServerInitCallback() {}
+void MatterMicrowaveOvenModePluginServerInitCallback() {}
 // ****************************************
 // Print out information about each cluster
 // ****************************************