-- Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. 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 skynet = require 'skynet'
local log = require 'mc.logging'
local props = require 'basic_cooling.define.cooling_properties'
local cooling_enums = require 'basic_cooling.define.cooling_enums'
local fans_config = require 'basic_cooling.cooling_config.fans_config'
local external_data_keeping = require 'basic_cooling.data_keeping.external_data_keeping'
local cooling_group = require 'basic_cooling.cooling_device.cooling_group'
local fan_service = require 'fan_service'
local singleton = require 'mc.singleton'
local context = require 'mc.context'
local class = require 'mc.class'

local cooling_init_service = class()
local FAN_INIT_DEFAULT_LEVEL_MIN_VAL<const> = 50
local FAN_INIT_DEFAULT_LEVEL_MAX_VAL<const> = 100

function cooling_init_service:ctor(data)
    self.data = data
    self.fructl_data_keeping = external_data_keeping.get_instance().data_keeping_objs.fructl_data_keeping
    self.cooling_group = cooling_group.get_instance()
    self.fan_service_instance = fan_service.get_instance()
    self.bmc_soc_data_keeping = external_data_keeping.get_instance().data_keeping_objs.bmc_soc_data_keeping
    self.fans_config_instance = fans_config.get_instance()
end

-- 启动阶段初始化风扇转速
function cooling_init_service:init_fan_speed()
    local init_level -- 当定制转速拿到[50,99]时认为是被定制了
    local bmc_reset_type
    local power_state
    while true do
        -- 当config对象未分发时延时等待对象分发
        if self.fans_config_instance:get_obj() then
            init_level = self.fans_config_instance:get_init_level_in_startup()
            if init_level < FAN_INIT_DEFAULT_LEVEL_MIN_VAL or init_level > FAN_INIT_DEFAULT_LEVEL_MAX_VAL then
                init_level = FAN_INIT_DEFAULT_LEVEL_MAX_VAL
            end
        else
            goto continue
        end
        -- 获取bmc复位原因
        if not self.bmc_soc_data_keeping:get_bmc_reset_type() then
            goto continue
        else
            bmc_reset_type = self.bmc_soc_data_keeping:get_bmc_reset_type()
        end
        -- 硬复位场景，开机到进系统过程中,如果定制了转速，按照定制转速下发
        if bmc_reset_type == cooling_enums.bmc_reset_type.HARD_RESET then
            power_state = self.fructl_data_keeping:get_power_state()
            if power_state == cooling_enums.power_status.ONING or
                power_state == cooling_enums.power_status.ON then
                self:set_fan_level(init_level)
            end
            -- cooling组件pid调速启动的最基本的对象已经准备好
            if self.data.is_base_obj_added then
                self:set_fan_level(init_level)
                break
            end
        -- 软复位场景，在bmc启动到pid接管调速阶段，下发定制转速
        elseif bmc_reset_type == cooling_enums.bmc_reset_type.SOFT_RESET_UID or
            bmc_reset_type == cooling_enums.bmc_reset_type.SOFT_RESET_NORMAL then
            -- 若第一次进入时候已经准备好,那么也会下发一次转速，pid接管失败将保持此转速
            self:set_fan_level(init_level)
            -- cooling组件pid调速启动的最基本的对象已经准备好
            if self.data.is_base_obj_added then
                break
            end
        else
            -- bmc_reset_type为无效值，则直接进入正常调速
            if self.data.is_base_obj_added then
                break
            end
        end

        ::continue::
        skynet.sleep(500)
    end
    self.data.cooling_init_service_is_end = true
    log:notice('Bmc Reset Type(%s), init level(%s)', bmc_reset_type, init_level)
end
function cooling_init_service:init()
    skynet.fork_once(function()
        self:init_fan_speed()
    end)
end

-- 调用单个风扇下发转速接口下发定制转速
function cooling_init_service:set_fan_level(fan_level)
    -- 获取当前已经识别到的风扇，调用风扇的单独下发接口下发转速
    local fans_info = self.cooling_group:get_fans_info_with_fan_id()
    for _, fan_obj in pairs(fans_info) do
        local ok, rsp = pcall(function()
            return self.fan_service_instance:set_fan_pwm(fan_obj.SystemId, fan_obj.FanId, fan_level)
        end)
        if not ok then
            log:debug('Set fan(%d) pwm to %d failed, err_msg: %s', fan_obj.FanId, fan_level, rsp)
        elseif rsp ~= 0 then
            log:debug('Set fan(%d) pwm to %d failed, result: %s', fan_obj.FanId, fan_level, rsp)
        else
            log:debug('Set fan(%d) pwm to %d success', fan_obj.FanId, fan_level)
        end
    end
end

return singleton(cooling_init_service)