-- 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 log = require 'mc.logging'
local c_object_manage = require 'mc.orm.object_manage'
local client = require 'network_adapter.client'
local c_optical_module = require 'device.class.optical_module'
local card_update_identifier = require 'device.class.nic_mgmt.card.card_update_identifier'

local card_listen_callback = {}

-- 由于现在光模块告警关联在网卡的health下，需要把网卡的health同步到光模块的health
local function update_op_health(orm_obj, _, value)
    local ops = c_optical_module.collection:fetch({NetworkAdapterId = orm_obj.NodeId})
    for _, op in ipairs(ops) do
        op:update_health(value)
    end
end

local function synchronize_port_bdf(orm_obj, key, value)
    log:notice('synchronize port bdf, name:%s, key:%s, value:%s', orm_obj.NodeId, key, value)
    -- 除NIC卡外，其他网卡DevBus不为0
    if value == 0 and key == 'DevBus' and orm_obj.Type ~= 1 then
        log:notice('synchronize port bdf fail, name:%s, DevBus is 0', orm_obj.NodeId)
        return
    end

    if value == 0 and key == 'Bus' and orm_obj.Type == 1 then
        log:notice('synchronize port bdf fail, name:%s, Bus is 0', orm_obj.NodeId)
        return
    end

    local ports = orm_obj.children
    table.sort(ports, function(a, b)
        return a.PortID < b.PortID
    end)
    if orm_obj.SpecialPcieCard then
        orm_obj:next_tick(card_update_identifier.update_1822_port_bdf, ports, orm_obj)
    else
        orm_obj:next_tick(card_update_identifier.update_port_bdf, ports, orm_obj)
    end
end

local function synchronize_port_node_id(orm_obj, _, value)
    local ports = orm_obj.children
    for _, port in pairs(ports) do
        port.NetworkAdapterId = value
    end
end

function card_listen_callback.register_listen_callback(orm_obj)
    local switch = {
        Health = update_op_health,
        DevBus = synchronize_port_bdf,
        NodeId = synchronize_port_node_id,
        Bus = synchronize_port_bdf
    }
    orm_obj:connect_signal(orm_obj.on_property_changed, function(name, value)
        if switch[name] then
            switch[name](orm_obj, name, value)
        end
    end)

    local bus = c_object_manage.get_instance().bus
    if not bus then
        log:error(
            '[network_adapter]register listen callback: get bus failed, listen smbios status failed.')
        return
    end

    client:OnSmBiosInterfacesAdded(function (_, _, props)
        orm_obj.smbios_status = props.SmBiosStatus:value()
        log:debug('updtate smbios_status=%s', orm_obj.smbios_status)
    end)

    client:OnSmBiosPropertiesChanged(function (values, _, _)
        if not values.SmBiosStatus then
            return
        end
        orm_obj.smbios_status = values.SmBiosStatus:value()
        log:debug('updtate smbios_status=%s', orm_obj.smbios_status)
    end)
end

return card_listen_callback