-- 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 utils = require 'mc.utils'

local BOARD_MAP <const> = {
    BCU = 'CpuBoard',
    CLU = 'FanBoard',
    EXU = 'ExpBoard',
    SEU = 'DiskBP',
    IEU = 'Riser',
    NIC = 'NIC',
    VRD = 'Power',
    DPU = 'SDI',
    SDI = 'SDI',
    PSR = 'Product',
    L1 = 'ExpBoard',
    PEU = 'PeuBoard',
    LinkBoard = 'LCN'
}

local m = {}

function m.get_updating_task_uri(task_obj_list)
    for _, obj in pairs(task_obj_list) do
        if obj.State == 'New' or obj.State == 'Starting' or obj.State == 'Running' then
            return {true, '/UI/Rest/BMCSettings/UpdateService/UpdateProgress/' .. obj.Id}
        end
    end
    return {false, nil}
end

function m.get_active_task_uri(task_obj_list)
    if #task_obj_list ~= 0 then
        return '/UI/Rest/BMCSettings/UpdateService/FirmwareActive/ActiveProgress'
    end
    return nil
end

local function compare_power_components(a, b)
    local num_a = tonumber(string.match(a.Name, "%d+"))
    local num_b = tonumber(string.match(b.Name, "%d+"))
    if num_a and num_b then
        return num_a < num_b
    elseif num_a then
        return true
    elseif num_b then
        return false
    else
        return a.Name < b.Name
    end
end

local function compare_cpu_board_components(a, b)
    local tmp1, type1 = string.match(a.Name, 'CpuBoard(%d+)(%s%w+)')
    local tmp2, type2 = string.match(b.Name, 'CpuBoard(%d+)(%s%w+)')
    if not tmp1 and not tmp2 then
        return a.Name < b.Name
    elseif not tmp1 then
        return true
    elseif not tmp2 then
        return false
    elseif tonumber(tmp1) == tonumber(tmp2) then
        return type1 < type2
    else
        return tonumber(tmp1) < tonumber(tmp2)
    end
end

local function append_upgrade_resource(fw_list, version_list, index)
    for _, objs in pairs(fw_list) do
        table.sort(objs, function (a, b)
            if a.Type == 'Power' and b.Type == 'Power' then
                return compare_power_components(a, b)
            end
            if a.Type == 'CpuBoard' and b.Type == 'CpuBoard' then
                return compare_cpu_board_components(a, b)
            end
            return a.Name < b.Name
        end)
        for _, v in pairs(objs) do
            v.Id = index
            index = index + 1
            version_list[index] = v
        end
    end
end

local function insert_tmp_resource(t, name, type, version)
    table.insert(t[type], {
            Name = name,
            Type = tostring(type),
            Version = version
        }
    )
end

function m.get_upgrade_resource(active_version, fw_obj_list)
    local version_list = {
        { Id = 0, Name = 'BMC',  Type = 'firmware', Version = active_version }
    }
    if not fw_obj_list then
        return version_list
    end

    local t_all = {}
    for _, value in pairs(BOARD_MAP) do
        t_all[value] = {}
    end
    for _, obj in pairs(fw_obj_list) do
        if string.match(obj.Name, "Bios") then
            insert_tmp_resource(t_all, string.upper(obj.Id), 'CpuBoard', obj.Version)
            goto continue
        end
        -- PSU Name格式与其他不一样，需单独处理
        if string.match(obj.Name, "PSU") or string.match(obj.Name, "PowerConverter") then
            insert_tmp_resource(t_all, obj.Name, 'Power', obj.Version)
            goto continue
        end
        if string.match(obj.Name, "Product") then
            insert_tmp_resource(t_all, 'PSR', 'Product', obj.Version)
            goto continue
        end

        if string.match(obj.Name, "LinkBoard") then
            insert_tmp_resource(t_all, obj.Name, 'LCN', obj.Version)
            goto continue
        end

        -- 处理BMC暂未获取Retimer信息的场景,web页面无需显示
        if string.match(obj.Name, "Retimer") and obj.Version == "" then
            goto continue
        end

        if string.match(obj.Name, "Krun") then
            insert_tmp_resource(t_all, string.upper(obj.Id), 'CpuBoard', obj.Version)
            goto continue
        end

        local split = utils.split(obj.Id, '_')
        -- 使用Id来获取对应归属单板，split后单板简称可能在第一个元素或第二个元素
        local board_name = BOARD_MAP[split[1]] or BOARD_MAP[split[2]]
        if board_name then
            insert_tmp_resource(t_all, obj.Name, board_name, obj.Version)
        end
        ::continue::
    end
    append_upgrade_resource(t_all, version_list, #version_list)
    return version_list
end

return m
