-- Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. 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 log = require 'mc.logging'
local f_enum = require 'class.types.types'
local enums = require 'basic_cooling.define.cooling_enums'
local utils = require 'basic_cooling.cooling_utils'
local custom_msg = require 'messages.custom'
local props = require 'basic_cooling.define.cooling_properties'

local customize_config = {}

-- 定制化出场SmartCooling模式
local function customize_cooling_mode(self, ctx, customize_data)
    local smart_cooling_mode = {
        [16] = enums.smart_cooling_mode.COOLING_ENERGY_SAVING_MODE,
        [17] = enums.smart_cooling_mode.COOLING_LOW_NOISE_MODE,
        [18] = enums.smart_cooling_mode.COOLING_HIGH_PERFORMANCE_MODE,
        [19] = enums.smart_cooling_mode.COOLING_CUSTOM_MODE,
    }
    local smart_cooling_mode_mapping = {
        ['EnergySaving'] = 'energy saving', -- 节能模式
        ['LowNoise'] = 'low noise', -- 低噪模式
        ['HighPerformance'] = 'high performance', -- 高性能模式
        ['Custom'] = 'custom', -- 用户自定义模式
        ['LiquidCooling'] = 'liquid cooling' -- 液冷模式
    }
    local value = customize_data.BMCSet_Thermal_Policy.Value
    value = smart_cooling_mode[value]
    local smart_cooling_enable = self.interface_config_instance:is_smart_cooling_enabled()
    local pre_smart_cooling_mode = self.interface_config_instance:get_smart_cooling_mode()
    local err_msg = string.format('/%s/%s', 'CustomSettings', 'BMCSet_Thermal_Policy')
    if not smart_cooling_enable or not pre_smart_cooling_mode then
        log:error('Smart cooling mode is disabled')
        utils.op(ctx, 'Set smart cooling mode of thermal enforce policy from %s to %s failed',
        smart_cooling_mode_mapping[pre_smart_cooling_mode], smart_cooling_mode_mapping[value])
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local ok = self.interface_config_instance:set_smart_cooling_mode(ctx, value)
    if ok then
        utils.op(ctx, 'Set smart cooling mode of thermal enforce policy from %s to %s successfully',
        smart_cooling_mode_mapping[pre_smart_cooling_mode], smart_cooling_mode_mapping[value])
    else
        utils.op(ctx, 'Set smart cooling mode of thermal enforce policy from %s to %s failed',
        smart_cooling_mode_mapping[pre_smart_cooling_mode], smart_cooling_mode_mapping[value])
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
end

-- 定制出厂自定义进风口调速曲线
local function customize_inlet_temp_level(self, ctx, customize_data)
    local err_msg = string.format('/%s/%s', 'CustomSettings', 'Custom_Inlet_Temp_Level')
    local smart_cooling_enable = self.interface_config_instance:is_smart_cooling_enabled()
    if not smart_cooling_enable then
        log:error('Smart cooling mode is disabled')
        utils.op(ctx, 'Set inlet env temperature level failed')
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local inlet_temp_policy_str = customize_data.Custom_Inlet_Temp_Level.Value
    local inlet_temp_policy = utils.split(inlet_temp_policy_str, ',')
    if not inlet_temp_policy then
        log:error('Customize inlet temp level failed, data(%s) is invalid', inlet_temp_policy_str)
        utils.op(ctx, 'Set inlet env temperature level failed')
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local temp_arr_s = ''
    local spd_arr_s = ''
    local temp_len = 0
    for key, value in pairs(inlet_temp_policy) do
        if key == 1 then
            temp_len = value
            goto continue
        end
        if key <= (temp_len + 1) then
            temp_arr_s = temp_arr_s .. string.char(value)
        else
            spd_arr_s = spd_arr_s .. string.char(value)
        end
        ::continue::
    end
    local temp_arr = { string.byte(temp_arr_s, 1, #temp_arr_s) }
    local speed_arr = { string.byte(spd_arr_s, 1, #spd_arr_s) }
    local ok = self.interface_config_instance:set_custom_inlet_policy(ctx, temp_arr_s, spd_arr_s)
    if not ok then
        utils.op(ctx, 'Set inlet env temperature range [%s], speed range [%s] failed',
            table.concat(temp_arr, ' '), table.concat(speed_arr, ' '))
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Set temperature range [%s], speed range [%s] successfully',
        table.concat(temp_arr, ' '), table.concat(speed_arr, ' '))
end

-- 自定义目标调速
local function customize_obj_temp(self, ctx, customize_data, type)
    local custom_temperature_type ={
        [f_enum.TemperatureType.Outlet:value()] = 'Custom_OutletObjTem',
        [f_enum.TemperatureType.Cpu:value()] = 'Custom_CoreRemObjTem'
    }
    local t_obj_name = custom_temperature_type[type]
    local t_obj = customize_data[t_obj_name].Value
    local err_msg = string.format("/%s/%s", 'CustomSettings', t_obj_name)
    local smart_cooling_enable = self.interface_config_instance:is_smart_cooling_enabled()
    if not smart_cooling_enable then
        log:error('Smart cooling mode is disabled')
        utils.op(ctx, 'Customize obj(%s) temperature(%s) failed', t_obj_name, t_obj)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local ok, _ = self.interface_config_instance:set_custom_target_temperature(ctx, type, t_obj)
    if not ok then
        utils.op(ctx, 'Customize obj(%s) temperature(%s) failed', t_obj_name, t_obj)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Customize obj(%s) temperature(%s) successfully', t_obj_name, t_obj)
end

-- 出厂定制AC上电通电开机场景风扇速率比
local function customize_fan_init_default_level(self, ctx, customize_data)
    local err_msg = string.format("/%s/%s", 'CustomSettings', 'BMCSet_FanInitDefaultLevel')
    local level = customize_data.BMCSet_FanInitDefaultLevel.Value
    local ok = self.interface_config_instance:set_init_level_in_startup(ctx, level)
    if not ok then
        utils.op(ctx, 'Customize fan init default level(%s) failed', level)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Customize fan init default level(%s) successfully', level)
end

local config_customize_func_table = {
    ['BMCSet_Thermal_Policy'] = { customize_func = customize_cooling_mode },
    ['Custom_Inlet_Temp_Level'] = { customize_func = customize_inlet_temp_level },
    ['Custom_CoreRemObjTem'] = { customize_func = customize_obj_temp, type = f_enum.TemperatureType.Cpu:value() },
    ['Custom_OutletObjTem'] = { customize_func = customize_obj_temp, type = f_enum.TemperatureType.Outlet:value() },
    ['BMCSet_FanInitDefaultLevel'] = { customize_func = customize_fan_init_default_level }
}

-- 配置导入
function customize_config.on_import(self, ctx, customize_data)
    for prop, _ in pairs(customize_data) do
        local customize_table = config_customize_func_table[prop]
        if not customize_table then
            log:error('Customize prop [%s] is invalid', prop)
            goto continue
        end
        if customize_table.customize_func then
            customize_table.customize_func(self, ctx, customize_data, customize_table.type)
        end
        ::continue::
    end
end

local function get_custom_inlet_temp_level(self)
    local inlet_policy_obj = self.interface_config_instance:get_custom_inlet_policy()
    if not inlet_policy_obj then
        return nil
    end
    local inlet_env_range = ""
    local temp_arr = inlet_policy_obj[props.POLICY_TEMP_RANGE_LOW]
    local spd_arr = inlet_policy_obj[props.POLICY_SPEED_RANGE_HIGH]
    -- 导出数据格式为（4，0，20，30，40，20，50，70，80，90）
    -- 4后面4个表示温度区间，剩余表示转速区间
    inlet_env_range = inlet_env_range .. (#temp_arr - 1)
    for key, value in pairs(temp_arr) do
        if key ~= 1 then
            inlet_env_range = inlet_env_range .. ',' .. value
        end
    end
    for _, value in pairs(spd_arr) do
        inlet_env_range = inlet_env_range .. ',' .. value
    end
    return inlet_env_range
end

local function get_custom_target_temp(self, ctx)
    local rsp = {}
    local custom_target_temperatures = self.interface_config_instance:get_custom_target_temperatures(ctx)
    for _, obj in pairs(custom_target_temperatures) do
        if obj.TemperatureType == 1 then
            rsp.Custom_CoreRemObjTem = obj.TargetTemperatureCelsius
        elseif obj.TemperatureType == 2 then
            rsp.Custom_OutletObjTem = obj.TargetTemperatureCelsius
        end
    end
    return rsp
end

-- 配置导出
function customize_config.on_export(self, ctx)
    -- 获取自定义目标温度值（CPU核温和出风口）
    local ret = get_custom_target_temp(self, ctx)
    local smart_cooling_mode = {
        [enums.smart_cooling_mode.COOLING_ENERGY_SAVING_MODE] = 16,
        [enums.smart_cooling_mode.COOLING_LOW_NOISE_MODE] = 17,
        [enums.smart_cooling_mode.COOLING_HIGH_PERFORMANCE_MODE] = 18,
        [enums.smart_cooling_mode.COOLING_CUSTOM_MODE] = 19
    }
    -- 获取SmartCooling调速模式
    local smart_cooling_mode_str = self.interface_config_instance:get_smart_cooling_mode()
    ret.BMCSet_Thermal_Policy = smart_cooling_mode[smart_cooling_mode_str]
    -- 获取开机风扇默认转速
    ret.BMCSet_FanInitDefaultLevel = self.interface_config_instance:get_init_level_in_startup()
    -- 获取自定义进风口调速曲线
    ret.Custom_Inlet_Temp_Level = get_custom_inlet_temp_level(self)
    log:notice('Export customize config successfully')
    return ret
end

return customize_config