-- 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 id = string.upper(Uri.id)

-- 处理电源/电源砖场景
local psu_idx = string.match(id, '^CHASSISPSU(%d+)$')
if psu_idx then
    for _, path in pairs(ProcessingFlow[3].Destination.Members) do
        local obj_id = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/(.*)')
        if string.match(obj_id, "PSU" .. psu_idx .. "$") then
            return obj_id
        end
    end
end

if string.match(id, 'LCNLINKBOARD%d') then
    local prefix = string.match(Uri.id, 'LinkBoard%d+') .. "_"
    if string.match(id, 'PATCH$') then
        return prefix .. "Patch"
    end
    if string.match(id, 'SOFTWARE$') then
        return prefix .. "Software"
    end
end

local firmware_types = {
    'FPGA',
    'CPLD',
    'MCU',
    'SR',
    'VRD',
    'RETIMER'
}

local firmware_type = ''
local firmware_num
for _, v in ipairs(firmware_types) do
    if string.match(id, v .. '%d?$') ~= nil then
        firmware_type = v
        firmware_num = string.match(id, '%d$')
        break
    end
end


local position = ''
local name = ''
local device_name
local uri_device_name
for _, board in ipairs(Input) do
    --出现(和)会导致match函数匹配不到，加%转为普通字符
    local node_id = board.NodeId:gsub("(%W)", "%%%1")
    -- redfish不区分大小写，全转为大写匹配
    node_id = string.upper(node_id)

    --BCU的VRD要单独处理
    device_name = string.match(node_id, '(CPUBOARD%d+)')    -- if not match return nil
    uri_device_name = string.match(id, '(CPUBOARD%d+)')

    if firmware_type == 'VRD' and board.Type == 'BCU' and
      node_id ~= "" and device_name ~= nil and device_name == uri_device_name then
        position = board.Id
        name = device_name .. firmware_type
        break
    elseif firmware_type == 'VRD' and board.Type ~= 'BCU' and node_id ~= "" and string.match(id, '^' .. node_id) then
        position = board.Id
        name = node_id .. firmware_type
        break
    elseif firmware_type == 'RETIMER' and board.Type ~= 'BCU' and
      node_id ~= "" and string.match(id, '^' .. node_id) then
        position = board.Id
        name = id
        break
    elseif firmware_type ~= 'VRD' and node_id ~= "" and string.match(id, '^' .. node_id) then
        if firmware_type == 'SR' then
            name = node_id .. 'HWSR'
            if node_id == 'CHASSISBMC' then
                -- PSR固定对应ChassisBMC
                name = node_id .. 'PSR'
            end
        else
            name = node_id .. firmware_type
        end
        if string.match(id, name .. '%d?$') then
            position = board.Id
            break
        end
    end
end

if position == '' or firmware_type == '' then
    for _, path in pairs(ProcessingFlow[3].Destination.Members) do
        local obj_id = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/(.*)')
        if id == string.upper(obj_id) then
            return obj_id
        end
    end
    return id
end

if not string.match(id, name) then
    return id
end

local bcu_cpld_count = 0
local exu_cpld_count = 0
local dpu_cpld_count = 0
for _, path in pairs(ProcessingFlow[3].Destination.Members) do
    local is_bcu_cpld = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/BCU_CPLD%d_%d+')
    local is_exu_cpld = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/EXU_CPLD%d_%d+')
    local is_dpu_cpld = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/CPLD%d_DPU_%d+')
    if is_bcu_cpld then
        bcu_cpld_count = bcu_cpld_count + 1
    end
    if is_exu_cpld then
        exu_cpld_count = exu_cpld_count + 1
    end
    if is_dpu_cpld then
        dpu_cpld_count = dpu_cpld_count + 1
    end
end

-- 没有后缀有序号的固件
if firmware_num and bcu_cpld_count <= 1 and exu_cpld_count <= 1 then
    return id
end

--通过position和firmware_type找到对应资源树上的固件
for _, path in pairs(ProcessingFlow[3].Destination.Members) do
    local obj_id = string.match(path, '/bmc/kepler/UpdateService/FirmwareInventory/(.*)')
    -- 资源树id格式末尾为_position
    local id_table = {}
    for w in string.gmatch(obj_id, '[^_]+') do
        table.insert(id_table, w)
    end

    local match_flag = false
    local _, _, idx = string.match(id, "BCU(%d+)CPUBOARD(%d+)CPLD(%d+)")
    match_flag = match_flag or idx
    if idx and string.match(obj_id, 'BCU_CPLD' .. idx .. '_' .. position) then
        return obj_id
    end

    local _, _, idx1 = string.match(id, "EXU(%d+)EXPBOARD(%d+)CPLD(%d+)")
    match_flag = match_flag or idx1
    if idx1 and string.match(obj_id, 'EXU_CPLD' .. idx1 .. '_' .. position) then
        return obj_id
    end

    -- 处理EXU上存在Retimer固件的场景
    _, _, idx1 = string.match(id, "EXU(%d+)EXPBOARD(%d+)RETIMER(%d+)")
    match_flag = match_flag or idx1
    if idx1 and string.match(obj_id, idx1 .. '_' .. position) then
        return obj_id
    end

    local _, idx2 = string.match(id, "PCIECARD(%d+)CPLD(%d+)")
    match_flag = match_flag or idx2
    if idx2 and string.match(obj_id, 'CPLD' .. idx2 .. '_DPU') then
        return obj_id
    end

    -- 处理无PSR固件场景:PSR与EXU同position时，避免将EXU误认为chassisBMCPSR
    if not match_flag and string.match(path, firmware_type) and position == id_table[#id_table] and
        not (name == 'CHASSISBMCPSR' and id_table[2] ~= 'PSR') then
        return obj_id
    end
end

return id
