-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--          http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.
local mdb = require 'mc.mdb'
local class = require 'mc.class'
local app_base = require 'mc.client_app_base'
local mdb_service = require 'mc.mdb.mdb_service'
local subscribe_signal = require 'mc.mdb.subscribe_signal'
local org_freedesktop_dbus = require 'sd_bus.org_freedesktop_dbus'

local match_rule = org_freedesktop_dbus.MatchRule
local get_non_virtual_interface_objects = mdb_service.get_non_virtual_interface_objects
local foreach_non_virtual_interface_objects = mdb_service.foreach_non_virtual_interface_objects

local Accessor = require 'chassis.json_types.Accessor'
local Events = require 'chassis.json_types.Events'
local Processor = require 'chassis.json_types.Processor'
local Memory = require 'chassis.json_types.Memory'
local OnePower = require 'chassis.json_types.OnePower'
local Status = require 'chassis.json_types.Status'
local Fan = require 'chassis.json_types.Fan'
local Connector = require 'chassis.json_types.Connector'
local Drive = require 'chassis.json_types.Drive'
local DriveStatus = require 'chassis.json_types.DriveStatus'
local Overview = require 'chassis.json_types.Overview'
local System = require 'chassis.json_types.System'
local Board = require 'chassis.json_types.Board'
local ThresholdSensor = require 'chassis.json_types.ThresholdSensor'
local ThresholdSensorDisplay = require 'chassis.json_types.ThresholdSensorDisplay'
local FruCtrl = require 'chassis.json_types.FruCtrl'
local Sensors = require 'chassis.json_types.Sensors'

---@class chassis_client: BasicClient
local chassis_client = class(app_base.Client)

function chassis_client:GetAccessorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Accessor', true)
end

function chassis_client:ForeachAccessorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Accessor', cb, true)
end

function chassis_client:GetProcessorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor', true)
end

function chassis_client:ForeachProcessorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Processor', cb, true)
end

function chassis_client:GetMemoryObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Memory', true)
end

function chassis_client:ForeachMemoryObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Memory', cb, true)
end

function chassis_client:GetOnePowerObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PowerMgmt.OnePower', true)
end

function chassis_client:ForeachOnePowerObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PowerMgmt.OnePower', cb, true)
end

function chassis_client:GetStatusObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PowerMgmt.OnePower.Status', true)
end

function chassis_client:ForeachStatusObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PowerMgmt.OnePower.Status', cb,
        true)
end

function chassis_client:GetFanObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Fan', false)
end

function chassis_client:ForeachFanObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Fan', cb, false)
end

function chassis_client:GetConnectorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Connector', true)
end

function chassis_client:ForeachConnectorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Connector', cb, true)
end

function chassis_client:GetDriveObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Storage.Drive', true)
end

function chassis_client:ForeachDriveObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Storage.Drive', cb, true)
end

function chassis_client:GetDriveStatusObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Storage.Drive.DriveStatus', false)
end

function chassis_client:ForeachDriveStatusObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Storage.Drive.DriveStatus', cb,
        false)
end

function chassis_client:GetOverviewObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.Overview', true)
end

function chassis_client:ForeachOverviewObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.Overview', cb, true)
end

function chassis_client:GetSystemObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.System', true)
end

function chassis_client:ForeachSystemObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.System', cb, true)
end

function chassis_client:GetBoardObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.Board', true)
end

function chassis_client:ForeachBoardObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruData.Board', cb, true)
end

function chassis_client:GetThresholdSensorObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.ThresholdSensor', true)
end

function chassis_client:ForeachThresholdSensorObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.ThresholdSensor', cb, true)
end

function chassis_client:GetThresholdSensorDisplayObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.ThresholdSensorDisplay', true)
end

function chassis_client:ForeachThresholdSensorDisplayObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.ThresholdSensorDisplay', cb, true)
end

function chassis_client:GetFruCtrlObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruCtrl', true)
end

function chassis_client:ForeachFruCtrlObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.FruCtrl', cb, true)
end

function chassis_client:GetSensorsObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chassis.Sensors', true)
end

function chassis_client:ForeachSensorsObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chassis.Sensors', cb, true)
end

function chassis_client:OnAccessorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Accessor')
end

function chassis_client:OnAccessorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Accessor')
end

function chassis_client:GetEventsEventsObject(path_params)
    return mdb.try_get_object(self:get_bus(),
        path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
            '/bmc/kepler/Systems/:SystemId/Events', 'bmc.kepler.Systems.Events')
end

function chassis_client:GetEventsObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', true,
        {'/bmc/kepler/Systems/:SystemId/Events'})
end

function chassis_client:ForeachEventsObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', cb, true,
        {'/bmc/kepler/Systems/:SystemId/Events'})
end

function chassis_client:OnEventsPropertiesChanged(cb, path_params)
    local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
                               '/bmc/kepler/Systems/:SystemId/Events'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.Systems.Events', {'Health', 'MinorCount', 'MajorCount', 'CriticalCount'})
end

function chassis_client:OnEventsInterfacesAdded(cb, path_params)
    local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
                               '/bmc/kepler/Systems/:SystemId/Events'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), path_namespace, cb,
        'bmc.kepler.Systems.Events')
end

function chassis_client:OnEventsInterfacesRemoved(cb, path_params)
    local path_namespace = path_params and ('/bmc/kepler/Systems/' .. path_params['SystemId'] .. '/Events') or
                               '/bmc/kepler/Systems/:SystemId/Events'
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), path_namespace,
        cb, 'bmc.kepler.Systems.Events')
end

function chassis_client:OnProcessorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor')
end

function chassis_client:OnProcessorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Processor')
end

function chassis_client:OnMemoryInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Memory')
end

function chassis_client:OnMemoryInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Memory')
end

function chassis_client:OnOnePowerInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PowerMgmt.OnePower')
end

function chassis_client:OnOnePowerInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PowerMgmt.OnePower')
end

function chassis_client:OnStatusInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PowerMgmt.OnePower.Status')
end

function chassis_client:OnStatusInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PowerMgmt.OnePower.Status')
end

function chassis_client:OnFanInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Fan')
end

function chassis_client:OnFanInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Fan')
end

function chassis_client:OnConnectorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Connector')
end

function chassis_client:OnConnectorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Connector')
end

function chassis_client:OnDriveInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Storage.Drive')
end

function chassis_client:OnDriveInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Storage.Drive')
end

function chassis_client:OnDriveStatusInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Storage.Drive.DriveStatus')
end

function chassis_client:OnDriveStatusInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Storage.Drive.DriveStatus')
end

function chassis_client:OnOverviewInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.Overview')
end

function chassis_client:OnOverviewInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.Overview')
end

function chassis_client:OnSystemInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.System')
end

function chassis_client:OnSystemInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.System')
end

function chassis_client:OnBoardInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.Board')
end

function chassis_client:OnBoardInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruData.Board')
end

function chassis_client:OnThresholdSensorInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.ThresholdSensor')
end

function chassis_client:OnThresholdSensorInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.ThresholdSensor')
end

function chassis_client:OnThresholdSensorDisplayInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.ThresholdSensorDisplay')
end

function chassis_client:OnThresholdSensorDisplayInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.ThresholdSensorDisplay')
end

function chassis_client:OnFruCtrlInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruCtrl')
end

function chassis_client:OnFruCtrlInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.FruCtrl')
end

function chassis_client:OnSensorsPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chassis.Sensors')
end

function chassis_client:OnSensorsInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chassis.Sensors')
end

function chassis_client:OnSensorsInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chassis.Sensors')
end

---@param EventCode string
---@param Enabled integer
---@param ObjectIndex integer
---@param MockState integer
---@return Events.MockEventRsp
function chassis_client:EventsEventsMockEvent(ctx, path_params, EventCode, Enabled, ObjectIndex, MockState)
    local req = Events.MockEventReq.new(EventCode, Enabled, ObjectIndex, MockState):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.MockEventRsp.new(obj:MockEvent(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsMockEvent(ctx, path_params, EventCode, Enabled, ObjectIndex, MockState)
    return pcall(function()
        local req = Events.MockEventReq.new(EventCode, Enabled, ObjectIndex, MockState):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.MockEventRsp.new(obj:MockEvent(ctx, req:unpack(true)))
    end)
end

---@param StartId integer
---@param Count integer
---@param QueryParameters Events.KeyValueTable[]
---@return Events.GetAlarmListRsp
function chassis_client:EventsEventsGetAlarmList(ctx, path_params, StartId, Count, QueryParameters)
    local req = Events.GetAlarmListReq.new(StartId, Count, QueryParameters):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetAlarmListRsp.new(obj:GetAlarmList(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsGetAlarmList(ctx, path_params, StartId, Count, QueryParameters)
    return pcall(function()
        local req = Events.GetAlarmListReq.new(StartId, Count, QueryParameters):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetAlarmListRsp.new(obj:GetAlarmList(ctx, req:unpack(true)))
    end)
end

---@param StartId integer
---@param Count integer
---@param QueryParameters Events.KeyValueTable[]
---@return Events.GetEventListRsp
function chassis_client:EventsEventsGetEventList(ctx, path_params, StartId, Count, QueryParameters)
    local req = Events.GetEventListReq.new(StartId, Count, QueryParameters):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetEventListRsp.new(obj:GetEventList(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsGetEventList(ctx, path_params, StartId, Count, QueryParameters)
    return pcall(function()
        local req = Events.GetEventListReq.new(StartId, Count, QueryParameters):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetEventListRsp.new(obj:GetEventList(ctx, req:unpack(true)))
    end)
end

---@return Events.ClearEventListRsp
function chassis_client:EventsEventsClearEventList(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.ClearEventListRsp.new(obj:ClearEventList(ctx))
end

function chassis_client:PEventsEventsClearEventList(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.ClearEventListRsp.new(obj:ClearEventList(ctx))
    end)
end

---@return Events.GetEventInfoRsp
function chassis_client:EventsEventsGetEventInfo(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetEventInfoRsp.new(obj:GetEventInfo(ctx))
end

function chassis_client:PEventsEventsGetEventInfo(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetEventInfoRsp.new(obj:GetEventInfo(ctx))
    end)
end

---@param EventCode string
---@param MaskState integer
---@param Mode integer
---@return Events.MaskEventRsp
function chassis_client:EventsEventsMaskEvent(ctx, path_params, EventCode, MaskState, Mode)
    local req = Events.MaskEventReq.new(EventCode, MaskState, Mode):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.MaskEventRsp.new(obj:MaskEvent(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsMaskEvent(ctx, path_params, EventCode, MaskState, Mode)
    return pcall(function()
        local req = Events.MaskEventReq.new(EventCode, MaskState, Mode):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.MaskEventRsp.new(obj:MaskEvent(ctx, req:unpack(true)))
    end)
end

---@return Events.GetMaskedEventListRsp
function chassis_client:EventsEventsGetMaskedEventList(ctx, path_params)
    local obj = self:GetEventsEventsObject(path_params)

    return Events.GetMaskedEventListRsp.new(obj:GetMaskedEventList(ctx))
end

function chassis_client:PEventsEventsGetMaskedEventList(ctx, path_params)
    return pcall(function()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.GetMaskedEventListRsp.new(obj:GetMaskedEventList(ctx))
    end)
end

---@param EventInfo Events.KeyValueTable[]
---@return Events.AddEventRsp
function chassis_client:EventsEventsAddEvent(ctx, path_params, EventInfo)
    local req = Events.AddEventReq.new(EventInfo):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.AddEventRsp.new(obj:AddEvent(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsAddEvent(ctx, path_params, EventInfo)
    return pcall(function()
        local req = Events.AddEventReq.new(EventInfo):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.AddEventRsp.new(obj:AddEvent(ctx, req:unpack(true)))
    end)
end

---@param Path string
---@return Events.ExportEventRsp
function chassis_client:EventsEventsExportEvent(ctx, path_params, Path)
    local req = Events.ExportEventReq.new(Path):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.ExportEventRsp.new(obj:ExportEvent(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsExportEvent(ctx, path_params, Path)
    return pcall(function()
        local req = Events.ExportEventReq.new(Path):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.ExportEventRsp.new(obj:ExportEvent(ctx, req:unpack(true)))
    end)
end

---@param EventName string[]
---@return Events.CheckEventNameRsp
function chassis_client:EventsEventsCheckEventName(ctx, path_params, EventName)
    local req = Events.CheckEventNameReq.new(EventName):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.CheckEventNameRsp.new(obj:CheckEventName(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsCheckEventName(ctx, path_params, EventName)
    return pcall(function()
        local req = Events.CheckEventNameReq.new(EventName):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.CheckEventNameRsp.new(obj:CheckEventName(ctx, req:unpack(true)))
    end)
end

---@param AlarmName string
---@return Events.SetAlarmNameRsp
function chassis_client:EventsEventsSetAlarmName(ctx, path_params, AlarmName)
    local req = Events.SetAlarmNameReq.new(AlarmName):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetAlarmNameRsp.new(obj:SetAlarmName(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsSetAlarmName(ctx, path_params, AlarmName)
    return pcall(function()
        local req = Events.SetAlarmNameReq.new(AlarmName):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetAlarmNameRsp.new(obj:SetAlarmName(ctx, req:unpack(true)))
    end)
end

---@param EventCode string
---@param Severity integer
---@return Events.SetEventSeverityRsp
function chassis_client:EventsEventsSetEventSeverity(ctx, path_params, EventCode, Severity)
    local req = Events.SetEventSeverityReq.new(EventCode, Severity):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetEventSeverityRsp.new(obj:SetEventSeverity(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsSetEventSeverity(ctx, path_params, EventCode, Severity)
    return pcall(function()
        local req = Events.SetEventSeverityReq.new(EventCode, Severity):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetEventSeverityRsp.new(obj:SetEventSeverity(ctx, req:unpack(true)))
    end)
end

---@param EventKeyId string
---@param Action integer
---@return Events.SetEventActionRsp
function chassis_client:EventsEventsSetEventAction(ctx, path_params, EventKeyId, Action)
    local req = Events.SetEventActionReq.new(EventKeyId, Action):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.SetEventActionRsp.new(obj:SetEventAction(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsSetEventAction(ctx, path_params, EventKeyId, Action)
    return pcall(function()
        local req = Events.SetEventActionReq.new(EventKeyId, Action):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.SetEventActionRsp.new(obj:SetEventAction(ctx, req:unpack(true)))
    end)
end

---@param EventInfo Events.KeyValueTable[]
---@return Events.AddSelRsp
function chassis_client:EventsEventsAddSel(ctx, path_params, EventInfo)
    local req = Events.AddSelReq.new(EventInfo):validate()
    local obj = self:GetEventsEventsObject(path_params)

    return Events.AddSelRsp.new(obj:AddSel(ctx, req:unpack(true)))
end

function chassis_client:PEventsEventsAddSel(ctx, path_params, EventInfo)
    return pcall(function()
        local req = Events.AddSelReq.new(EventInfo):validate()
        local obj = self:GetEventsEventsObject(path_params)

        return Events.AddSelRsp.new(obj:AddSel(ctx, req:unpack(true)))
    end)
end

function chassis_client:SubscribeFruCtrlBeforePowerOnSignal(cb)
    local sig = match_rule.signal('BeforePowerOnSignal', 'bmc.kepler.Systems.FruCtrl')
    self.signal_slots[#self.signal_slots + 1] = self:get_bus():match(sig, function(msg)
        cb(msg:read())
    end)
end

function chassis_client:ctor()
    self.signal_slots = {}
end

---@type chassis_client
return chassis_client.new('chassis')
