-- 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 c_fan_object = require 'fan_object'
local c_fan_type_object = require 'fan_type_object'
local log = require 'mc.logging'

local fans_manager = c_object('Fans')

local MIN_PWM = 10
local MAX_PWM = 100
local function is_valid_pwm(pwm)
    return pwm and pwm >= MIN_PWM and pwm <= MAX_PWM
end

local function cal_hardware_pwm(pwm_percent, max_supported_pwm)
    return math.floor(pwm_percent / 100 * max_supported_pwm + 0.5)
end

local function get_fan_pwm(fan_obj, pwm_percent)
    if not fan_obj:configurable() or not is_valid_pwm(pwm_percent) then
        return fan_obj.ExpectedPWM
    end
    -- 不在位风扇照常下发转速，不影响风扇组其它风扇调速
    return cal_hardware_pwm(pwm_percent, fan_obj.MaxSupportedPWM)
end

function fans_manager:ctor()
    self.fan_collection = {}
    self.t_pwm = {}
    self.l_pwm = {}
end

function fans_manager:set_pwm(l_pwm)
    for index, fan_obj in ipairs(self.fan_collection) do
        self.t_pwm[index] = get_fan_pwm(fan_obj, l_pwm[index])
    end
    return self.Fans.methods.SetFansPWM(self.t_pwm)
end

function fans_manager:check_standby()
    return self.WorkInStandby == 1
end

function fans_manager:set_standy_fan()
    if self:check_standby() then
        for _, fan_object in pairs(self.fan_collection) do
            fan_object.standbyfan = true
        end
    end
end

function fans_manager:get_fans_power()
    local total_power = 0
    local fan_type_object_table = c_fan_type_object.collection
    if not fan_type_object_table or not next(fan_type_object_table) then
        log:info('No fan type object found!')
        return 0
    end
    if not c_fan_object.collection or not next(c_fan_object) then
        log:info('No fan object found!')
        return 0
    end
    c_fan_object.collection:fold(function(_, fan_obj)
        local power = fan_obj:get_fan_power()
        total_power = total_power + power
    end)
    return total_power
end

function fans_manager:init()
    self:connect_signal(self.on_add_object_complete, function()
        self:next_tick(function()
            -- 同一个板子的风扇 position是相同的，从小到大存放fan_collection中
            self.fan_collection = c_fan_object.collection:fetch_by_position(self:get_position())
            table.sort(
                self.fan_collection,
                function (fan_1, fan_2)
                    return fan_1.FanId < fan_2.FanId
                end
            )
            self:set_standy_fan()
        end)
    end)
    fans_manager.super.init(self)
end

return fans_manager
