-- 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 m = {}
local cjson = require 'cjson'
local mc_ctx = require 'mc.context'
local custom_messages = require 'messages.custom'

function m.get_expand_parameters(is_clear_conf, force_update, stage)
    local ret_paras = {}

    if is_clear_conf then
        ret_paras.RestoreFactorySettings = 'true'
    end

    if force_update == nil or force_update == true then
        ret_paras.ForceUpdate = 'true'
    else
        ret_paras.ForceUpdate = 'false'
    end

    ret_paras.Stage = stage and 'true' or 'false'

    return ret_paras
end

function m.get_upgrade_progress(progress)
    local res = cjson.json_object_new_array()
    local UPDATE_SERVICE = "bmc.kepler.firmware_mgmt"
    local UPDATE_SERVICE_PATH = "/bmc/kepler/UpdateService"
    local UPDATE_SERVICE_INF = "bmc.kepler.UpdateService"
    local _, progress_tbl = bus:call(UPDATE_SERVICE, UPDATE_SERVICE_PATH, UPDATE_SERVICE_INF,
        'GetUpdateProgress', 'a{ss}', (mc_ctx.get_context() or mc_ctx.new()))
    local object
    for _, value in pairs(progress_tbl) do
        object = cjson.json_object_new_object()
        -- 升级任务名
        object['TaskName'] = value.TaskName or value[1]
        -- 升级固件描述
        object['Component'] = value.Firmware or value[2]
        -- 升级包名称
        object['FileName'] = value.FileName or value[4]
        -- 升级进度
        object['Percentage'] = value.Percentage or value[5]
        -- 升级状态
        object['TaskState'] = value.TaskState or value[6]
        -- 升级任务错误码
        object['ErrorCode'] = tonumber(value.ErrorCode or value[7])
        -- 固件预计升级的剩余时间
        object['EstimatedRemainingTime'] = value.EstimatedRemainingTime and tonumber(value.EstimatedRemainingTime)
        object['FirmwareId'] = value.FirmwareInstance or value[3]
        res[#res + 1] = object
    end
    return res
end

function m.get_pending_list(list)
    local res = cjson.json_object_new_array()
    local object
    for _, value in pairs(list) do
        object = cjson.json_object_new_object()
        object['SystemId'] = value.SystemId
        object['FirmwareType'] = value.Firmware
        object['ActiveStatus'] = value.ActiveStatus
        object['ActiveAction'] = value.ActiveAction
        res[#res + 1] = object
    end
    return res
end

function m.get_options(param)
    local res = {}
    if param.ImageType == 'FullImage' then
        if not param.FullImageNames then
            local err = custom_messages.UnrequiredProperty('FullImageNames')
            err.RelatedProperties = {'#/FullImageNames'}
            error(err)
        end
        if #param.FullImageNames == 0 then
            local err = custom_messages.PropertyValueNotEmpty()
            err.RelatedProperties = {'#/FullImageNames'}
            error(err)
        end
        res.UpdateMode = 'OptionalFullImage'
    end

    return res
end

function m.get_packages(param)
    local res, package, options = {}, {}, {}
    if param.ForceUpdate == nil or param.ForceUpdate == true then
        options['ForceUpdate'] = 'true'
    else
        options['ForceUpdate'] = 'false'
    end
    options['Stage'] = param.Stage and 'true' or 'false'
    package = {param.FilePath, options}
    res[#res + 1] = package
    if param.ImageType == 'FullImage' then
         for _, name in ipairs(param.FullImageNames) do
             package = {name, options}
             res[#res + 1] = package
         end
     end
    return res
end

function m.get_active_policy(policy)
    if not policy or #policy == 0 then
        return {}
    end
    local policy_set = {}
    local unique_values = {}
    for _, value in ipairs(policy) do
        if not policy_set[value] then
            policy_set[value] = true
            table.insert(unique_values, value)
        end
    end
    if policy_set.PowerOn and policy_set.PowerOff then
        error(custom_messages.OperationFailed())
    end
    if policy_set.PowerOff and policy_set.ResetBMC then
        return {ActivationControl = 'ResetAC'}
    end
    table.sort(unique_values)

    return {
        ActivationControl = table.concat(unique_values, ",")
    }
end

-- 当前仅做去重处理
function m.get_stage_list(input)
    if not input or #input == 0 then
        return {}
    end
    local temp = {}
    local list = {}
    local id
    for _, value in pairs(input) do
        id = value.FirmwareId
        if not temp[id] then
            temp[id] = true
            table.insert(list, id)
        end
    end

    return list
end

return m
