-- 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 log = require 'mc.logging'
local cmn = require 'common'
local client = require 'general_hardware.client'

---@class Card @组件
---@field private mds_obj table @MDS组件对象
local c_card = class()

local UNAVAILABLE<const> = 'N/A'
local DEFAULT_INTERFACE<const> = 'bmc.kepler.Systems.Board'

function c_card:destroy()
end

-- 从硬件读取MCU版本并更新本地的资源树属性
function c_card:task_update_mcu_version()
    if self:get_prop('MCUVersion') == UNAVAILABLE then
        return
    end
    cmn.skynet.fork(function()
        local mcu_version = ''
        local timeout = 120
        repeat
            if self.mcu_obj then
                mcu_version = self.mcu_obj:get_mcu_version()
                self:set_prop('MCUVersion', mcu_version)
            end
            cmn.skynet.sleep(100)
            timeout = timeout - 1
        until mcu_version ~= '' or timeout < 0
    end)
end

local function match_firmware_path(path, position)
    local str = path:match('.*/(.*)')
    local index = string.find(str, '_') -- 查找第一个_的位置
    if not index or string.sub(str, 1, index - 1) ~= 'MCU' then
        return false
    end
    index = path:find('_[^_]*$') -- 查找最后一个_的位置
    return path:sub(index + 1) == position
end

-- 监听对应firmware上version属性的变化
function c_card:listen_firmware_version_changed()
    client:OnFirmwareInfoPropertiesChanged(function(values, path, interface)
        log:info('===== general_hardware listen firmware version %s =======', interface)
        if match_firmware_path(path, self.position) then
            if not values['Version'] then
                return
            end
            self:set_prop('MCUVersion', values['Version']:value())
        end
    end)
end

function c_card:set_ref_mcu_obj(obj)
    self.mcu_obj = obj
end

function  c_card:get_prop(name, interface)
    if not self.mds_obj then
        return nil
    end

    if interface then
        return self.mds_obj[interface][name]
    elseif self.mds_obj[name] then
        return self.mds_obj[name]
    else
        return self.mds_obj[DEFAULT_INTERFACE][name]
    end
end

function c_card:set_prop(name, val, interface)
    if not self.mds_obj then
        return nil
    end
 
    if interface then
        self.mds_obj[interface][name] = val
    elseif self.mds_obj[name] then
        self.mds_obj[name] = val
    else
        self.mds_obj[DEFAULT_INTERFACE][name] = val
    end
end

function c_card:ctor(bus, mds_obj, position)
    self.bus = bus
    self.mds_obj = mds_obj
    self.position = position
end

function c_card:init()
    self:listen_firmware_version_changed()
end

return c_card