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

local nvme_mi_command = {}

function nvme_mi_command.pkg_ctrl_health_stat_dword(data)
    local dword_info = {
        sctlid = 0,
        maxrent = 0,
        incf = 0,
        incpf = 0,
        incvf = 0,
        report_all = 0,
        csts = 0,
        ctemp = 0,
        pdlu = 0,
        spare = 0,
        cwartn = 0,
        ccf = 0
    }
    for k, v in pairs(data) do
        if dword_info[k] then
            dword_info[k] = v
        end
    end
    local dword0 = dword_info.sctlid | (dword_info.maxrent << 16) | (dword_info.incf << 24) |
        (dword_info.incpf << 25) | (dword_info.incpf << 26) | (dword_info.report_all << 31)

    local dword1 = dword_info.csts | (dword_info.ctemp << 1) | (dword_info.pdlu << 2) |
        (dword_info.spare << 3) | (dword_info.cwartn << 4) | (dword_info.ccf << 31)
    return {dword0 = dword0, dword1 = dword1}
end

function nvme_mi_command.pkg_config_get_dword(data)
    local dword_info = {
        port_id = 0,
        config_id = 0
    }
    for k, v in pairs(data) do
        if dword_info[k] then
            dword_info[k] = v
        end
    end
    local dword0 = dword_info.port_id << 24 | dword_info.config_id
    return {dword0 = dword0, dword1 = 0}
end

local function update_controller_health_status(obj)
    local controller_health_status = obj.nvme_mi_obj:ControllerHealthStatus():value()
    if not controller_health_status then
        log:error('get Disk%s controller_health_status failed', obj.nvme.Slot)
        return
    end

    log:info('get Disk%s controller_health_status successfully, %s', obj.nvme.Slot)
    obj.controller_health_status = controller_health_status
end

local function update_mctp_trans_unit_size(obj)
    local mctp_trans_unit_size = obj.nvme_mi_obj:MctpTransSize():value()
    if not mctp_trans_unit_size then
        log:error('get Disk%s mctp_trans_unit_size failed', obj.nvme.Slot)
        return
    end

    log:info('get Disk%s mctp_trans_unit_size successfully, %s', obj.nvme.Slot)
    obj.mctp_trans_unit_size = mctp_trans_unit_size
end

local function update_nvm_subsystem_info(obj)
    local nvm_subsystem_info = obj.nvme_mi_obj:SubsystemInfo():value()
    if not nvm_subsystem_info then
        log:error('get Disk%s nvm_subsystem_info failed', obj.nvme.Slot)
        return
    end

    log:info('get Disk%s nvm_subsystem_info successfully, %s', obj.nvme.Slot)
    obj.nvm_subsystem_info = nvm_subsystem_info
end

local function update_subsys_health_status(obj)
    local subsys_health_status = obj.nvme_mi_obj:SubsystemHealthStatus():value()
    if not subsys_health_status then
        log:error('get Disk%s subsys_health_status failed', obj.nvme.Slot)
        return
    end

    log:info('get Disk%s nvm_subsystem_info successfully, %s', obj.nvme.Slot)
    obj.subsys_health_status = subsys_health_status
end

function nvme_mi_command.update_nvme_mi_command_info(obj)
    update_controller_health_status(obj)
    update_mctp_trans_unit_size(obj)
    update_nvm_subsystem_info(obj)
    update_subsys_health_status(obj)
end

return nvme_mi_command