-- Copyright (c) 2024 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 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 BlockIO = require 'storage.json_types.BlockIO'
local Accessor = require 'storage.json_types.Accessor'
local PCIeDevice = require 'storage.json_types.PCIeDevice'
local PCIeCard = require 'storage.json_types.PCIeCard'
local PCIe = require 'storage.json_types.PCIe'
local PCIeEndpoint = require 'storage.json_types.PCIeEndpoint'
local PCIeTransport = require 'storage.json_types.PCIeTransport'
local PCIeRoutingEntry = require 'storage.json_types.PCIeRoutingEntry'
local Events = require 'storage.json_types.Events'
local FruCtrl = require 'storage.json_types.FruCtrl'
local SmBios = require 'storage.json_types.SmBios'
local Bios = require 'storage.json_types.Bios'
local PcieAddrInfo = require 'storage.json_types.PcieAddrInfo'
local Component = require 'storage.json_types.Component'
local SmsStatus = require 'storage.json_types.SmsStatus'
local Sms = require 'storage.json_types.Sms'
local Connector = require 'storage.json_types.Connector'
local Board = require 'storage.json_types.Board'

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

function storage_client:GetBlockIOObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chip.BlockIO', true)
end

function storage_client:ForeachBlockIOObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Chip.BlockIO', cb, true)
end

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

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

function storage_client:GetPCIeDeviceObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PCIeDevices.PCIeDevice', true)
end

function storage_client:ForeachPCIeDeviceObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PCIeDevices.PCIeDevice', cb, true)
end

function storage_client:GetPCIeCardObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PCIeDevices.PCIeCard', true)
end

function storage_client:ForeachPCIeCardObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PCIeDevices.PCIeCard', cb, true)
end

function storage_client:GetPCIeObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.MctpBinding.PCIe', true)
end

function storage_client:ForeachPCIeObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.MctpBinding.PCIe', cb, true)
end

function storage_client:GetPCIeEndpointObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeEndpoint', true)
end

function storage_client:ForeachPCIeEndpointObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeEndpoint', cb, true)
end

function storage_client:GetPCIeTransportObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeTransport', true)
end

function storage_client:ForeachPCIeTransportObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeTransport', cb, true)
end

function storage_client:GetPCIeRoutingEntryObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeRoutingEntry', true)
end

function storage_client:ForeachPCIeRoutingEntryObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Mctp.PCIeRoutingEntry', cb, true)
end

function storage_client:GetEventsObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', true)
end

function storage_client:ForeachEventsObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Events', cb, true)
end

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

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

function storage_client:GetSmBiosObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.SmBios', true)
end

function storage_client:ForeachSmBiosObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.SmBios', cb, true)
end

function storage_client:GetBiosObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Bios', true)
end

function storage_client:ForeachBiosObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Bios', cb, true)
end

function storage_client:GetPcieAddrInfoObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PcieAddrInfo', true)
end

function storage_client:ForeachPcieAddrInfoObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.PcieAddrInfo', cb, true)
end

function storage_client:GetComponentObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Component', true)
end

function storage_client:ForeachComponentObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Component', cb, true)
end

function storage_client:GetSmsStatusObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Sms.SmsStatus', true)
end

function storage_client:ForeachSmsStatusObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Sms.SmsStatus', cb, true)
end

function storage_client:GetSmsObjects()
    return get_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Sms', true)
end

function storage_client:ForeachSmsObjects(cb)
    return foreach_non_virtual_interface_objects(self:get_bus(), 'bmc.kepler.Systems.Sms', cb, true)
end

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

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

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

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

function storage_client:OnBlockIOInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chip.BlockIO')
end

function storage_client:OnBlockIOInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Chip.BlockIO')
end

function storage_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 storage_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 storage_client:OnPCIeDeviceInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PCIeDevices.PCIeDevice')
end

function storage_client:OnPCIeDeviceInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PCIeDevices.PCIeDevice')
end

function storage_client:OnPCIeCardPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PCIeDevices.PCIeCard', {'PcbVersion'})
end

function storage_client:OnPCIeCardInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PCIeDevices.PCIeCard')
end

function storage_client:OnPCIeCardInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.PCIeDevices.PCIeCard')
end

function storage_client:OnPCIeInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.MctpBinding.PCIe')
end

function storage_client:OnPCIeInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.MctpBinding.PCIe')
end

function storage_client:OnPCIeEndpointInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeEndpoint')
end

function storage_client:OnPCIeEndpointInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeEndpoint')
end

function storage_client:OnPCIeTransportInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeTransport')
end

function storage_client:OnPCIeTransportInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeTransport')
end

function storage_client:OnPCIeRoutingEntryInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeRoutingEntry')
end

function storage_client:OnPCIeRoutingEntryInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Mctp.PCIeRoutingEntry')
end

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

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

function storage_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 storage_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 storage_client:OnSmBiosInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.SmBios')
end

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

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

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

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

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

function storage_client:OnComponentPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Component', {'ReplaceFlag'})
end

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

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

function storage_client:OnSmsStatusPropertiesChanged(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_properties_changed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Sms.SmsStatus', {'State'})
end

function storage_client:OnSmsStatusInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Sms.SmsStatus')
end

function storage_client:OnSmsStatusInterfacesRemoved(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_removed(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Sms.SmsStatus')
end

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

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

function storage_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 storage_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 storage_client:OnBoardInterfacesAdded(cb)
    self.signal_slots[#self.signal_slots + 1] = subscribe_signal.on_interfaces_added(self:get_bus(), '/bmc', cb,
        'bmc.kepler.Systems.Board')
end

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

function storage_client:SubscribePCIeEndpointOnMessage(cb)
    local sig = match_rule.signal('OnMessage', 'bmc.kepler.Systems.Mctp.PCIeEndpoint')
    self.signal_slots[#self.signal_slots + 1] = self:get_bus():match(sig, function(msg)
        cb(msg:read())
    end)
end

function storage_client:SubscribePCIeEndpointMessageReceived(cb)
    local sig = match_rule.signal('MessageReceived', 'bmc.kepler.Systems.Mctp.PCIeEndpoint')
    self.signal_slots[#self.signal_slots + 1] = self:get_bus():match(sig, function(msg)
        cb(msg:read())
    end)
end

function storage_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 storage_client:ctor()
    self.signal_slots = {}
end

---@type storage_client
return storage_client.new('storage')
