-- 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 class = require 'mc.class'
local log = require 'mc.logging'
local bios_enum = require 'domain.bios_firmware.defs'
local fructl_handler = require 'infrastructure.fructl'

local PackageValidator = class()

local whlist_list = {
    [bios_enum.UpgradeMode.Cold] = {bios_enum.PackageType.Normal,
        bios_enum.PackageType.Tee, bios_enum.PackageType.Krun},
    [bios_enum.UpgradeMode.Hot] = {bios_enum.PackageType.Patch},
    [bios_enum.UpgradeMode.Force] = {bios_enum.PackageType.Normal,
        bios_enum.PackageType.Tee, bios_enum.PackageType.Krun},
    [bios_enum.UpgradeMode.PowerOffEffective] = {bios_enum.PackageType.Normal,
        bios_enum.PackageType.Patch, bios_enum.PackageType.Tee},
    [bios_enum.UpgradeMode.OnlineForce] = {bios_enum.PackageType.Normal, bios_enum.PackageType.Tee}
}

-- 冷升级->不能升级补丁包
-- 热设计->不能升级非补丁包
-- 装备模式->不能升级补丁包
function PackageValidator:ctor()
    -- 升级包的白名单
    self.WhlistList = whlist_list
end

function PackageValidator:_log_(upgrade_mode, package_type)
    if upgrade_mode == bios_enum.UpgradeMode.Hot and
        package_type == bios_enum.PackageType.Normal then
        log:maintenance(log.MLOG_ERROR, log.FC__PUBLIC_OK,
            'the basic package cannot be upgraded using the hot upgrade interface')
        return
    end
    if upgrade_mode == bios_enum.UpgradeMode.Cold and
        package_type == bios_enum.PackageType.Patch then
        log:maintenance(log.MLOG_ERROR, log.FC__PUBLIC_OK,
            'the bios patch package cannot be upgraded using the cold upgrade interface')
        return
    end
end

function PackageValidator:_validate_package(ctx)
    local upgrade_mode = ctx.UpgradeMode
    local package_type = ctx.PackageType
    local list = self.WhlistList[upgrade_mode]
    if not list then
        error(string.format('[bios]validate: upgrade mode(%s) invalid', upgrade_mode))
    end
    for _, type in pairs(list) do
        if type == package_type then
            return
        end
    end
    self:_log_(upgrade_mode, package_type)
    error(string.format('[bios]validate: upgrade mode(%s), package type(%s) invalid',
        bios_enum.UpgradeModeStr[upgrade_mode], bios_enum.PackageTypeStr[package_type]))
end

function PackageValidator:_validate_scenarios(ctx)
    if ctx.UpgradeMode ~= bios_enum.UpgradeMode.Hot then
        return
    end
    local power_state = fructl_handler.get_power_status(ctx.SystemId)
    if power_state ~= 'ON' and ctx.UpgradeMode == bios_enum.UpgradeMode.Hot then
        log:error('[bios]validate: power state not on, hot upgrade fail')
        error('power state not on, hot upgrade fail')
    end
end

function PackageValidator:validate(ctx)
    if not ctx or not ctx.UpgradeMode or not ctx.PackageType then
        log:error('[bios]package validator: invalid param')
        error('invalid param')
    end
    -- 校验包合法性
    self:_validate_package(ctx)
    -- 校验场景合法性
    self:_validate_scenarios(ctx)
end

return PackageValidator