------------------- iBMC INFO -------------------
IPMC                 CPU:         {* CpuType *}
IPMI             Version:         2.0
Active iBMC      Version:         {* ActiveVersion *}
Active iBMC        Build:         {* ActiveBuildNum *}
Active iBMC        Built:         {* ActiveReleaseDate *}
Backup iBMC      Version:         {* BackupVersion *}
Available iBMC   Version:         {* AvailableVersion *}
Available iBMC     Build:         {* AvailableBuildNum *}
Active Uboot     Version:         {* ActiveUbootVersion *} ({* ActiveUbootReleaseDate *})
Backup Uboot     Version:         {* BackupUbootVersion *} ({* BackupUbootReleaseDate *})
Active Secure Bootloader Version: {* ActiveSecureBootloaderVersion *} ({* ActiveSecureBootloaderReleaseDate *})
Backup Secure Bootloader Version: {* BackupSecureBootloaderVersion *} ({* BackupSecureBootloaderReleaseDate *})
Active Secure Firmware   Version: {* ActiveSecureFirmwareVersion *} ({* ActiveSecureFirmwareReleaseDate *})
Backup Secure Firmware   Version: {* BackupSecureFirmwareVersion *} ({* BackupSecureFirmwareReleaseDate *})
{%
local function string_split(str, delimiter)
    -- 复用/echoes/ipmcget/_sel下的函数，用于字符串的拆分
    if str == nil or str == '' then
        return {}
    end
    if delimiter == nil then
        delimiter = ','
    end

    local res = {}
    for match in (str .. delimiter):gmatch("(.-)" .. delimiter) do
        table.insert(res, match)
    end
    return res
end

local function filter_type(version, name)
    -- 获取对应物理实体的版本
    -- version的格式为 e.g. SR_EXU_0101/MCU_IEU_01010101
    local all_version = {}
    if type(version) == 'table' then
        for _, v in pairs(version) do
            if type(v.Id) == 'string' and type(v.Version) == 'string' and string_split(v.Id,"_")[2] == name then
                table.insert(all_version, v.Version)
            end
        end
    end
    return all_version
end

echo('----------------- Product INFO -----------------\n')
if type(ProductId) == 'number' then
    echo(string.format('Product               ID:         0x%04x\n', ProductId))
end
if type(ProductName) == 'string' then
    echo(string.format('Product             Name:         %s\n', ProductName))
end
if type(ProductUniqueID) == 'string' then
    echo(string.format('Product        Unique ID:         %s\n', ProductUniqueID))
end
for _, v in pairs(Bios) do
    local BiosVersion, BiosBackupVersion = v.Version, v.Version
    local BiosLocation = v.Location
    local Index = v.Index ~= 0 and tostring(v.Index) or ''
    if type(BiosLocation) ~= 'string' then
        BiosLocation = ''
    end
    if type(BiosVersion) ~= 'string' then
        BiosVersion = ''
    end
    if type(BiosBackupVersion) ~= 'string' then
        BiosBackupVersion = ''
    end
    if Index == '' then
        echo(string.format('Active BIOS%s      Version:         (%s)%s\n', Index, BiosLocation , BiosVersion))
        echo(string.format('Backup BIOS%s      Version:         %s\n', Index, BiosBackupVersion))
    else
        echo(string.format('Active BIOS%s     Version:         (%s)%s\n', Index, BiosLocation , BiosVersion))
        echo(string.format('Backup BIOS%s     Version:         %s\n', Index, BiosBackupVersion))
    end
end

if #filter_type(CsrVersion, 'PSR') > 0 then
    -- PSR归属Product INFO
    echo(string.format('PSR              Version:         %s\n', filter_type(CsrVersion, 'PSR')[1]))
end

if type(RiserCards) == 'table' and #RiserCards > 0 then
    echo('--------------- Riser Card INFO ----------------\n')
    local riser_name = 'Riser'
    table.sort(RiserCards, function (a, b)
        return a.Slot < b.Slot
    end)
    for _, v in pairs(RiserCards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' then
            echo(string.format('%s%-5d     BoardName:         %s\n', riser_name, v.Slot, v.Name))
            echo(string.format('%s%-7d     BoardID:         0x%04x\n', riser_name, v.Slot, v.BoardID))
            echo(string.format('%s%-12d   CUID:         %s\n', riser_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and v.PCBVersion ~= 'N/A'then
                echo(string.format('%s%-11d     PCB:         %s\n',  riser_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%s%-2d     CPLD Version:         (U%d)%s\n', riser_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-11d     CSR:         %s\n', riser_name, v.Slot, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%s%-11d     MCU:         %s\n', riser_name, v.Slot, v.MCUVersion))
            end
        end
    end
end

if type(HddBackplanes) == 'table' and #HddBackplanes > 0 then
    echo('-------------- HDD Backplane INFO --------------\n')
    for _, v in pairs(HddBackplanes) do
        if type(v.DeviceName) == 'string' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%-12s   BoardName:         %s\n', v.DeviceName, v.Name))
            echo(string.format('%-14s   BoardID:         0x%04x\n', v.DeviceName, v.BoardID))
            echo(string.format('%-17s   CUID:         %s\n', v.DeviceName, v.UID))
            echo(string.format('%-18s   PCB:         %s\n', v.DeviceName, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%-9s   CPLD Version:         (U%d)%s\n', v.DeviceName, v.LogicUnit, v.LogicVersion))
            else
                echo(string.format('%-9s   CPLD Version:         N/A\n', v.DeviceName))
            end
            -- SEU归属该实体
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%-18s   CSR:         %s\n', v.DeviceName, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%-18s   MCU:         %s\n', v.DeviceName, v.MCUVersion))
            end
        end
    end
end

local function print_cpld_version(count, board_name, board)
    if count > 1 then
        for i = 1, count do
            echo(string.format('%s%-2d CPLD%d Version:         (U%d)%s\n', board_name, board.Slot, i,
                board.MultiLogicUnit[string.format("CPLD%d", i)], board.MultiLogicVersion[string.format("CPLD%d", i)]))
        end
    elseif #board.LogicVersion > 0 and type(board.LogicVersion) == 'string' and type(board.LogicUnit) == 'number' then
        echo(string.format('%s%-1d   CPLD Version:         (U%d)%s\n', board_name, board.Slot, board.LogicUnit, board.LogicVersion))
    end
end

local function print_fpga_version(fpga_count, board_name, board)
    if fpga_count > 0 then
        echo(string.format('%s%-2d  FPGA Version:         (U%d)%s\n', board_name, board.Slot,
            board.MultiLogicUnit["FPGA"], board.MultiLogicVersion[string.format("FPGA")]))
    end
end

local function print_csr_version(board_name, board)
    if type(board.SRVersion) == 'string' and #board.SRVersion > 0 then
        echo(string.format('%s%-10d   CSR:         %s\n', board_name, board.Slot, board.SRVersion))
    end
end

local function print_mcu_version(board_name, board)
    if type(board.MCUVersion) == 'string' and #board.MCUVersion > 0 then
        echo(string.format('%s%-10d   MCU:         %s\n', board_name, board.Slot, board.MCUVersion))
    end
end

local function print_xpu_boards(boards, board_name)
    for _, v in pairs(boards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d   BoardName:         %s\n', board_name, v.Slot, v.Name))
            echo(string.format('%s%-6d   BoardID:         0x%04x\n', board_name, v.Slot, v.BoardID))
            echo(string.format('%s%-9d   CUID:         %s\n', board_name, v.Slot, v.UID))
            echo(string.format('%s%-10d   PCB:         %s\n', board_name, v.Slot, v.PCBVersion))
            local count = 0
            local fpga_count = 0
            for key, value in pairs(v.MultiLogicVersion) do
                if not value or value == '0.00' then
                    goto continue
                end
                if string.match(key, "FPGA") then
                    fpga_count = fpga_count + 1
                    goto continue
                end
                count = count + 1
                ::continue::
            end
            print_cpld_version(count, board_name, v)
            print_fpga_version(fpga_count, board_name, v)
            print_csr_version(board_name, v)
            print_mcu_version(board_name, v)
        end
    end
end

if type(CpuBoards) == 'table' and #CpuBoards > 0 then
    echo('---------------- CPU Board INFO ----------------\n')
    print_xpu_boards(CpuBoards, 'CpuBoard')
end

if type(NpuBoards) == 'table' and #NpuBoards > 0 then
    echo('-------------- NPU/GPU Board INFO --------------\n')
    print_xpu_boards(NpuBoards, 'NpuBoard')
end

if type(ExpBoards) == 'table' and #ExpBoards > 0 then
    echo('---------------- EXP Board INFO ----------------\n')
    print_xpu_boards(ExpBoards, 'ExpBoard')
end

if type(FanBoards) == 'table' and #FanBoards > 0 then
    echo('---------------- FAN Board INFO ----------------\n')
    local fan_board_name = 'FanBoard'
    for _, v in pairs(FanBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d   BoardName:         %s\n', fan_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-6d   BoardID:         0x%04x\n', fan_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-9d   CUID:         %s\n', fan_board_name, v.Slot, v.UID))
            echo(string.format('%s%-10d   PCB:         %s\n', fan_board_name, v.Slot, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" then
                echo(string.format('%s%-1d   CPLD Version:         (U%d)%s\n', fan_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-10d   CSR:         %s\n', fan_board_name, v.Slot, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%s%-10d   MCU:         %s\n', fan_board_name, v.Slot, v.MCUVersion))
            end
        end
    end
end

if type(NetworkCards) == 'table' and #NetworkCards > 0 then
    local nic_exist = false
    local nic_no = 0
    for _, v in pairs(NetworkCards) do
        if v.Type == 1 and type(v.DeviceLocator) == 'string' and type(v.BoardID) == 'number' and type(v.ComponentUniqueID) == 'string' and type(v.PCBVersion) == 'string' then
            if not nic_exist then
                echo('------------------- NIC INFO -------------------\n')
            end

            nic_exist = true
            nic_no = nic_no + 1
            local spaces = string.rep(' ', 9)
            local len = #v.DeviceLocator
            -- 当网卡长度大于临界值14时，计算对齐board_id增加空格
            if len > 14 then
                -- 9是正常打印情况下的空格个数
                spaces = string.rep(' ', 9 - (len - 14))
            end

            echo(string.format('%-14s   BoardID:%s0x%04x\n', v.DeviceLocator, spaces, v.BoardID))
            echo(string.format('%-17s   CUID:         %s\n', v.DeviceLocator, v.ComponentUniqueID))
            echo(string.format('%-18s   PCB:         %s\n', v.DeviceLocator, v.PCBVersion))
            if #filter_type(CsrVersion, 'NIC') > 0 then
                echo(string.format('%-18s   CSR:         %s\n', v.DeviceLocator, filter_type(CsrVersion, 'NIC')[nic_no]))
            end
            if #filter_type(McuVersion, 'NIC') > 0 then
                echo(string.format('%-18s   MCU:         %s\n', v.DeviceLocator, filter_type(McuVersion, 'NIC')[nic_no]))
            end
        end
    end
end

if type(PCIeCards) == 'table' and #PCIeCards > 0 then
    echo('---------------- PCIe Card INFO ----------------\n')
    for _, v in pairs(PCIeCards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.PCBVersion) == 'string' then
            echo(string.format('PCIe%-6d   ProductName:         %s\n', v.Slot, v.Name))
            echo(string.format('PCIe%-10d   BoardID:         0x%04x\n', v.Slot, v.BoardID))
            echo(string.format('PCIe%-14d   PCB:         %s\n', v.Slot, v.PCBVersion))
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('PCIe%-7d   CSRVersion:         %s\n', v.Slot, v.SRVersion))
            end
            if type(v.UID) == 'string' and #v.UID > 0 then
                echo(string.format('PCIe%-13d   CUID:         %s\n', v.Slot, v.UID))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('PCIe%-14d   MCU:         %s\n', v.Slot, v.MCUVersion))
            end
            if type(v.VrdVersion) == 'string' and #v.VrdVersion > 0 then
                echo(string.format('PCIe%-14d   VRD:         %s\n', v.Slot, v.VrdVersion))
            end
        end
    end
end

if type(SecurityModules) == 'table' and #SecurityModules > 0 then
    echo('------------- Security Module INFO -------------\n')
    for _, v in pairs(SecurityModules) do
        if type(v.Protocol) == 'string' and type(v.ProtocolVersion) == 'string' and type(v.Manufacturer) == 'string' and type(v.FirmwareVersion) == 'string' then
            echo(string.format('Specification       Type:         %s\n', v.Protocol))
            echo(string.format('Specification    Version:         %s\n', v.ProtocolVersion))
            echo(string.format('Manufacturer        Name:         %s\n', v.Manufacturer))
            echo(string.format('Manufacturer     Version:         %s\n', v.FirmwareVersion))
        end
    end
end

if type(PsuBoards) == 'table' and #PsuBoards > 0 then
    -- 电源板对外作为单个电源组件展示
    echo('------------------- PSU INFO -------------------\n')
    local psu_board_name = 'PSU'
    for _, v in pairs(PsuBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-9d   BoardName:         %s\n', psu_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-11d   BoardID:         0x%04x\n', psu_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-14d   CUID:         %s\n', psu_board_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and #v.PCBVersion > 0 and v.PCBVersion ~= "" and v.PCBVersion ~= "N/A" then
                echo(string.format('%s%-15d   PCB:         %s\n', psu_board_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" and v.LogicVersion ~= "N/A" then
                echo(string.format('%s%-6d   CPLD Version:         (U%d)%s\n', psu_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-15d   CSR:         %s\n', psu_board_name, v.Slot, v.SRVersion))
            end
        end
    end
end

if type(PSUs) == 'table' and #PSUs > 0 then
    local one_powers = {}
    local power_converters = {}
    for _, v in pairs(PSUs) do
        if type(v.DeviceLocator) == 'string' and type(v.FirmwareVersion) == 'string' and string.match(v.DeviceLocator, "PSU") then
            one_powers[#one_powers + 1] = v
        end

        if type(v.DeviceLocator) == 'string' and type(v.FirmwareVersion) == 'string' and string.match(v.DeviceLocator, "PowerConverter") then
            power_converters[#power_converters + 1] = v
        end
    end

    table.sort(one_powers, function (a, b)
        return a.SlotNumber < b.SlotNumber
    end)

    if #one_powers > 0 then
        -- 存在电源板时已打印此信息，此处避免重复打印
        if #PsuBoards == 0 then
            echo('------------------- PSU INFO -------------------\n')
        end

        for _, v in pairs(one_powers) do
            echo(string.format('%s           Version:           %s\n', v.DeviceLocator, v.FirmwareVersion))
        end
    end

    if #power_converters > 0 then
        echo('-------------------- Power Converter INFO -------------------\n')
        for _, v in pairs(power_converters) do
            echo(string.format('%s           Version:           %s\n', v.DeviceLocator, v.FirmwareVersion))
        end
    end 
end

if type(PeuBoards) == 'table' and #PeuBoards > 0 then
    echo('---------------- PEU Board INFO ----------------\n')
    local peu_board_name = 'PeuBoard'
    for _, v in pairs(PeuBoards) do
        if type(v.Slot) == 'number' and type(v.Name) == 'string' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%s%-4d   BoardName:         %s\n', peu_board_name, v.Slot, v.Name))
            if type(v.BoardID) == 'number' and v.BoardID ~= 0 then
                echo(string.format('%s%-6d   BoardID:         0x%04x\n', peu_board_name, v.Slot, v.BoardID))
            end
            echo(string.format('%s%-9d   CUID:         %s\n', peu_board_name, v.Slot, v.UID))
            if type(v.PCBVersion) == 'string' and #v.PCBVersion > 0 and v.PCBVersion ~= "" and v.PCBVersion ~= "N/A" then
                echo(string.format('%s%-10d   PCB:         %s\n', peu_board_name, v.Slot, v.PCBVersion))
            end
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and #v.LogicVersion > 0 and v.LogicVersion ~= "" and v.LogicVersion ~= "N/A" then
                echo(string.format('%s%-1d   CPLD Version:         (U%d)%s\n', peu_board_name, v.Slot, v.LogicUnit, v.LogicVersion))
            end
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%s%-10d   CSR:         %s\n', peu_board_name, v.Slot, v.SRVersion))
            end
        end
    end
end
 
if type(VrdVersion) == 'table' and #VrdVersion > 0 then
    echo('------------------- Power INFO -------------------\n')
    local vrd_list = {}
    local vrd_name
    for _, v in pairs(VrdVersion) do
        vrd_name = string.match(v.Name, 'CpuBoard(%d+)')
        if type(v.Version) == 'string' and v.Version ~= '' and type(v.Name) == 'string' and vrd_name then
            table.insert(vrd_list, {vrd_name, v.Version})
        end
    end
    table.sort(vrd_list, function (a, b)
        return tonumber(a[1]) < tonumber(b[1])
    end)
    for _, value in ipairs(vrd_list) do
        echo(string.format('CpuBoard%-7s  Version:         %s\n', value[1] .. 'VRD', value[2]))
    end
end

if type(M2TransferCards) == 'table' and #M2TransferCards > 0 then
    echo('--------------- M.2 Adapter INFO ----------------\n')
    for _, v in pairs(M2TransferCards) do
        if type(v.DeviceName) == 'string' and type(v.Name) == 'string' and type(v.BoardID) == 'number' and type(v.UID) == 'string' and type(v.PCBVersion) == 'string' then
            echo(string.format('%-12s    BoardName:     %s\n', v.DeviceName, v.Name))
            echo(string.format('%-14s      BoardID:     0x%04x\n', v.DeviceName, v.BoardID))
            echo(string.format('%-17s       CUID:     %s\n', v.DeviceName, v.UID))
            echo(string.format('%-18s       PCB:     %s\n', v.DeviceName, v.PCBVersion))
            if type(v.LogicVersion) == 'string' and type(v.LogicUnit) == 'number' and v.LogicVersion ~= "" and  v.LogicVersion ~= 'N/A' then
                echo(string.format('%-9s CPLD Version:     (U%d)%s\n', v.DeviceName, v.LogicUnit, v.LogicVersion))
            else
                echo(string.format('%-9s CPLD Version:     N/A\n', v.DeviceName))
            end
            -- SEU归属该实体
            if type(v.SRVersion) == 'string' and #v.SRVersion > 0 then
                echo(string.format('%-18s       CSR:     %s\n', v.DeviceName, v.SRVersion))
            end
            if type(v.MCUVersion) == 'string' and #v.MCUVersion > 0 then
                echo(string.format('%-18s       MCU:     %s\n', v.DeviceName, v.MCUVersion))
            end
        end
    end
end
%}