-- 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.

-- Description: 添加事件接口
local singleton = require 'mc.singleton'
local class = require 'mc.class'
local log = require 'mc.logging'
local cjson = require 'cjson'
local ctx = require 'mc.context'
local PATH = '/bmc/kepler/Systems/1/Events'
local client = require 'storage.client'

local c_add_event = class()

-- 此处统一告警对象名称
local function get_pcie_card_name(card_type_id)
    local map = {
        [0] = "LSI 3108 with MR",
        [1] = "LSI 3108 with IR",
        [2] = "LSI 3108 with IT",
        [3] = "LSI 3008 with MR",
        [4] = "LSI 3008 with IR",
        [5] = "LSI 3008 with IT",
        [6] = "LSI 3508 with MR",
        [7] = "LSI 3516 with MR",
        [8] = "LSI 3408 with iMR",
        [9] = "LSI 3416 with iMR",
        [10] = "LSI 3408 with IT",
        [11] = "LSI 3416 with IT",
        [12] = "LSI 3004 with iMR",
        [13] = "LSI 3908 with IT PCIE",
        [14] = "LSI 3908 with MR",
        [15] = "LSI 3108 with IR",
        [16] = "LSI 3808 with MR",
        [96] = 'HI1880_SP186_M_16i',
        [97] = 'HI1880_SP186_M_32i',
        [98] = 'HI1880_SP186_M_40i',
        [99] = 'HI1880_SP686C_M_16i',
        [100] = 'HI1880_SP686C_M_16i',
        [101] = 'HI1880_SP686C_MH_32i',
        [102] = 'HI1880_SP686C_M_40i',
        [103] = 'HI1880_SP686C_M_40i',
        [113] = 'HI1880_SP186_M_8i'
    }

    return map[card_type_id] or 'Unknown'
end

local function add_event(param)
    local event_obj
    client:ForeachEventsObjects(function(o)
        if o.path == PATH then
            event_obj = o
        end
    end)
    if not event_obj then
        log:error('get events object failed')
        return
    end
    local ok, res = pcall(function()
        return event_obj:AddEvent_PACKED(ctx.new(), param):unpack()
    end)
    if not ok then
        log:error('add events failed, %s', res)
        return
    end
    log:notice('add event successfully, record id [%s]', res)
    return true
end

function c_add_event.generate_bbu_lower_voltage(assert, device_num, card_type_id)
    local param = {}
    param[#param + 1] = { 'ComponentName', 'PCIeCard' }
    param[#param + 1] = { 'State', assert }
    param[#param + 1] = { 'EventKeyId', 'PCIeRAIDCard.PCIeCardBBULowerVoltage' }
    param[#param + 1] = { 'MessageArgs', cjson.encode({'', device_num, get_pcie_card_name(card_type_id)}) }
    param[#param + 1] = { 'SystemId', '' }
    param[#param + 1] = { 'ManagerId', '' }
    param[#param + 1] = { 'ChassisId', '1' }
    param[#param + 1] = { 'NodeId', device_num }

    pcall(add_event, param)
end

function c_add_event.generate_drive_max_temp(assert, temp)
    local param = {}
    param[#param + 1] = { 'ComponentName', 'Disk' }
    param[#param + 1] = { 'State', assert }
    param[#param + 1] = { 'EventKeyId', 'Disk.DiskMaxTempMajorInfo' }
    param[#param + 1] = { 'MessageArgs', cjson.encode({'HDD', 'Max', temp, '60'}) }
    param[#param + 1] = { 'SystemId', '' }
    param[#param + 1] = { 'ManagerId', '1' }
    param[#param + 1] = { 'ChassisId', '1' }
    param[#param + 1] = { 'NodeId', '' }

    pcall(add_event, param)
end

-- Phy误码增长过快事件
function c_add_event.generate_phy_increase_too_fast(assert, desc)
    local param = {}
    param[#param + 1] = { 'ComponentName', 'SAS PHY' }
    param[#param + 1] = { 'State', assert }
    param[#param + 1] = { 'EventKeyId', 'SASPHY.SASPHYErrIncreasedTooFast' }
    param[#param + 1] = { 'MessageArgs', cjson.encode({desc}) }
    param[#param + 1] = { 'SystemId', '' }
    param[#param + 1] = { 'ManagerId', '' }
    param[#param + 1] = { 'ChassisId', '1' }
    param[#param + 1] = { 'NodeId', '' }

    pcall(add_event, param)
end

-- 磁盘占用率过高事件
function c_add_event.generate_percentage_threshold(assert, ...)
    local param = {}
    param[#param + 1] = { 'ComponentName', 'System' }
    param[#param + 1] = { 'State', assert and 'true' or 'false' }
    param[#param + 1] = { 'EventKeyId', 'System.SystemDiskPartitionOverLoad' }
    param[#param + 1] = { 'MessageArgs', cjson.encode({...}) }
    param[#param + 1] = { 'SystemId', '' }
    param[#param + 1] = { 'ManagerId', '' }
    param[#param + 1] = { 'ChassisId', '' }
    param[#param + 1] = { 'NodeId', '' }

    return add_event(param)
end

-- NVMe盘硬盘链路故障
function c_add_event.generate_nvme_link_fault(assert, name)
    local param = {}
    param[#param + 1] = { 'ComponentName', name }
    param[#param + 1] = { 'State', assert }
    param[#param + 1] = { 'EventKeyId', 'Disk.PCIeLinkFail' }
    param[#param + 1] = { 'MessageArgs', cjson.encode({'', name, 'PCIe'}) }
    param[#param + 1] = { 'SystemId', '' }
    param[#param + 1] = { 'ManagerId', '' }
    param[#param + 1] = { 'ChassisId', '' }
    param[#param + 1] = { 'NodeId', '' }

    return add_event(param)
end

return singleton(c_add_event)