-- 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 device_path = '/bmc/kepler/Chassis/1'
local device_interface = 'bmc.kepler.Chassis'
local cooling_config_path = '/bmc/kepler/Systems/1/CoolingConfig'
local cooling_config_interface = 'bmc.kepler.Systems.CoolingConfig'

local m = {}

function m.is_fan_device_supported()
    local ok, obj = pcall(mdb.get_object, bus, device_path, device_interface)
    if not ok then
        log:error('Invalid Path, err(%s)', obj)
        return false
    end
    for _, item in pairs(obj.DeviceSpecication) do
        if item[1] == 'Fan' and item[2] ~= 0 then
            return true
        end
    end
    log:error('The current device has no fans')
    return false
end

-- 解析fanMode
function m.parse_fan_mode(input)
    local delim = ','
    local comma_pos = string.find(input, delim) -- 查找第一个逗号的位置
    local prop = 'fanMode'
    if not comma_pos then
        if input == '0' then
            return {'Auto', 30}
        end
        if input == '1' then
            return {'Manual', 30}
        end
        if input == '2' then
            return {'Mixed', 30}
        end
        error(base_messages.PropertyValueFormatError(prop, input))
    else
        local mode = string.sub(input, 1, comma_pos - 1) -- 获取逗号前面的字符串
        local timeout = string.sub(input, comma_pos + 1) -- 获取逗号后面的字符串
        timeout = math.tointeger(timeout) -- timeout需要为整数
        if mode == '0' or mode == '2' then -- 数据格式为两段时，第一段只能为1
            error(base_messages.PropertyValueFormatError(prop, input))
        end
        if not timeout then -- 不能转换为整数
            error(base_messages.PropertyValueFormatError(prop, input))
        end
        if timeout < 0 or timeout > 300 then
            error(base_messages.PropertyValueFormatError(prop, input))
        end
        return {'Manual', timeout}
    end
end

function m.check_fan_level(fan_level, level_range)
    if fan_level < level_range[1] or fan_level > 100 then
        error(custom_messages.ValueOutOfRange(fan_level))
    end
    return true
end

-- 复用v2规则
-- 数据不在或获取失败，则MIB节点GET操作时返回成功，且输出按如下处理：
-- 整型类型节点：输出为-1
-- 字符串类型节点：输出为'\0'
-- 枚举类型节点：输出为unknown(1)
function m.get_fan_mode()
    if not m.is_fan_device_supported() then
        return '\0'
    end
    local ok, obj = pcall(mdb.get_object, bus, cooling_config_path, cooling_config_interface)
    if not ok or not obj.CtrlMode then
        log:error('Invalid path, err(%s)', obj)
        error(custom_messages.InvalidPath("******", "Content"))
    end
    if obj.CtrlMode == "Auto" then
        return "0"
    elseif obj.CtrlMode == "Manual" then
        return "1," .. tostring(obj.TimeOut)
    elseif obj.CtrlMode == "Mixed" then
        return "2"
    end
end

function m.get_fan_level()
    if not m.is_fan_device_supported() then
        return -1
    end
    local ok, obj = pcall(mdb.get_object, bus, cooling_config_path, cooling_config_interface)
    if not ok or not obj.CtrlMode or not obj.ManualLevel then
        log:error('Invalid path, err(%s)', obj)
        error(custom_messages.InvalidPath("******", "Content"))
    end
    if obj.CtrlMode == "Manual" then
        return obj.ManualLevel
    else
        return 255
    end
end

return m
