-- 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 mc_utils = require 'mc.utils'
local utils_core = require 'utils.core'
local cjson = require "cjson"

local m = {}

-- 事件主体类型和名称的对照表
local subject_name_table = {
    [0] = 'CPU',                          -- 0x00：CPU
    [1] = 'Memory',                       -- 0x01：内存
    [2] = 'Disk',                         -- 0x02：硬盘
    [3] = 'PSU',                          -- 0x03：电源
    [4] = 'Fan',                          -- 0x04：风扇
    [5] = 'Disk Backplane',               -- 0x05：硬盘背板
    [6] = 'RAID Card',                    -- 0x06：RAID扣卡
    [7] = 'UNKNOWN',                      -- 0x07：预留属性
    [8] = 'PCIe Card',                    -- 0x08：PCIe标卡
    [9] = 'AMC',                          -- 0x09：AMC板
    [10] = 'HBA',                         -- 0x0A：HBA卡
    [11] = 'Mezz Card',                   -- 0x0B：Mezz扣卡
    [12] = 'UNKNOWN',                     -- 0x0C：预留属性
    [13] = 'NIC',                         -- 0x0D：网卡扣卡
    [14] = 'Memory Board',                -- 0x0E：内存板
    [15] = 'PCIe Riser',                  -- 0x0F：PCIe Riser卡
    [16] = 'Mainboard',                   -- 0x10：主板
    [17] = 'LCD',                         -- 0x11：LCD
    [18] = 'Chassis',                     -- 0x12：机箱
    [19] = 'NCM',                         -- 0x13：NC板
    [20] = 'Switch Module',               -- 0x14：交换板
    [21] = 'Storage Board',               -- 0x15：存储板
    [22] = 'Chassis Backplane',           -- 0x16：机框背板
    [23] = 'HMM/CMC',                     -- 0x17：SMM板/CMC
    [24] = 'Fan Backplane',               -- 0x18：风扇背板
    [25] = 'Power Adapter Board',         -- 0x19：电源转接板
    [26] = 'BMC',                         -- 0x1A：BMC/BMC板
    [27] = 'MM/MMC',                      -- 0x1B：MMC(MM)板
    [28] = 'Twin Node Backplane',         -- 0x1C：双胞胎底板
    [29] = 'Base Plane',                  -- 0x1D：Base (交换平面)
    [30] = 'Fabric Plane',                -- 0x1E：Fabric (交换平面)
    [31] = 'Switch Mezz',                 -- 0x1F：交换扣卡(如FC GW扣卡/FCoE/M8PA)
    [32] = 'LED',                         -- 0x20：LED
    [33] = 'SD Card',                     -- 0x21：SD卡
    [34] = 'Security Module',             -- 0x22：TPM/TCM卡
    [35] = 'I/O Board',                   -- 0x23：IO板
    [36] = 'CPU Board',                   -- 0x24：处理器板
    [37] = 'RMC',                         -- 0x25：RMC板
    [38] = 'PCIe Adapter',                -- 0x26：PCIE SSD盘转接卡
    [39] = 'PCH',                         -- 0x27：PCH(南桥)
    [40] = 'Cable',                       -- 0x28：线缆/内部连接
    [41] = 'Port',                        -- 0x29：端口
    [42] = 'LSW',                         -- 0x2A：LSW
    [43] = 'PHY',                         -- 0x2B：PHY
    [44] = 'System',                      -- 0x2C：业务系统/产品
    [45] = 'M.2 Transfer Card',           -- 0x2D：M.2转接卡
    [46] = 'LED Board',                   -- 0x2E：LED转接板
    [47] = 'LPM',                         -- 0x2F：LPM(也叫PBI板，即PCH、BMC、IO组合板)
    [48] = 'PIC Card',                    -- 0x30：PIC卡（灵活插卡）
    [49] = 'Button',                      -- 0x31：按钮
    [50] = 'Expander',                    -- 0x32：Expander
    [51] = 'CPI',                         -- 0x33：CPI(集中控制分区单元，Central Partition Interconnect Module )
    [52] = 'ACM',                         -- 0x34：ACM(系统时钟板，Advanced Clock Module)
    [53] = 'CIM',                         -- 0x35：CIM(中心接口模块，Central Interface Module)
    [54] = 'PFM',                         -- 0x36：PFM(电源风扇合一模块)
    [55] = 'KPAR',                        -- 0x37：KPAR(多分区系统)
    [56] = 'JC',                          -- 0x38：JC芯片
    [57] = 'SCM',                         -- 0x39：SCM(系统计算模块，指CPU+内存的计算单元)
    [58] = 'Minisas HD channel',          -- 0x3A：MINISAS HD通道
    [59] = 'SATA DOM channel',            -- 0x3B：SATA DOM通道
    [60] = 'GE channel',                  -- 0x3C：GE通道
    [61] = 'XGE channel',                 -- 0x3D：XGE通道
    [62] = 'PCIe Switch',                 -- 0x3E：PCIe Switch
    [63] = 'Interface Device',            -- 0x3F：接口器件
    [64] = 'xPU Carrier Board',           -- 0x40：xPU载板
    [65] = 'Disk BaseBoard',              -- 0x41：硬盘底板（CH222V3的SESA）
    [66] = 'VGA Interface Card',          -- 0x42：VGA接口卡
    [67] = 'Pass-Through Card',           -- 0x43：直通卡(SAS直通卡等)
    [68] = 'Logical Driver',              -- 0x44：逻辑盘
    [69] = 'PCIe Retimer',                -- 0x45：PCIe Retimer
    [70] = 'PCIe Repeater',               -- 0x46：PCIe Reperter
    [71] = 'SAS',                         -- 0x47：SAS
    [72] = 'Memory Channel',              -- 0x48：内存通道
    [73] = 'BMA',                         -- 0x49：BMA
    [74] = 'LOM',                         -- 0x4A：板载网卡
    [75] = 'Signal Adapter Board',        -- 0x4B：信号转接板
    [76] = 'Horizontal Connection Board', -- 0x4C：水平转接板
    [77] = 'Node',                        -- 0x4D：节点
    [78] = 'Asset Locate Board',          -- 0x4E：资产管理控制板
    [79] = 'Unit',                        -- 0x4F：机柜U位
    [80] = 'RMM',                         -- 0x50：机柜管理模块
    [81] = 'Rack',                        -- 0x51：机柜
    [82] = 'BBU',                         -- 0x52：备电
    [83] = 'OCP Card',                    -- 0x53：OCP扣卡
    [84] = 'Leakage Detection Card',      -- 0x54：漏液检测卡
    [85] = 'MESH Card',                   -- 0x55：MESH卡
    [86] = 'NPU',                         -- 0x56：神经网络计算芯片
    [87] = 'CIC Card',                    -- 0x57：融合接口卡
    [88] = 'Expansion Module',            -- 0x58：Expansion Module
    [89] = 'Fan Module',                  -- 0x59：风扇模块
    [90] = 'AR Card',                     -- 0x5A：AR卡
    [91] = 'Converge Board',              -- 0x5B：汇聚板
    [92] = 'SoC Board',                   -- 0x5C：SoC主板
    [93] = 'Expand Board',                -- 0x5D：扩展板
    [94] = 'HiAM',                        -- 0x5E:HiAM
    [95] = 'OpticalModule',               -- 0x5F：光模块
    [96] = 'HDU',                         -- 0x60:HDU
    [98] = 'LCN',                         -- 0x62: 区域计算网络
    [192] = 'BCU',                        -- 0xC0：基础计算组件
    [193] = 'EXU',                        -- 0xC1：系统扩展组件
    [194] = 'SEU',                        -- 0xC2：存储扩展组件
    [195] = 'IEU',                        -- 0xC3：IO扩展组件
    [196] = 'CLU'                         -- 0xC4：散热组件
}

-- 事件的格式变为kv类型的结构体数组
local function format_event_list(event_list)
    -- 计算结构体参数个数
    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

function m.alarm_list(event_list)
    if not event_list or #event_list == 0 then
        return {
            TotalCount = 0,
            List = {}
        }
    end
    utils_core.tzset()
    local res = format_event_list(event_list)
    local results = {}
    local alarm_item
    for i = 1, #res, 1 do
        alarm_item = res[i]
        results[#results + 1] = {
            ID = i,
            Level = alarm_item.Severity,
            Subject = subject_name_table[tonumber(alarm_item.SubjectType)],
            Content = alarm_item.Description,
            CreatedTime = mc_utils.date_format(tonumber(alarm_item.Timestamp), '%Y-%m-%d %H:%M:%S', false),
            EventCode = alarm_item.EventCode,
            HandlingSuggestion = alarm_item.Suggestion
        }
    end
    return {
        TotalCount = #res,
        List = results
    }
end

function m.event_subject_types(component_types)
    local res = cjson.json_object_new_object()
    local types = cjson.json_object_new_array()
    local num = 0
    -- 获取实时的部件类型
    if component_types then
        for _, obj in ipairs(component_types) do
            local temp_obj = cjson.json_object_new_object()
            temp_obj.ID = obj.ComponentType
            temp_obj.Label = obj.ComponentName
            types[#types + 1] = temp_obj
            num = num + 1
        end
    end
    res.TotalCount = num
    res.List = types
    return res
end

local function get_subject_type(subject_name)
    for type, name in pairs(subject_name_table) do
        if name == subject_name then
            return type
        end
    end
    return ''
end

function m.get_selected_param(origin_params)
    local params = {}
    for k, v in pairs(origin_params) do
        if k == 'EndTime' then
            params[#params + 1] = {'SelEndTime', v}
        elseif k == 'SearchString' then
            params[#params + 1] = {'SelSearchString', v}
        elseif k == 'Subject' then
            params[#params + 1] = {'SelObjectType', tostring(get_subject_type(v))}
        elseif k == 'Level' and v ~= cjson.null then
            params[#params + 1] = {'SelLevel', v == 'Informational' and 'Normal' or v}
        elseif k == 'BeginTime' then
            params[#params + 1] = {'SelBeginTime', v}
        end
    end
    return params
end

function m.get_reversed_index_count(total, skip, top)
    local count = top
    local index = total - skip - count + 1
    if index <= 0 then
        count = count + index - 1
        index = 1
    end
    count = count < 0 and 0 or count
    return {
        Index = index,
        Count = count
    }
end

function m.get_result(total, event_list)
    if not event_list or #event_list == 0 then
        return {
            TotalCount = 0,
            List = {}
        }
    end
    local res = format_event_list(event_list)
    local results = {}
    local event_item
    for i = 1, #res, 1 do
        event_item = res[i]
        results[#results + 1] = {
            ID = event_item.RecordId,
            Level = event_item.Severity == 'Normal' and 'Informational' or event_item.Severity,
            Subject = tonumber(event_item.SubjectType),
            SubjectName = subject_name_table[tonumber(event_item.SubjectType)],
            Content = event_item.Description,
            CreatedTime = mc_utils.date_format(tonumber(event_item.Timestamp), '%Y-%m-%d %H:%M:%S', false),
            EventCode = event_item.EventCode,
            HandlingSuggestion = event_item.Suggestion,
            Status = event_item.State
        }
    end
    return {
        TotalCount = total,
        List = results
    }
end

return m
