-- 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 singleton = require 'mc.singleton'
local log = require 'mc.logging'
local c_nic = require 'card_manager.class.nic.nic'
local c_pcie = require 'card_manager.class.pcie.pcie'
local cmn = require 'common'

local card_manager = {}
card_manager.__index = card_manager

function card_manager:on_add_object(class_name, object, position)
    local switch = {
        ['BoardNICCard'] = function ()
            local obj = c_nic.new(self.bus, object, position)
            self:task_set_ref_mcu_obj(obj)
            obj:task_update()
            self.niccards[position] = obj
        end,
        ['BoardPCIeCard'] = function ()
            local obj = c_pcie.new(self.bus, object, position)
            self.pciecards[position] = obj
        end
    }

    if switch[class_name] then
        switch[class_name]()
        log:notice('[CardManager] Add object, class: %s, position: %s', class_name, position)
    end
end

function card_manager:on_delete_object(class_name, object, position)
    local switch = {
        ['BoardNICCard'] = function ()
            self.niccards[position] = nil
        end,
        ['BoardPCIeCard'] = function ()
            self.pciecards[position] = nil
        end
    }

    if switch[class_name] then
        switch[class_name]()
        log:notice('[CardManager] Delete object, class: %s, position: %s', class_name, position)
    end
end

-- 关联对应的MCU升级对象
function card_manager:task_set_ref_mcu_obj(obj)
    cmn.skynet.fork(function ()
        local mcu_obj = nil
        local time_out = 60
        local mcu_service
        repeat
            mcu_service = self.service_manager:get_service('mcu')
            mcu_obj = mcu_service:get_obj_by_position(obj.position)
            if mcu_obj then
                obj:set_ref_mcu_obj(mcu_obj)
            end
            time_out = time_out - 1
            cmn.skynet.sleep(200)
        until mcu_obj or time_out < 0
    end)
end

function card_manager:get_device_name(position)
    if not position then
        return
    end
    local device_name
    local nic_card = self.niccards[position]
    local retries = 0
    repeat
        if not nic_card or not nic_card:get_prop('DeviceName') or nic_card:get_prop('DeviceName') == "" then
            nic_card = self.niccards[position]
            retries = retries + 1
            cmn.skynet.sleep(200)
        else
            device_name = nic_card:get_prop('DeviceName')
        end
    until device_name or retries > 30 -- 防止固件加载比板卡快导致获取不到信息
    log:notice('[FW_Manager]get %s,position: %s ,retry: %s', device_name, position, retries)
    return device_name
end

function card_manager.new(service_manager)
    return setmetatable({service_manager = service_manager}, card_manager)
end

function card_manager:init(bus)
    self.bus = bus
    self.niccards = {}
    self.pciecards = {}
    log:info('[card_manager] init finished.')
end

return singleton(card_manager)