-- 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: equipment customization
local log = require 'mc.logging'
local common = require 'sensor.sensor_common'
local cc = require 'sensor.sensor_const'
local oper = require 'sensor_operation'
local shm_data_mgmt = require 'shm_data_management'

local sensor_customize = {}

local DEFAULT_QUERY_NUMBER<const> = 2000
local DEFAULT_BASE_NUMBER<const> = 1

local CUSTOMIZE_IMPORT<const> = 0
local CUSTOMIZE_EXPORT<const> = 1

local function customize_query_sel_max_num(mode, mgr, value)
    -- 定制化导入
    if mode == CUSTOMIZE_IMPORT then
        local customize_flag = false
        local max_count = value or DEFAULT_QUERY_NUMBER
        if max_count ~= mgr.sel_info.QueryMaxCount then
            mgr.sel_info.QueryMaxCount = max_count
            shm_data_mgmt.update_max_query_count(max_count)
            customize_flag = true
        end
        return common.RET_OK, customize_flag
    end

    -- 定制化导出
    return common.RET_OK, mgr.sel_info.QueryMaxCount
end

local function customize_sel_mode(mode, mgr, value)
    -- 定制化导入
    if mode == CUSTOMIZE_IMPORT then
        local customize_flag = false
        local sel_mode = value == 'RotateAfterFull' and 1 or 0
        if mgr.sel_info.SelMode ~= sel_mode then
            mgr.sel_info.SelMode = sel_mode
            customize_flag = true
            require 'skynet'.fork_once(function ()
                mgr:clear_redundant_sel()
            end)
        end
        return common.RET_OK, customize_flag
    end

    -- 定制化导出
    local sel_mode_str = mgr.sel_info.SelMode == 1 and 'RotateAfterFull' or 'ClearAfterFull'
    return common.RET_OK, sel_mode_str
end

local function customize_dynamic_sensor_base_num(mode, mgr, value)
    -- 定制化导入
    if mode == CUSTOMIZE_IMPORT then
        local customize_flag = false
        local base_number = value or DEFAULT_BASE_NUMBER
        if mgr.sensor_number_base ~= base_number then
            mgr.sensor_number_base = base_number
            mgr.db:insert_persist_property(cc.SDR_DEVICE, cc.SENSOR_NUMBER_BASE, base_number)
            customize_flag = true
        end
        return common.RET_OK, customize_flag
    end

    -- 定制化导出
    local sdr_obj = mgr.db:query_persist_property(cc.SDR_DEVICE, cc.SENSOR_NUMBER_BASE)
    return common.RET_OK, sdr_obj and tonumber(sdr_obj.Value) or DEFAULT_BASE_NUMBER
end

local function customize_pef_enable(mode, mgr, value)
    -- 定制化导入
    if mode == CUSTOMIZE_IMPORT then
        local enable = value == 'on' and 1 or 0
        if mgr.config.Enabled ~= enable then
            mgr.config.Enabled = enable
            return common.RET_OK, true
        end
        return common.RET_OK, false
    end

    -- 定制化导出
    return common.RET_OK, mgr.config.Enabled == 1 and 'on' or 'off'
end

local customize_func_table = {
    ['BMCSet_QuerySELMaxNumValue'] = {
        customize_func = customize_query_sel_max_num,
        oper_key = oper.SEL_MAXNUM
    },
    ['BMCSet_SEL_Mode'] = {
        customize_func = customize_sel_mode,
        oper_key = oper.SEL_MODE
    },
    ['BMCSet_CustomDynamicSensorNumBase'] = {
        customize_func = customize_dynamic_sensor_base_num,
        oper_key = oper.SENSOR_NUMBASE
    },
    ['BMCSet_PEF_Enable'] = {
        customize_func = customize_pef_enable,
        oper_key = oper.PEF_ENABLE
    }
}

function sensor_customize.on_import(ctx, customize_data, customize_mgr)
    local customize_item, ok, flag
    for prop, data in pairs(customize_data) do
        customize_item = customize_func_table[prop]
        if not customize_item then
            log:error('import %s has no object to process', prop)
            goto continue
        end
        ok, flag = customize_item.customize_func(CUSTOMIZE_IMPORT, customize_mgr[prop], data.Value)
        if ok ~= common.RET_OK then
            log:error('import %s has error occured (%s) in customize config', prop, ok)
            oper.log(ctx, customize_item.oper_key, oper.FAILED)
            goto continue
        end
        log:notice('import %s successfully in customize config', prop)
        if flag then
            oper.log(ctx, customize_item.oper_key, oper.SUCCESS, data.Value)
        end
        ::continue::
    end
end

function sensor_customize.on_export(ctx, customize_mgr)
    local data = {}
    local ok, ret
    for prop, customize_item in pairs(customize_func_table) do
        ok, ret = customize_item.customize_func(CUSTOMIZE_EXPORT, customize_mgr[prop])
        if ok == common.RET_OK then
            log:notice('export %s successfully in customize config', prop)
        end
        data[prop] = ret
    end
    return data
end

return sensor_customize