-- Copyright (c) 2026 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 c_object = require 'mc.orm.object'
local log = require 'mc.logging'
local skynet = require 'skynet'
local c_network_adapter = require 'device.class.network_adapter'
local comm_fun = require 'device.class.nic_mgmt.comm_fun'
local comm_defs = require 'device.class.nic_mgmt.comm_defs'
local c_object_manage = require 'mc.orm.object_manage'

local c_network_adapter_preload = c_object('NetworkAdapterPreload')

function c_network_adapter_preload:ctor()
end

function c_network_adapter_preload:init()
    log:notice('add network adapter preload object, node id = %s, port count = %s',
        self.NodeId, self.PortCount)
    c_network_adapter_preload.super.init(self)
    if not self.PortCount then
        log:error('network adapter preload object init failed, port count is nil, node id = %s', self.NodeId)
        return
    end
    local ref_connector_name = string.format('Ref%dPortConnector', self.PortCount)
    if not self[ref_connector_name] then
        log:error('network adapter preload object init failed, %s is nil, node id: %s', ref_connector_name, self.NodeId)
        return
    end
    self[ref_connector_name].Presence = 1
    log:notice('set %s presence to 1 successfully, node id: %s', ref_connector_name, self.NodeId)
end

function c_network_adapter_preload:set_port_count(port_count)
    log:notice('%s set preload port count to %s', self.NodeId, port_count)
    local card_orm_obj = c_network_adapter.collection:find({NodeId = self.NodeId})
    if not card_orm_obj then
        log:error('%s set preload port count failed, network adapter orm object not found', self.NodeId)
        return false
    end

    local bus = c_object_manage.get_instance().bus
    local card_device_obj = comm_fun.get_device_obj_by_path_interface(bus, card_orm_obj.device_path,
        comm_defs.NETWORK_ADAPTER_OEM_INTERFACE)
    if not card_device_obj then
        log:error('%s set preload port count failed, network adapter device object not found', self.NodeId)
        return false
    end

    local ok = card_device_obj:call_method('SetPreloadPortCount', 'y', port_count)
    if not ok then
        log:error('%s set preload port count failed, network adapter device object call method failed', self.NodeId)
        return false
    end

    local old_ref_connector_name = string.format('Ref%dPortConnector', self.PortCount)
    if not self[old_ref_connector_name] then
        log:error('%s set preload port count failed, %s is nil, node id: %s', old_ref_connector_name, self.NodeId)
        return false
    end
    local new_ref_connector_name = string.format('Ref%dPortConnector', port_count)
    if not self[new_ref_connector_name] then
        log:error('%s set preload port count failed, %s is nil, node id: %s', new_ref_connector_name, self.NodeId)
        return false
    end
    skynet.fork_once(function ()
        -- 休眠0.5s，保证redfish接口patch后的get操作能获取到网卡对象，如果直接卸载网卡对象，会导致get查询不到信息
        skynet.sleep(50)
        -- 先设置老Connector为0卸载掉老的CSR对象，再休眠1s，设置新Connector为1加载新的CSR对象，避免卸载和加载同时进行时产生网卡主键冲突问题
        self[old_ref_connector_name].Presence = 0
        log:notice('set old %s presence to 0 successfully, node id: %s', old_ref_connector_name, self.NodeId)
        skynet.sleep(100)
        self[new_ref_connector_name].Presence = 1
        log:notice('set new %s presence to 1 successfully, node id: %s', new_ref_connector_name, self.NodeId)
    end)

    self.PortCount = port_count
    log:notice('%s set preload port count to %s successfully', self.NodeId, port_count)
    return true
end

return c_network_adapter_preload
