-- Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
-- 
-- this file licensed under the 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 class = require 'mc.class'
local Singleton = require 'mc.singleton'
local ipmi = require 'ipmi'
local log = require 'mc.logging'
local initiator = require 'mc.initiator'
local privilege = require 'mc.privilege'
local enums = require 'basic_cooling.define.cooling_enums'

local cooling_utils = class()

function cooling_utils:ctor()
    self.last_time_map = {}
end

function cooling_utils.ipmi_op(ctx, fmt, ...)
    ipmi.ipmi_operation_log(ctx, 'thermal_mgmt', fmt, ...)
end

function cooling_utils.op(ctx, fmt, ...)
    local intf = ctx.Interface and ctx.Interface or 'N/A'
    local user_name = ctx.UserName and ctx.UserName or 'N/A'
    local client_addr = ctx.ClientAddr and ctx.ClientAddr or 'N/A'

    log:operation(initiator.new(intf, user_name, client_addr), 'thermal_mgmt', fmt, ...)
end

-- 限频日志
---@param level number params: 1,error 2,info 3,debug
---@param interval_s number params: interval seconds
function cooling_utils:frequency_limit_log(level, interval_s, fmt, ...)
    local last_time_key = debug.getinfo(2, 'S').short_src .. ':' .. debug.getinfo(2, "l").currentline
    local cur_time = os.time()
    local log_callback = {
        [enums.log_level.ERROR] = log.error,
        [enums.log_level.INFO] = log.info,
        [enums.log_level.DEBUG] = log.debug
    }
    local last_time = self.last_time_map[last_time_key]
    if not last_time or cur_time - last_time >= interval_s then
        self.last_time_map[last_time_key] =  cur_time
        log_callback[level](log, fmt, ...)
    end
end

function cooling_utils.size_of(t)
    local cnt = 0
    for _, _ in pairs(t) do
        cnt = cnt + 1
    end
    return cnt
end

-- 数组升序判断函数
function cooling_utils.is_array_ascending(arr)
    for i = 2, #arr do
        if arr[i] <= arr[i - 1] then
            return false
        end
    end
    return true
end
-- 数组非降序判断函数
function cooling_utils.is_array_not_descending(arr)
    for i = 2, #arr do
        if arr[i] < arr[i - 1] then
            return false
        end
    end
    return true
end

function cooling_utils.verify_privilege_for_rpc(prop, expect_priv)
    privilege.validate_set_prop(prop, expect_priv)
end

-- input字符串按照delimiter进行分隔, 返回table
function cooling_utils.split(input, delimiter)
    if type(input) ~= 'string' or #input <= 0 then
        return nil
    end
    if type(delimiter) ~= 'string' or #delimiter <= 0 then
        return nil
    end
    local res = {}
    -- 使用 Lua 的 string.gmatch 函数进行字符串的拆分
    for match in string.gmatch(input, "([^" .. delimiter .. "]+)") do
        table.insert(res, match)
    end
    return res
end

function cooling_utils.parse_table_info(t)
    local str = ""
    for k, v in pairs(t) do
        str = str .. k .. ":" .. v .. " "
    end
    return str
end

-- 对嵌套的table数据进行扁平操作，即将{ {1, 2, 3}, {4, 5, 6} }数据变为{1, 2, 3, 4, 5, 6}
function cooling_utils.flatten_table(data)
    local res = {}
    for _, v in pairs(data) do
        if type(v) == 'table' then
            local flattened = cooling_utils.flatten_table(v)
            for _, inner_v in pairs(flattened) do
                table.insert(res, inner_v)
            end
        else
            table.insert(res, v)
        end
    end
    return res
end

function cooling_utils.average(t)
    local sum = 0
    local count = 0
    for _, value in pairs(t) do
        sum = sum + value
        count = count + 1
    end
    return sum / count
end

function cooling_utils.get_array_from_rpc_u8_array(arrays)
    local res = {}
    for i = 1, #arrays do
        res[i] = string.byte(arrays, i)
    end
    return res
end

function cooling_utils.get_max_value(t)
    local max = -math.huge
    for _, value in pairs(t) do
        if type(value) == 'number' and value > max then
            max = value
        end
    end
    return max
end

return Singleton(cooling_utils)