-- 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 class = require 'mc.class'
local singleton = require 'mc.singleton'
local client = require 'pcie_device.client'
local log = require 'mc.logging'

local FRUCTRL_ITF<const> = 'bmc.kepler.Systems.FruCtrl'
local POWER_STATE_PROPERTY<const> = 'PowerState'

local common_interface = class()

function common_interface:ctor(bus)
    self.update_power_status_callbacks = {}
    self.power_status = {}
    self.bus = bus
end

function common_interface:init()
    pcall(function()
        self:listen_and_update_power_status()
    end)
end

function common_interface:register_update_power_status(cb, obj)
    table.insert(self.update_power_status_callbacks, {
        callback = cb,
        obj = obj
    })
    
end

function common_interface:listen_and_update_power_status()
    client:OnFruCtrlPropertiesChanged(function(values, path, interface)
        if interface ~= FRUCTRL_ITF then
            log:debug('[pcie_device] monitor power state: interface(%s) mismatch', interface)
            return
        end
        -- 更新电源状态
        local system_id = tonumber(string.match(path or '', 'bmc/kepler/Systems/(%d+)/FruCtrl'))
        if system_id then
            self.power_status[system_id] = values[POWER_STATE_PROPERTY]:value()
            log:notice('[pcie_device] system %s power state is %s', system_id, self.power_status[system_id])
            for _, callback_obj in pairs(self.update_power_status_callbacks) do
                callback_obj.callback(callback_obj.obj, system_id, self.power_status[system_id])
            end
        end
    end)
    -- BMC重启场景，对象概率性还没上树导致 获取一次电源状态 失败，并且后续电源状态可能不会再发生变化，需要监听接口变更
    client:OnFruCtrlInterfacesAdded(function(_, path, obj)
        local system_id = tonumber(string.match(path or '', 'bmc/kepler/Systems/(%d+)/FruCtrl'))
        if system_id and obj then
            self.power_status[system_id] = obj[POWER_STATE_PROPERTY]:value()
            log:notice('[pcie_device] system %s power state is %s', system_id, self.power_status[system_id])
        end
    end)
    -- 先获取一次电源状态
    client:ForeachFruCtrlObjects(function(obj)
        local system_id = tonumber(string.match(obj.path or '', 'bmc/kepler/Systems/(%d+)/FruCtrl'))
        if system_id then
            self.power_status[system_id] = obj[POWER_STATE_PROPERTY]
            log:notice('[pcie_device] system %s power state is %s', system_id, self.power_status[system_id])
        end
    end)
end

return singleton(common_interface)