-- 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 sf = string.format
local utils = require 'mc.utils'

local new_bmc_trap_oid = '1.3.6.1.4.1.{{SnmpOemIdentifier}}.500.11' -- append with .x.y

local function band(data, mask)
    return data & mask
end

function m.get_severity_level(severity)
    if severity == nil then
        return
    end

    if band(severity, 0x01) == 1 then
        return 1
    elseif band(severity, 0x02) == 2 then
        return 2
    elseif band(severity, 0x04) == 4 then
        return 3
    elseif band(severity, 0x08) == 8 then
        return 4
    elseif severity == 0 then -- 当severity为0，也返回1
        return 1
    end
end

local severity_detail = {
    [0] = 'normal',
    [1] = 'minor',
    [2] = 'major',
    [3] = 'critical'
}

local severity_decs_to_num = {
    ["Minor"] = 2,
    ['Major'] = 3,
    ['Critical'] = 4
}

function m.get_severity_level_detail(severity)
    if severity == nil then
        return
    end

    if severity == 0 then
        return 'none'
    elseif severity == 0x0F then
        return 'all'
    end

    local detail = ''
    for i = 0, 3, 1 do
        if band(severity, 0x01 << i) ~= 0 then
            if #detail ~= 0 then
                detail = detail .. ','
            end

            detail = detail .. severity_detail[i]
        end
    end

    return detail
end

local severity_mask = {
    normal = 0x01,
    minor = 0x02,
    major = 0x04,
    critical = 0x08
}

function m.get_severity_filter(level_detail)
    if level_detail == nil then
        return
    end

    if level_detail == 'none' then
        return 0
    elseif level_detail == 'all' then
        return 0x0F
    end

    local result = 0
    for match in (level_detail .. ','):gmatch('(.-)' .. ',') do
        if severity_mask[match] then
            result = result | severity_mask[match]
        end
    end

    return result
end

-- 事件的格式变为kv类型的结构体数组
local function format_event_list(event_list)
    if #event_list == 0 then
        return {}
    end
    -- 计算结构体参数个数
    local num = 0
    local end_flag = event_list[1].MappingTable[1].Key
    for key, value in pairs(event_list) do
        if value.MappingTable[1].Key == end_flag and key ~= 1 then
            break
        end
        num = num + 1
    end
    -- 格式化结构体,num个结构体构成一条Sel
    local count = 0
    local res = {}
    local event = {}
    for _, v in pairs(event_list) do
        event[v.MappingTable[1].Key] = v.MappingTable[1].Value
        count = count + 1
        if count % num == 0 then
            local temp = event
            event = {}
            res[#res + 1] = temp
        end
    end
    return res
end

-- V3只考虑精准告警模式
local function parse_trap_oid(code)
    local xxx = ((code >> 24) & 0xff) + 1
    local yyy = code & 0x00ffffff
    return sf('%s.%u.%u', new_bmc_trap_oid, xxx, yyy)
end

function m.get_alarms(source_data)
    local alarms = format_event_list(source_data)
    local res = {}
    for i, event in ipairs(alarms) do
        local oid = parse_trap_oid(tonumber(event.EventCode))
        table.insert(res,
            {
                eventIndex = i,
                eventSensorName = event.ComponentName,
                eventAlertTime = utils.date_format(event.Timestamp, "%Y-%m-%d %H:%M:%S", false),
                eventAlertSeverity = severity_decs_to_num[event.Severity],
                eventDescription = event.Description,
                eventCode = event.OldEventCode,
                eventOID = oid,
                newEventCode = event.EventCode,
                newEventOID = oid
            })
    end
    return res
end

return m
