-- 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 f_enum = require 'class.types.types'
local enums = require 'basic_cooling.define.cooling_enums'
local log = require 'mc.logging'
local props = require 'basic_cooling.define.cooling_properties'
local custom_msg = require 'messages.custom'
local utils = require 'basic_cooling.cooling_utils'
local cooling_policys = require 'basic_cooling.cooling_policys'

local ctl_mode = {
    [0] = enums.modes.Auto,
    [1] = enums.modes.Manual,
    [2] = enums.modes.Mixed,
    [enums.modes.Auto] = 0,
    [enums.modes.Manual] = 1,
    [enums.modes.Mixed] = 2
}

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,
    [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
}

local custom_temperature_type = {
    [f_enum.TemperatureType.Outlet:value()] = 'CustomOutlet',
    [f_enum.TemperatureType.Cpu:value()] = 'CustomCpuCorem',
    [f_enum.TemperatureType.Disk:value()] = 'CustomDisk',
    [f_enum.TemperatureType.Memory:value()] = 'CustomMemory',
    [f_enum.TemperatureType.NPUAiCore:value()] = 'CustomNpuAiCore',
    [f_enum.TemperatureType.NPUHbm:value()] = 'CustomNpuHbm',
    [f_enum.TemperatureType.PCH:value()] = 'CustomPCH',
    [f_enum.TemperatureType.VDDQ:value()] = 'CustomVDDQ',
    [f_enum.TemperatureType.VRD:value()] = 'CustomVRD',
    [f_enum.TemperatureType.SoCBoardOutlet:value()] = 'CustomSocBoardOutlet',
    [f_enum.TemperatureType.SoCBoardInlet:value()] = 'CustomSocBoardInlet'
}

local custom_speed_type = {
    [f_enum.PolicyType.InletCustom:value()] = 'CustomInlet',
    [f_enum.PolicyType.DiskCustom:value()] = 'CustomDisk'
}

local business_config = {}

local function import_mode(self, ctx, config_info)
    local value = config_info.Mode.Value
    if not value or not config_info.Mode.Import then
        return
    end
    value = ctl_mode[value]
    local pre_ctl_mode = self.interface_config_instance:get_fan_ctrl_mode()
    -- 导入手动模式，则设置为最大超时时间，其他模式超时时间属性不会被设置
    local ok = self.interface_config_instance:set_fan_ctrl_mode(ctx, value, 100000000)
    if not ok then
        local err_msg = string.format('/%s/%s/%s', 'Cooling', 'cooling', 'Mode')
        utils.op(ctx, 'Set control mode from [%s] to [%s] failed', pre_ctl_mode, value)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Set control mode from [%s] to [%s] successfully', pre_ctl_mode, value)
end

local function import_level(self, ctx, config_info)
    local value = config_info.Level.Value
    if not value or not config_info.Level.Import then
        return
    end
    local pre_maunal_level = self.interface_config_instance:get_fan_manual_level()
    local ok = self.interface_config_instance:set_fan_maunal_level(ctx, value)
    if not ok then
        local err_msg = string.format('/%s/%s/%s', 'Cooling', 'cooling', 'Mode')
        utils.op(ctx, 'Set fan level from [%s] to [%s] failed', pre_maunal_level, value)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Set fan level from [%s] to [%s] successfully', pre_maunal_level, value)
end

local function import_smart_cooling_mode(self, ctx, config_info)
    local smart_cooling_mode_mapping = {
        ['EnergySaving'] = 'energy saving', -- 节能模式
        ['LowNoise'] = 'low noise', -- 低噪模式
        ['HighPerformance'] = 'high performance', -- 高性能模式
        ['Custom'] = 'custom', -- 用户自定义模式
        ['LiquidCooling'] = 'liquid cooling' -- 液冷模式
    }
    local value = config_info.SmartCoolingMode.Value
    if not value or not config_info.SmartCoolingMode.Import then
        return
    end
    value = smart_cooling_mode[value]
    local pre_smart_cooling_mode = self.interface_config_instance:get_smart_cooling_mode()
    local ok = self.interface_config_instance:set_smart_cooling_mode(ctx, value)
    if not ok then
        local err_msg = string.format('/%s/%s/%s', 'Cooling', 'cooling', 'SmartCoolingMode')
        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
    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])
end

local function import_custom_t_obj_config(self, ctx, config_info, temp_type)
    local t_obj_name = custom_temperature_type[temp_type] .. 'Tobj'
    local t_obj = config_info[t_obj_name].Value
    if not t_obj then
        return
    end
    if not config_info[t_obj_name].Import then
        return
    end
    local ok, range = self.interface_config_instance:set_custom_target_temperature(ctx, temp_type, t_obj)
    if not ok then
        local err_msg = string.format('/%s/%s/%s', 'Cooling', 'cooling', t_obj_name)
        utils.op(ctx, 'Invalid configuration, custom temperature obj(type:%s) config (setting value is [%s], ' ..
            'range_min is [%s], range_max is [%s]) import failed', temp_type, t_obj, range[1], range[2])
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    utils.op(ctx, 'Custom temperature obj(type:%s) config (current value is [%s], ' ..
        'range_min is [%s], range_max is [%s]) import successfully', temp_type, t_obj, range[1], range[2])
end

local function import_inlet_env_range_l(self, ctx, config_info)
    local range = config_info.EnvRangeRdL.Value
    if not range or not config_info.EnvRangeRdL.Import then
        return
    end
    local temp_arr_s = ''
    local spd_arr_s = ''
    local temp_len = 0
    -- 导入数据格式为[4,0,20,30,40,20,50,70,80,90]
    -- 4后面4个表示温度区间，剩余表示转速区间
    for key, value in pairs(range) 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
        local err_msg = string.format('/%s/%s/%s', 'Policy1Class', 'CustomizedInletPolicy', 'EnvRangeRdL')
        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 inlet env temperature range [%s], speed range [%s] successfully',
        table.concat(temp_arr, ' '), table.concat(speed_arr, ' '))
end

local cooling_requirement_map = {
    ['TargetTemperatureCelsius'] = {
        name = 'TargetTemperatureCelsius'
    },
    ['FailoverPercent'] = {
        name = 'FailedValue'
    },
    ['ThresholdTemperatureCelsius'] = {
        name = 'MaxAllowedTemperatureCelsius'
    },
    ['SmartCoolingTargetTemperatureCelsius'] = {
        name = 'SmartCoolingTargetTemperatureCelsius'
    }
}

local function import_cooling_requirement(self, ctx, index, import_obj)
    local err_msg = string.format('/CoolingRequirement/%s', index)
    if not import_obj.Id or not import_obj.Id.Value then
        log:error('CoolingRequirement(index: %s) check failed, get cooling requirement id failed', index)
        utils.op(ctx, 'Set CoolingRequirement configuration information failed')
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local id = import_obj.Id.Value
    local source_tree_obj = self.interface_config_instance:get_cooling_requirement_obj_by_id(id)
    if not source_tree_obj then
        log:error('CoolingRequirement check failed, invalid cooling requirement(id: %s) obj', id)
        return
    end
    for import_name, source_tree_map in pairs(cooling_requirement_map) do
        if import_obj[import_name] and import_obj[import_name].Value and import_obj[import_name].Import then
            local ok = self.interface_config_instance:set_cooling_requirement_prop(
                ctx, source_tree_obj, source_tree_map.name, import_obj[import_name].Value
            )
            if not ok then
                err_msg = string.format('/CoolingRequirement/%s/%s', index, import_name)
                utils.op(ctx, 'Set CoolingRequirement(id: %s) %s to %s failed',
                    id, import_name, type(import_obj[import_name].Value) == 'table' and
                    '[' .. table.concat(import_obj[import_name].Value, ' ') .. ']' or
                    import_obj[import_name].Value)
                error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
            end
            utils.op(ctx, 'Set CoolingRequirement(id: %s) %s to %s successfully',
                id, import_name, type(import_obj[import_name].Value) == 'table' and
                '[' .. table.concat(import_obj[import_name].Value, ' ') .. ']' or
                import_obj[import_name].Value)
        end
    end
end

local cooling_policy_single_map = {
    ['Hysteresis'] = { name = 'Hysteresis' }
}

local cooling_policy_group_map = {
    ['TemperatureRangeCelsiusLow'] = { name = 'TemperatureRangeLow' },
    ['TemperatureRangeCelsiusHigh'] = { name = 'TemperatureRangeHigh' },
    ['PWMRangeLow'] = { name = 'SpeedRangeLow' },
    ['PWMRangeHigh'] = { name = 'SpeedRangeHigh' }
}

local function check_temperature_or_pwm_array(ctx, index, import_obj, name)
    -- 数组不进行导入，不做校验
    if not import_obj[name].Import then
        return
    end
    local err_msg = string.format('/CoolingRequirement/%s/%s', index, name)
    local MIN_ARRAY_LEN<const>, MAX_ARRAY_LEN<const> = 1, 63
    -- 温度区间、转速区间长度最小值（1）、最大值（63）
    if #import_obj[name].Value < MIN_ARRAY_LEN or #import_obj[name].Value > MAX_ARRAY_LEN then
        log:error('CoolingPolicy(id: %s) check failed, %s length is invalid, min(%s), max(%s)',
            import_obj.Id.Value, name, MIN_ARRAY_LEN, MAX_ARRAY_LEN)
        utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    if name == 'TemperatureRangeCelsiusLow' or name == 'TemperatureRangeCelsiusHigh' then
        -- 温度区间，参数合法性判断：升序排列
        if not utils.is_array_ascending(import_obj[name].Value) then
            log:error('CoolingPolicy(id: %s) check failed, %s must be in ascending order', import_obj.Id.Value, name)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
        -- 温度区间高数组右端点需要为127
        if name == 'TemperatureRangeCelsiusHigh' and import_obj[name].Value[#import_obj[name].Value] ~= 127 then
            log:error('CoolingPolicy(id: %s) check failed, the last digit of the array must be 127',
                import_obj.Id.Value)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
        -- 温度区间低数组左端点需要为-128或-127
        if name == 'TemperatureRangeCelsiusLow' and import_obj[name].Value[1] ~= -127 and
            import_obj[name].Value[1] ~= -128 then
            log:error('CoolingPolicy(id: %s) check failed, the first digit of the array must be -127 or -128',
                import_obj.Id.Value)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
    else
        -- 转速区间参数合法性判断：非降序排列
        if not utils.is_array_not_descending(import_obj[name].Value) then
            log:error('CoolingPolicy(id: %s) check failed, %s must be non-descending order', import_obj.Id.Value, name)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
    end
end

local function check_high_and_low_array(ctx, index, import_obj, low_array_name, high_array_name)
    -- 高低数组都不导入，不进行校验
    if not import_obj[low_array_name].Import and not import_obj[high_array_name].Import then
        return
    end
    local err_msg = string.format('/CoolingRequirement/%s', index)
    -- 温度区间和转速区间高低数组是否长度相等
    if #import_obj[low_array_name].Value ~= #import_obj[high_array_name].Value then
        log:error('CoolingPolicy(id: %s) check failed, the lengths of the low range and high range are not the same',
            import_obj.Id.Value)
        utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    for idx = 1, #import_obj[low_array_name].Value do
        -- 温度区间和转速区间是否低数组每一位都不大于高数组对应位置数值
        if import_obj[low_array_name].Value[idx] > import_obj[high_array_name].Value[idx] then
            log:error('CoolingPolicy(id: %s) check failed, temperature array or speed array (position %s) error',
                import_obj.Id.Value, idx)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
    end
end

local function check_temperature_and_pwm_array(ctx, index, import_obj)
    local err_msg = string.format('/CoolingRequirement/%s', index)
    -- 温度区间和转速区间数组长度是否相等
    if #import_obj.TemperatureRangeCelsiusLow.Value ~= #import_obj.PWMRangeLow.Value then
        log:error('CoolingPolicy(id: %s) check failed, the lengths of the temperature range and speed range ' ..
            'are not the same', import_obj.Id.Value)
        utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
end

local function check_temperature_and_pwm_range(ctx, index, import_obj, source_tree_obj)
    if (import_obj.TemperatureRangeCelsiusLow and import_obj.TemperatureRangeCelsiusLow.Import) or
        (import_obj.TemperatureRangeCelsiusHigh and import_obj.TemperatureRangeCelsiusHigh.Import) or
        (import_obj.PWMRangeLow and import_obj.PWMRangeLow.Import) or
        (import_obj.PWMRangeHigh and import_obj.PWMRangeHigh.Import) then
        -- 导入某一区间时，是否4个数组都存在
        if not import_obj.TemperatureRangeCelsiusLow or not import_obj.TemperatureRangeCelsiusHigh or
            not import_obj.PWMRangeLow or not import_obj.PWMRangeHigh then
            log:error('CoolingPolicy(id: %s) missing speed or temperature array', import_obj.Id.Value)
            utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', import_obj.Id.Value)
            local err_msg = string.format('/CoolingPolicy/%s', index)
            error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
        end
        check_temperature_or_pwm_array(ctx, index, import_obj, 'TemperatureRangeCelsiusLow')
        check_temperature_or_pwm_array(ctx, index, import_obj, 'TemperatureRangeCelsiusHigh')
        check_temperature_or_pwm_array(ctx, index, import_obj, 'PWMRangeLow')
        check_temperature_or_pwm_array(ctx, index, import_obj, 'PWMRangeHigh')
        check_high_and_low_array(ctx, index, import_obj, 'TemperatureRangeCelsiusLow', 'TemperatureRangeCelsiusHigh')
        check_high_and_low_array(ctx, index, import_obj, 'PWMRangeLow', 'PWMRangeHigh')
        check_temperature_and_pwm_array(ctx, index, import_obj)
        return true
    end
    return false
end

local function set_temperature_and_pwm_range(ctx, index, import_obj, source_tree_obj, id)
    local err_msg = string.format('/CoolingPolicy/%s', index)
    -- 检查曲线的温度和转速数组，失败则直接报错
    local check_result = check_temperature_and_pwm_range(ctx, index, import_obj, source_tree_obj)
    if not check_result then
        return
    end
    local temp_s = import_obj.TemperatureRangeCelsiusLow.Value
    local temp_low_left_border = import_obj.TemperatureRangeCelsiusLow.Value[1]
    table.remove(temp_s, 1)
    local speed_s = import_obj.PWMRangeLow.Value
    -- 把表转换为ascii码的字符串
    local temp_s_str = string.char(table.unpack(temp_s))
    local speed_s_str = string.char(table.unpack(speed_s))
    local cooling_policys_instance = cooling_policys.get_instance()
    local ok, rsp = pcall(cooling_policys_instance.SetCustomCoolingPolicy, cooling_policys_instance,
        source_tree_obj, ctx, temp_s_str, speed_s_str)
    table.insert(import_obj.TemperatureRangeCelsiusLow.Value, 1, temp_low_left_border)
    if not ok then
        log:error('set cooling policy(%s) failed, err_msg: %s', id, err_msg)
        utils.op(ctx, 'Set CoolingPolicy(id: %s) configuration information failed', id)
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    -- 打印操作日志
    for import_prop_name, _ in pairs(cooling_policy_group_map) do
        if import_obj[import_prop_name].Import and import_obj[import_prop_name].Value then
            utils.op(ctx, 'Set CoolingPolicy(id: %s) %s to %s successfully', id, import_prop_name,
                '[' .. table.concat(import_obj[import_prop_name].Value, ' ') .. ']')
        end
    end
end

local function import_cooling_policy(self, ctx, index, import_obj)
    local err_msg = string.format('/CoolingPolicy/%s', index)
    if not import_obj.Id or not import_obj.Id.Value then
        log:error('CoolingPolicy(index: %s) check failed, get cooling policy id failed', index)
        utils.op(ctx, 'Set CoolingPolicy configuration information failed')
        error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
    end
    local id = import_obj.Id.Value
    local source_tree_obj = self.interface_config_instance:get_policy_by_id(id)
    if not source_tree_obj then
        log:error('CoolingPolicy check failed, invalid cooling policy(id: %s) obj', id)
        return
    end
    for import_name, source_tree_map in pairs(cooling_policy_single_map) do
        if import_obj[import_name] and import_obj[import_name].Value and import_obj[import_name].Import then
            local ok = self.interface_config_instance:set_cooling_policy_prop(
                ctx, source_tree_obj, source_tree_map.name, import_obj[import_name].Value
            )
            if not ok then
                utils.op(ctx, 'Set CoolingPolicy(id: %s) %s to %s failed',
                    id, import_name, type(import_obj[import_name].Value) == 'table' and
                    '[' .. table.concat(import_obj[import_name].Value, ' ') .. ']' or import_obj[import_name].Value)
                error(custom_msg.CollectingConfigurationErrorDesc(err_msg))
            end
            utils.op(ctx, 'Set CoolingPolicy(id: %s) %s to %s successfully',
                id, import_name, type(import_obj[import_name].Value) == 'table' and
                '[' .. table.concat(import_obj[import_name].Value, ' ') .. ']' or import_obj[import_name].Value)
        end
    end
    set_temperature_and_pwm_range(ctx, index, import_obj, source_tree_obj, id)
end

local config_import_func_table = {
    ['Cooling'] = {
        ['Mode']                          = { config_func = import_mode },
        ['Level']                         = { config_func = import_level },
        ['SmartCoolingMode']              = { config_func = import_smart_cooling_mode },
        ['CustomOutletTobj']              = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.Outlet:value() },
        ['CustomOutletTobjRange']         = { config_func = nil },
        ['CustomCpuCoremTobj']            = { config_func = import_custom_t_obj_config,
                                           type        = f_enum.TemperatureType.Cpu:value() },
        ['CustomCpuCoremTobjRangeMax']    = { config_func = nil },
        ['CustomCpuCoremTobjRangeMin']    = { config_func = nil },
        ['CustomDiskTobj']                = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.Disk:value() },
        ['CustomDiskTobjRange']           = { config_func = nil },
        ['CustomMemoryTobj']              = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.Memory:value() },
        ['CustomMemoryTobjRange']         = { config_func = nil },
        ['CustomPCHTobj']                 = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.PCH:value() },
        ['CustomPCHTobjRange']            = { config_func = nil },
        ['CustomVRDTobj']                 = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.VRD:value() },
        ['CustomVRDTobjRange']            = { config_func = nil },
        ['CustomVDDQTobj']                = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.VDDQ:value() },
        ['CustomVDDQTobjRange']           = { config_func = nil },
        ['CustomNpuHbmTobj']              = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.NPUHbm:value() },
        ['CustomNpuHbmTobjRange']         = { config_func = nil },
        ['CustomNpuAiCoreTobj']           = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.NPUAiCore:value() },
        ['CustomNpuAiCoreTobjRange']      = { config_func = nil },
        ['CustomSocBoardInletTobj']       = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.SoCBoardInlet:value() },
        ['CustomSocBoardInletTobjRange']  = { config_func = nil },
        ['CustomSocBoardOutletTobj']      = { config_func = import_custom_t_obj_config,
                                              type        = f_enum.TemperatureType.SoCBoardOutlet:value() },
        ['CustomSocBoardOutletTobjRange'] = { config_func = nil },
    },
    ['Policy1Class'] = {
        ['EnvRangeRdL'] = {config_func = import_inlet_env_range_l }
    },
    ['CoolingRequirement'] = {
        config_func = import_cooling_requirement
    },
    ['CoolingPolicy'] = {
        config_func = import_cooling_policy
    }
}

local function add_custom_t_obj_config(self, ctx, rsp)
    local t_obj_name, range_name
    local custom_target_temperatures = self.interface_config_instance:get_custom_target_temperatures(ctx)
    for _, v in pairs(custom_target_temperatures) do
        if not custom_temperature_type[v.TemperatureType] then
            goto continue
        end
        t_obj_name = custom_temperature_type[v.TemperatureType] .. 'Tobj'
        range_name = t_obj_name .. 'Range'
        if v.TargetTemperatureCelsius == 0 then
            goto continue
        end
        rsp[t_obj_name] = v.TargetTemperatureCelsius
        if v.TemperatureType == f_enum.TemperatureType.Cpu:value() then
            rsp.CustomCpuCoremTobjRangeMin = v.MinTargetTemperatureCelsius
            rsp.CustomCpuCoremTobjRangeMax = v.MaxTargetTemperatureCelsius
        else
            rsp[range_name] = { v.MinTargetTemperatureCelsius, v.MaxTargetTemperatureCelsius }
        end
        ::continue::
    end
end

local function add_custom_speed_config(self, rsp)
    local policys = self.interface_config_instance:get_custom_policy()
    local obj_name
    for _, v in pairs(policys) do
        obj_name = custom_speed_type[v.PolicyType]
        if not obj_name then
            goto continue
        end
        rsp[obj_name .. 'SpeedRange'] = v[props.POLICY_SPEED_RANGE]
        ::continue::
    end
end

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

local function get_cooling_requirements(self)
    local requirements = {}
    local objs = self.interface_config_instance:get_cooling_requirement_objs()
    -- 配置导出时根据RequirementId进行排序
    table.sort(objs, function(a, b)
        return a.RequirementId < b.RequirementId
    end)
    for _, obj in pairs(objs) do
        if #obj[props.SMART_COOLING_TARTGET_TEMPERATURE] == 0 then
            requirements[#requirements + 1] = {
                Id = obj[props.REQUIREMENT_ID],
                TargetTemperatureCelsius = obj[props.TARGET_TEMP_CELSIUS],
                ThresholdTemperatureCelsius = obj[props.MAX_ALLOWED_TEMPERATURE_CELSIUS],
                FailoverPercent = obj[props.FAILED_VALUE]
            }
        else
            requirements[#requirements + 1] = {
                Id = obj[props.REQUIREMENT_ID],
                ThresholdTemperatureCelsius = obj[props.MAX_ALLOWED_TEMPERATURE_CELSIUS],
                SmartCoolingTargetTemperatureCelsius = obj[props.SMART_COOLING_TARTGET_TEMPERATURE],
                FailoverPercent = obj[props.FAILED_VALUE]
            }
        end
    end
    return requirements
end

local function get_cooling_policys(self)
    local policys = {}
    local objs = self.interface_config_instance:get_cooling_policy_objs()
    -- 配置导出时根据PolicyIdx进行排序
    table.sort(objs, function(a, b)
        return a.PolicyIdx < b.PolicyIdx
    end)
    for _, obj in pairs(objs) do
        -- 如果时自定义进风口或者硬盘温度曲线则不再普通曲线类中导出
        if obj[props.POLICY_TYPE] == enums.policy_type.Inlet or obj[props.POLICY_TYPE] == enums.policy_type.Disk then
            goto continue
        end
        policys[#policys + 1] = {
            Id = obj[props.POLICY_IDX],
            TemperatureRangeCelsiusLow = obj[props.POLICY_TEMP_RANGE_LOW],
            TemperatureRangeCelsiusHigh = obj[props.POLICY_TEMP_RANGE_HIGHT],
            PWMRangeLow = obj[props.POLICY_SPEED_RANGE_LOW],
            PWMRangeHigh = obj[props.POLICY_SPEED_RANGE_HIGH],
            Hysteresis = obj[props.HYSTERESIS]
        }
        ::continue::
    end
    return policys
end

-- 配置导入
function business_config.on_import(self, ctx, business_data)
    local import_table
    for name, config_info in pairs(business_data) do
        import_table = config_import_func_table[name]
        if not import_table then
            log:error('Import object[%s] is invalid', name)
            goto continue
        end
        if import_table.config_func then
            for index, obj in ipairs(config_info) do
                import_table.config_func(self, ctx, index, obj)
            end
            goto continue
        end
        for prop, _ in pairs(config_info) do
            if not import_table[prop] then
                log:error('Import prop [%s] is invalid', prop)
                goto next
            end
            if import_table[prop].config_func then
                import_table[prop].config_func(self, ctx, config_info, import_table[prop].type)
            end
            ::next::
        end
        log:notice('Import object [%s] successfully', name)
        ::continue::
    end
end

-- 配置导出
function business_config.on_export(self, ctx)
    local cooling_obj = {}
    local policy1class_obj = {}
    local data = {}
    cooling_obj.Mode = ctl_mode[self.interface_config_instance:get_fan_ctrl_mode()]
    cooling_obj.Level = self.interface_config_instance:get_fan_manual_level()
    cooling_obj.SmartCoolingMode = smart_cooling_mode[self.interface_config_instance:get_smart_cooling_mode()]
    add_custom_t_obj_config(self, ctx, cooling_obj)
    -- 自定义曲线
    add_custom_speed_config(self, cooling_obj)
    policy1class_obj.EnvRangeRdL = get_inlet_env_range_l(self)
    if next(cooling_obj) then
        data.Cooling = cooling_obj
    end
    if next(policy1class_obj) then
        data.Policy1Class = policy1class_obj
    end
    local cooling_requirements = get_cooling_requirements(self)
    if next(cooling_requirements) then
        data.CoolingRequirement = cooling_requirements
    end
    local cooling_policys = get_cooling_policys(self)
    if next(cooling_policys) then
        data.CoolingPolicy = cooling_policys
    end
    log:notice('Export Cooling, Policy1Class, CoolingRequirement and CoolingPolicy successfully')
    return data
end

return business_config