-- Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. 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 class = require 'mc.class'
local bs = require 'mc.bitstring'
local log = require 'mc.logging'
local pldm_standard = require 'protocol_open.protocol.pldm_standard'

local pldm_huawei = class(pldm_standard)
local huawei_manufacture_id<const> = 0x07DB
local pldm_oem_request_packet_type<const> = 0x3f

local response_bs<const> = bs.new([[<<
    manufacture_id:32/big,
    _:8,
    huawei_cmd_id:8,
    sub_cmd_id:8,
    data/string
>>]])

local request_bs<const> = bs.new([[<<
    pad:8,
    manufacture_id:32/big,
    _:8,
    huawei_cmd_id:8,
    sub_cmd_id:8,
    extra_cmd:8
>>]])

local request_params_template<const> = {
    command_code = true,
    huawei_cmd_id = true,
    sub_cmd_id = true,
    extra_cmd = true,
    data = true
}

function pldm_huawei:construct_request_data(ctx, request)
    ctx.manufacture_id = huawei_manufacture_id
    ctx.huawei_cmd_id = request.huawei_cmd_id
    ctx.sub_cmd_id = request.sub_cmd_id
    ctx.extra_cmd = request.extra_cmd or 0

    local data = request_bs:pack({
        pad = 0,
        manufacture_id = ctx.manufacture_id,
        huawei_cmd_id = ctx.huawei_cmd_id,
        sub_cmd_id = ctx.sub_cmd_id,
        extra_cmd = ctx.extra_cmd
    })

    return pldm_huawei.super.construct_request_data(self, ctx, {
        pldm_type = pldm_oem_request_packet_type,
        command_code = request.command_code,
        rsp_command_code = request.command_code, -- pldm的rsp command code与req command code一致
        data = data .. (request.data or '')
    })
end

function pldm_huawei:unpack_response_data(ctx, rsp_bin)
    if ctx.completion_code and ctx.completion_code ~= 0 then
        log:debug('[protocol %s]: unsuccessful request with completion_code: %s', self.name,
            ctx.completion_code)
        return nil
    end

    local rsp = response_bs:unpack(rsp_bin, true)

    if not rsp then
        log:debug('[protocol %s]: empty data received', self.name)
        return nil
    end

    if not rsp.manufacture_id or rsp.manufacture_id ~= huawei_manufacture_id then
        log:debug('[protocol %s]: invalid response data with wrong manufacture_id: %s', self.name,
            rsp.manufacture_id)
        return nil
    end

    if not rsp.huawei_cmd_id or rsp.huawei_cmd_id ~= ctx.huawei_cmd_id or not rsp.sub_cmd_id or
        rsp.sub_cmd_id ~= ctx.sub_cmd_id then
        log:debug(
            '[protocol %s]: invalid response data with cmd: huawei_cmd_id: %s, sub_cmd_id: %s',
            self.name, rsp.huawei_cmd_id, rsp.sub_cmd_id)
        return nil
    end

    return rsp.data
end

function pldm_huawei:ctor()
    self.name = 'pldm_huawei'
    self.request_params_template = request_params_template
end

return pldm_huawei
