-- 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 ipmi = require 'ipmi'
local context = require 'mc.context'
local log = require 'mc.logging'
local menums = require 'types.enums'
local ctx_new = context.get_context_or_default()

local ipmi_func = {}

-- Cold Reset
function ipmi_func:ipmi_cold_reset(fru_dev_id, ctx, fructrl, powerapi)
    if menums.PGSignalState[fructrl:get_FruPowerState(fru_dev_id)] ~= 'ON' then
        ipmi.ipmi_operation_log(ctx, 'fructrl', 'FRU' .. fru_dev_id .. ' forced system reset failed')
        return {CompletionCode = 0xd5}
    end

    ctx_new['fru_id'] = fru_dev_id
    local ok, result = pcall(function()
        return powerapi:system_reset(ctx_new, 'ForceRestart', 'ChassisControlCommand')
    end)
    if ok and result == 0x00 then
        ipmi.ipmi_operation_log(ctx, 'fructrl', 'Set FRU' .. fru_dev_id .. ' to forced system reset successfully')
        return {CompletionCode = 0x00}
    end
    ipmi.ipmi_operation_log(ctx, 'fructrl', 'FRU' .. fru_dev_id .. ' forced system reset failed')
    return {CompletionCode = 0xd5}
end

-- Warm Reset
function ipmi_func:ipmi_warm_reset(fru_dev_id, ctx, fructrl)
    if menums.PGSignalState[fructrl:get_PowerState()] ~= 'ON' then
        ipmi.ipmi_operation_log(ctx, 'fructrl', 'FRU' .. fru_dev_id .. ' warm reset failed')
        return {CompletionCode = 0xd5}
    end

    -- 不支持热复位
    ipmi.ipmi_operation_log(ctx, 'fructrl', 'FRU' .. fru_dev_id .. ' warm reset failed')
    return {CompletionCode = 0xd5}
end

-- Force Reboot
function ipmi_func:ipmi_force_reboot(fru_dev_id, ctx, fructrl, powerapi)
    if menums.PGSignalState[fructrl:get_PowerState()] ~= 'ON' then
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'FRU' .. fru_dev_id .. ' forced power off the service system, and then power it on failed')
        return {CompletionCode = 0xd5}
    end
    ctx_new['fru_id'] = 0
    local result = powerapi:system_reset(ctx_new, 'ForcePowerCycle', 'ChassisControlCommand')
    if result == 0x00 then
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'Set FRU' .. fru_dev_id .. ' to forced power off the service system, and then power it on successfully')
        return {CompletionCode = 0x00}
    else
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'FRU' .. fru_dev_id .. ' forced power off the service system, and then power it on failed')
        return {CompletionCode = 0xd5}
    end
end

-- Graceful Reboot
function ipmi_func:ipmi_graceful_reboot(fru_dev_id, ctx, fructrl, powerapi)
    if menums.PGSignalState[fructrl:get_FruPowerState(fru_dev_id)] ~= 'ON' then
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'FRU' .. fru_dev_id .. ' graceful power off the service system, and then power it on failed')
        return {CompletionCode = 0xd5}
    end
    ctx_new['fru_id'] = fru_dev_id
    local result = powerapi:system_reset(ctx_new, 'PowerCycle', 'ChassisControlCommand')
    if result == 0x00 then
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'Set FRU' .. fru_dev_id .. ' to graceful power off the service system, and then power it on successfully')

        return {CompletionCode = 0x00}
    else
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'FRU' .. fru_dev_id .. ' graceful power off the service system, and then power it on failed')
        return {CompletionCode = 0xd5}
    end
end

-- Issue Diagnostic Interrupt
function ipmi_func:ipmi_issue_diagnostic_interrupt(fru_dev_id, ctx)
    log:error('Nmi command is not supported on BMC')
    ipmi.ipmi_operation_log(ctx, 'fructrl', 'FRU' .. fru_dev_id .. ' issue diagnostic interrupt failed')
    return {CompletionCode = 0xd5}
end

function ipmi_func:ipmi_graceful_shutdown(fru_dev_id, ctx, powerapi)
    ctx_new['fru_id'] = fru_dev_id
    local result = powerapi:system_reset(ctx_new, 'GracefulShutdown', 'ChassisControlCommand', fru_dev_id)
    if result == 0x00 then
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'Set FRU' .. fru_dev_id .. ' to normal power off successfully')
        return {CompletionCode = 0x00}
    else
        ipmi.ipmi_operation_log(ctx, 'fructrl',
            'FRU' .. fru_dev_id .. ' normal power off faild')
        return {CompletionCode = 0xd5}
    end
end

return ipmi_func
