-- 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 event = require 'infrastructure.event'
local cjson = require 'cjson'

local common = {}

local discovery <const> = {
    SERVICE = 'bmc.kepler.hwdiscovery'
}

common.ipmi_type = {
    IPMI_PCIE_CARD_TYPE = 1,
    IPMI_OCP_CARD_TYPE = 2
}
-- 从元素集合中查找指定元素
--     1.如果元素为基本数据类型，则传入元素值
--     2.如果元素为table类型，则传入条件匹配函数（匹配成功返回true）
function common.find(coll, val_or_match_func)
    -- table类型，按条件查找
    if type(val_or_match_func) == 'function' then
        for _, item in pairs(coll) do
            if val_or_match_func(item) == true then
                return item
            end
        end
    -- 简单类型
    else
        for i, item in pairs(coll) do
            if item == val_or_match_func then
                return i
            end
        end
    end
    return nil
end

-- skynet
local ok, skynet = pcall(require, 'skynet')
common.skynet = {
    fork = function (cb)
        if ok then
            return skynet.fork(cb)
        end
    end,
    fork_loop = function (param, cb)
        if ok then
            return skynet.fork_loop(param, cb)
        end
    end,
    sleep = function (timeout)
        if ok then
            skynet.sleep(timeout)
        end
    end,
    wakeup = function (process)
        if ok then
            skynet.wakeup(process)
        end
    end,
    wait = function ()
        if ok then
            skynet.wait()
        end
    end,
    timeout = function (param, cb)
        if ok then
            return skynet.timeout(param, cb)
        end
    end
}

common.discovery = discovery

-- 重试函数
function common.retry_func(wait, retries, cb, ...)
    local ok = false
    local rsp = nil
    for try = 1, retries do
        ok, rsp = cb(...)
        if ok then
            return ok, rsp
        end
        skynet.sleep(wait)
    end
    return ok, rsp
end

function common.generate_event(event_key_id, msg_args, assert, com_name, fru_type)
    local param = {}
    param[#param + 1] = { 'ComponentName', com_name }
    param[#param + 1] = { 'State', assert}
    param[#param + 1] = { 'EventKeyId', event_key_id }
    param[#param + 1] = { 'MessageArgs', cjson.encode(msg_args) }
    param[#param + 1] = { 'SystemId', '1' }
    param[#param + 1] = { 'ManagerId', '1' }
    param[#param + 1] = { 'ChassisId', '1' }
    param[#param + 1] = { 'NodeId', '' }
    param[#param + 1] = { 'SubjectType', tostring(fru_type) }

    local ok, ret = pcall(event.generate_event, param)
    if ok then
        log:notice('add event successfully, args: %s', cjson.encode(msg_args))
    else
        log:error('add event failed, %s, args: %s', ret, cjson.encode(msg_args))
    end
end

return common