-- 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 class = require 'mc.class'
local log = require 'mc.logging'
local singleton = require 'mc.singleton'
local libpid = require 'libpid'
local custom_msg = require 'messages.custom'

local CMD_SET_DEBUG_INFO<const> = 0x0f
local CMD_SET_PID_CONFIG<const> = 0x10
local CMD_CONFIG_INFO<const> = 1
local CMD_CONTROL_INFO<const> = 2
local ENABLED<const> = 1
local DISABLED<const> = 0
local SZ_WORD<const> = 2

---@class thermal_mgmt_mock
local thermal_mgmt_mock = class()

function thermal_mgmt_mock:ctor()
    
end

local function fill_table_byte(buff_t, offset, val)
    buff_t[offset] = val
    return offset + 1
end

local function fill_table_word(buff_t, offset, val)
    buff_t[offset] = val & 0xff
    buff_t[offset + 1] = (val >> 8) & 0xff
    return offset + 2
end

-- 封装writeinfo接口的10个命令头部的前6位
-- | lenLow | lenHigh | reversed | cmd | reserved cmd_lenLow | reserved cmd_lenHigh |
local function table_common_header(buff_t, cmd)
    local total_len = 0
    total_len = fill_table_word(buff_t, total_len, 0)
    total_len = fill_table_byte(buff_t, total_len, 0)
    total_len = fill_table_byte(buff_t, total_len, cmd)
    total_len = fill_table_word(buff_t, total_len, 0)
    return total_len
end

function thermal_mgmt_mock:get_pid_version()
    local buff_t = {}
    local total_len_offset = 0
    local cmd_len_offset = 4
    local total_len = table_common_header(buff_t, CMD_SET_DEBUG_INFO)
    total_len = fill_table_byte(buff_t, total_len, 0) -- sub cmd: print pid version
    total_len_offset = fill_table_word(buff_t, total_len_offset, total_len)
    cmd_len_offset = fill_table_word(buff_t, cmd_len_offset, total_len - SZ_WORD)
    log:notice('cmd_len_offset = %s, total_len_offset = %s', cmd_len_offset, total_len_offset)
    local ret = libpid.WriteInfo(total_len, buff_t)
    if ret ~= 0 then
        log:error('Print pid version failed, ret = %s', ret)
        error(custom_msg.OperationFailed())
    end
end

function thermal_mgmt_mock:set_print_info_enabled(info_type, info_enabled)
    if info_type ~= CMD_CONFIG_INFO and info_type ~= CMD_CONTROL_INFO then
        log:error('Set pid info tag failed, type value is out of range.')
        error(custom_msg.PropertyValueOutOfRange(info_type, '%Type'))
    end
    if info_enabled ~= ENABLED and info_enabled ~= DISABLED then
        log:error('Set pid info tag failed, enabled value is out of range.')
        error(custom_msg.PropertyValueOutOfRange(info_enabled, '%Enabled'))
    end
    local buff_t = {}
    local total_len_offset = 0
    local cmd_len_offset = 4
    local total_len = table_common_header(buff_t, CMD_SET_DEBUG_INFO)

    total_len = fill_table_byte(buff_t, total_len, info_type)
    total_len = fill_table_byte(buff_t, total_len, info_enabled)
    total_len_offset = fill_table_word(buff_t, total_len_offset, total_len)
    cmd_len_offset = fill_table_word(buff_t, cmd_len_offset, total_len - SZ_WORD)
    log:notice('cmd_len_offset = %s, total_len_offset = %s', cmd_len_offset, total_len_offset)
    local ret = libpid.WriteInfo(total_len, buff_t)
    if ret ~= 0 then
        log:error('Set pid info tag failed, ret = %s', ret)
        error(custom_msg.OperationFailed())
    end
    log:notice('Set pid %s info tag %s successfully', info_type == CMD_CONFIG_INFO and 'configuration' or 'control',
        info_enabled == ENABLED and 'enable' or 'disable')
end

function thermal_mgmt_mock:set_pid_config_enabled(support, enabled)
    if support ~= 0 then
        log:error('Set pid config failed')
        error(custom_msg.PropertyValueOutOfRange(support, '%ItemIndex'))
    end
    if enabled ~= ENABLED and enabled ~= DISABLED then
        log:error('Set pid config failed, item value must be 0 or 1')
        error(custom_msg.PropertyValueOutOfRange(enabled, '%ItemValue'))
    end
    local buff_t = {}
    local total_len_offset = 0
    local cmd_len_offset = 4
    local total_len = table_common_header(buff_t, CMD_SET_PID_CONFIG)
    
    total_len = fill_table_byte(buff_t, total_len, support)
    total_len = fill_table_byte(buff_t, total_len, enabled)
    total_len_offset = fill_table_word(buff_t, total_len_offset, total_len)
    cmd_len_offset = fill_table_word(buff_t, cmd_len_offset, total_len - SZ_WORD)
    log:notice('cmd_len_offset = %s, total_len_offset = %s', cmd_len_offset, total_len_offset)
    local ret = libpid.WriteInfo(total_len, buff_t)
    if ret ~= 0 then
        log:error('Set pid config failed, ret = %s', ret)
        error(custom_msg.OperationFailed())
    end
    log:notice('Set pid config %s successfully', enabled == ENABLED and 'enable' or 'disable')
end

return singleton(thermal_mgmt_mock)