-- 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 card_comm = {}

local BUSINESSPORT_CARD_TYPE_VIR<const> = 6
local BUSINESSPORT_CARD_TYPE_TEAM<const> = 7
local BUSINESSPORT_CARD_TYPE_BRIDGE<const> = 8

local t_resource = {
    [0] = 'CPU1',
    [1] = 'CPU2',
    [2] = 'CPU3',
    [3] = 'CPU4',
    [251] = 'CPU1,CPU2,CPU3,CPU4',
    [253] = 'CPU1,CPU2',
    [254] = 'PCH',
    [255] = 'PCIeSwitch'
}

function card_comm.is_virtual_port(type)
    if type == BUSINESSPORT_CARD_TYPE_VIR or
       type == BUSINESSPORT_CARD_TYPE_BRIDGE or
       type == BUSINESSPORT_CARD_TYPE_TEAM then
        return true
    end
    return false
end

function card_comm.set_card_init_asset_data(data_obj, resource_obj)
    resource_obj.AssetType = 'NetworkAdapter'
    resource_obj.AssetName = data_obj.Name
    resource_obj.InventorySerialNumber = data_obj.SerialNumber
    resource_obj.InventoryFirmwareVersion = data_obj.FirmwareVersion
    resource_obj.InventoryPCBVersion = data_obj.PCBVersion
    resource_obj.InventoryManufacturer = data_obj.Manufacturer
    resource_obj.AssetTag = 'N/A'
    resource_obj.PartNumber = 'N/A'
    resource_obj.ManufactureDate = 'N/A'
    resource_obj.Slot = tostring(data_obj.SlotNumber)
    resource_obj.UUID = ''
end

function card_comm.param_validator(device_locator)
    if device_locator == '' then
        return false
    end
    if  device_locator:find('%$') then
        return false
    end
    return true
end

function card_comm.set_resource_id_and_node_id(type, device_locator, position, resource_obj)
    if type == 3 then
        resource_obj.ID = string.gsub(device_locator, '%s+', '')
        resource_obj.NodeId = string.gsub(device_locator, '%s+', '')
        return
    end

    resource_obj.ID = string.gsub(position, '%s+', '') .. string.gsub(device_locator, '%s+', '')
    resource_obj.NodeId = string.gsub(position, '%s+', '') .. string.gsub(device_locator, '%s+', '')
end

function card_comm.update_root_bdf(data_obj, resource_obj)
    log:notice('update root bdf, name:%s, BDF:%s:%s.%s, DeviceBDF:%s:%s.%s, type:%s', resource_obj.NodeId, data_obj.Bus,
        data_obj.Device, data_obj.Function, data_obj.DevBus, data_obj.DevDevice, data_obj.DevFunction, data_obj.Type)
    local ok, val = pcall(string.format, '0000:%02x:%02x.%01x', data_obj.Bus, data_obj.Device, data_obj.Function)
    if ok then
        resource_obj.RootBDF = val
    end
end

function card_comm.update_associated_resource(data_obj, resource_obj)
    resource_obj.AssociatedResource = t_resource[data_obj.SocketId]
end

function card_comm.listen_update_resource_tree_property(listen_obj, resource_obj)
    listen_obj:listen('SocketId', function(_, value)
        local resource = t_resource[value]
        if not resource then
            log:error('Invalid SocketId:%s', value)
            resource = 'CPU1'
        end
        resource_obj.AssociatedResource = resource
    end)
    listen_obj:listen('Bus', function(_, _)
        card_comm.update_root_bdf(listen_obj, resource_obj)
    end)
    listen_obj:listen('Device', function(_, _)
        card_comm.update_root_bdf(listen_obj, resource_obj)
    end)
    listen_obj:listen('Function', function(_, _)
        card_comm.update_root_bdf(listen_obj, resource_obj)
    end)
end

return card_comm