-- 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 c_object = require 'mc.orm.object'
local log = require 'mc.logging'
local c_fan_group_object = require 'fan_group_object'
local fan_group_policy_object = c_object('FanGroupPolicy')

local DEFAULT_SPEED_PERCENT_DIFFERENCE<const> = 32767
local MAX_SPEED_PERCENT<const> = 100

function fan_group_policy_object:init()
    self:connect_signal(self.on_add_object_complete, function()
        log:notice('add FanGroupPolicy object complete, '..
            'Id:%d, PolicyType:%s, FanGroupIds:%s, RelativeGroupIds:%s, SpeedPercentDifference:%s',
            self.Id, self.PolicyType, table.concat(self.FanGroupIds, ' '),
            table.concat(self.RelativeGroupIds, ' '), self.SpeedPercentDifference)
    end)
    fan_group_policy_object.super.init(self)
end

function fan_group_policy_object:fan_group_speed_adjust(fan_table)
    -- 0表示自动调速，1表示手动调速，如果是通过手动调速下发则不做转速修正
    if not fan_table[0] or fan_table[0] == 1 then
        fan_table[0] = nil
        return fan_table
    end

    -- 第0位作为中间变量在此时取消赋值
    fan_table[0] = nil
    if not self.SpeedPercentDifference or
        self.SpeedPercentDifference == DEFAULT_SPEED_PERCENT_DIFFERENCE then
        return fan_table
    end

    -- 目前仅支持类型1和2
    if self.PolicyType ~= 1 and self.PolicyType ~= 2 then
        return fan_table
    end

    c_fan_group_object.collection:fold(function (_, fan_group_obj)
        local max_level = 0 --风扇组的最大转速
        for _, slot in pairs(fan_group_obj.FanSlots) do
            -- 每个风扇组的转速取当前组内风扇的最大值
            max_level = math.max(max_level, fan_table[slot] or 0)
        end
        fan_group_obj.SpeedPercent = max_level
    end)

    if self.PolicyType == 2 then
        return self:adjust_fan_speed_by_policy2(fan_table)
    end
    return fan_table
end

function fan_group_policy_object:adjust_fan_speed_by_policy2(fan_table)
    -- 策略2要求2个数组属性都要有值
    if not next(self.FanGroupIds) or not next(self.RelativeGroupIds) then
        return fan_table
    end
    local relative_groups_max_level = 0
    c_fan_group_object.collection:fold(function (_, fan_group_obj)
        for _, group_id in ipairs(self.RelativeGroupIds) do
            if fan_group_obj.Id == group_id then
                relative_groups_max_level = math.max(relative_groups_max_level, fan_group_obj.SpeedPercent)
                break
            end
        end
    end)
    
    c_fan_group_object.collection:fold(function (_, fan_group_obj)
        for _, group_id in ipairs(self.FanGroupIds) do
            -- 风扇最大转速比不能高于100
            fan_group_obj.SpeedPercent = math.max(
                fan_group_obj.SpeedPercent, relative_groups_max_level + self.SpeedPercentDifference
            )
            fan_group_obj.SpeedPercent =
                fan_group_obj.SpeedPercent <= MAX_SPEED_PERCENT and fan_group_obj.SpeedPercent or MAX_SPEED_PERCENT
        end
    end)

    -- 每个风扇的转速赋值
    c_fan_group_object.collection:fold(function (_, fan_group_obj)
        -- 仅对FanGroupIds里的风扇组风扇做转速差修正
        for _, fan_group_id in pairs(self.FanGroupIds) do
            if fan_group_obj.Id ~= fan_group_id then
                goto continue
            end

            for _, slot in pairs(fan_group_obj.FanSlots) do
                -- 组件接收到的转速表存在该slot位置的转速才做赋值，即不对初始转速表做新增与删除
                fan_table[slot] = fan_table[slot] and fan_group_obj.SpeedPercent or nil
            end

            ::continue::
        end
    end)
    return fan_table
end

return fan_group_policy_object