-- 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 mdb_access = require 'route_mapper.mdb_access'
local json = require 'cjson'
local m = {}

local json_format_firmware_info = {
    ['VrdVersion'] = true,
    ['CsrVersion'] = true,
    ['McuVersion'] = true,
    ['BiosVersion'] = true
}

function m.get_all_firmware_info(infos)
    local res = {}
    for _, value in pairs(infos) do
        res[value.FirmwareId] = value.FirmwareInfo
    end
    for key, _ in pairs(json_format_firmware_info) do
        if res[key] then
            res[key] = json.decode(res[key].Value)
        else
            res[key] = {}  -- 避免回显模板频繁判空
        end
    end
    return res
end

function m.filter_retimer_path(members)
    local list = {}
    for _, path in pairs(members) do
        if string.find(path, "Retimer") then
            table.insert(list, path)
        end
    end
    return list
end

function m.get_product_unique_id(unique_id, vendor_id)
    local id = nil
    -- 防止product_mgmt组件没有上树
    if unique_id == nil or vendor_id == nil then
        return nil
    end

    -- 资源树上的unique_id和vendor_id应为'0x'+8位十六进制数字，共10位
    if string.len(unique_id) == 10 and string.len(vendor_id) == 10 then
        if string.upper(vendor_id) ~= "0XFFFFFFFF" then
            -- 若vendor_id为0x12345678, unique_id为0x87654321, 则拼接结果为0x1234567887654321
            id = string.format("0x%08X%08X",
                tonumber(string.sub(vendor_id, 3), 16), tonumber(string.sub(unique_id, 3), 16))
        else
            id = string.format("0x%08X", tonumber(string.sub(unique_id, 3), 16))
        end
    end

    return id
end

function m.read_all_cpuboards(cpuboards)
    local list = {}
    local cpuboards_paths = {}
    local mdb_obj
    local mdb_obj1
    local cpulist
    for _, paths in pairs(cpuboards) do
        if string.find(paths, 'CpuBoard') then
            table.insert(cpuboards_paths, paths)
        end
    end
    for _, path in pairs(cpuboards_paths) do
        cpulist = {}
        mdb_obj = mdb_access.get_object(bus, path, 'bmc.kepler.Systems.Board')
        mdb_obj1 = mdb_access.get_object(bus, path, 'bmc.kepler.Systems.Board.Unit')
        if mdb_obj and mdb_obj1 then
            cpulist['DeviceName'] = mdb_obj['DeviceName']
            cpulist['Name'] = mdb_obj['Name']
            cpulist['BoardID'] = mdb_obj['BoardID']
            cpulist['PCBVersion'] = mdb_obj['PcbVersion']
            cpulist['LogicUnit'] = mdb_obj['LogicUnit']
            cpulist['LogicVersion'] = mdb_obj['LogicVersion']
            cpulist['UID'] = mdb_obj1['UID']
            cpulist['Slot'] = mdb_obj['Slot']
            cpulist['MCUVersion'] = mdb_obj['MCUVersion']
            cpulist['SRVersion'] = mdb_obj['SRVersion']
            cpulist['MultiLogicUnit'] = mdb_obj['MultiLogicUnit']
            cpulist['MultiLogicVersion'] = mdb_obj['MultiLogicVersion']
            table.insert(list, cpulist)
        end
    end

    table.sort(list, function(cpuboard1, cpuboard2)
        return cpuboard1.Slot < cpuboard2.Slot
    end)
    return list
end
function m.get_all_network_adapters()
    local network_adapter_objs = {}
    local mds_objs = mdb.get_sub_objects(bus, '/bmc/kepler/Systems/1/NetworkAdapters',
        'bmc.kepler.Systems.NetworkAdapter')
    for _, mds_obj in pairs(mds_objs) do
        -- 仅保存板载网卡
        if mds_obj.Type == 1 then
            table.insert(network_adapter_objs, {
                Type = mds_obj.Type,
                DeviceLocator = mds_obj.DeviceLocator,
                BoardID = mds_obj.BoardID,
                ComponentUniqueID = mds_obj.ComponentUniqueID,
                PCBVersion = mds_obj.PCBVersion,
                Name = mds_obj.Name
            })
        end
    end
    return network_adapter_objs
end

function m.get_all_psus()
    local psu_objs = {}
    local mds_objs = mdb.get_sub_objects(bus, '/bmc/kepler/Systems/1/PowerMgmt',
        'bmc.kepler.Systems.PowerMgmt.OnePower')
    for _, mds_obj in pairs(mds_objs) do
        table.insert(psu_objs, {
            DeviceLocator = mds_obj.DeviceLocator,
            FirmwareVersion = mds_obj.FirmwareVersion,
            SlotNumber = mds_obj.SlotNumber
        })
    end
    return psu_objs
end

function m.get_board_info(board_type)
    local ret_objs = {}
    local board_objs = mdb.get_sub_objects(bus, '/bmc/kepler/Systems/1/Boards/' .. board_type,
        'bmc.kepler.Systems.Board')
    local unit_obj
    for _, board_obj in pairs(board_objs) do
        unit_obj = mdb.get_object(bus, board_obj.path, 'bmc.kepler.Systems.Board.Unit')
        table.insert(ret_objs, {
            DeviceName = board_obj.DeviceName,
            Name = board_obj.Name,
            BoardID = board_obj.BoardID,
            PCBVersion = board_obj.PcbVersion,
            LogicUnit = board_obj.LogicUnit,
            LogicVersion = board_obj.LogicVersion,
            Slot = board_obj.Slot,
            MCUVersion = board_obj.MCUVersion,
            SRVersion = board_obj.SRVersion,
            MultiLogicUnit = board_obj.MultiLogicUnit,
            MultiLogicVersion = board_obj.MultiLogicVersion,
            UID = unit_obj.UID
        })
    end

    table.sort(ret_objs, function(a, b)
        -- 提取Slot数字进行比较，确保按照ExpBoard1，ExpBoard2的顺序打印
        return tonumber(a.Slot) < tonumber(b.Slot)
    end)

    return ret_objs
end

return m
