-- 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 ipmi = require 'manufacture.ipmi.cmds.StartDftTest'
local factory = require 'factory'
local context = require 'mc.context'
local mc_ipmi = require 'ipmi'
local log = require 'mc.logging'
local bs = require 'mc.bitstring'

local cc = mc_ipmi.types.Cc

local END_MASK<const> = 0x80
local COMMAND_INDEX_WITH_PARAM<const> = 0x2
local COMMAND_INDEX_WITH_PARAM2<const> = 0xA
local COMMAND_DFTID_WITH_PARAM2<const> = 0xE

local ipmi_handler = {}

local function response_error(code)
    return ipmi.StartDftTestRsp.new(code, END_MASK, "")
end

local req_dftid_tail_code = bs.new("<<slot_id:32, dev_num, param/string>>")
local req_index_tail_code = bs.new("<<param/string>>")

function ipmi_handler.get_test_item_info_by_long(req, HostId)
    local manufacture_service = factory.get_obj("manufacture_service")
    if req.Command >> 4 == COMMAND_INDEX_WITH_PARAM or req.Command >> 4 == COMMAND_INDEX_WITH_PARAM2 then
        local tail = req_index_tail_code:unpack(req.Tail)
        local obj = manufacture_service:get_obj_form_type_list_by_count(req.Type, req.Index, HostId)
        if not obj or not tail then
            return nil
        end
        obj.Param = tail.param
        return obj
    end
    local tail = req_dftid_tail_code:unpack(req.Tail)
    if not tail then
        return nil
    end
    local obj = manufacture_service:get_obj_by_dftid(req.Index, tail.slot_id, tail.dev_num, HostId)
    if not obj then
        return nil
    end
    if req.Command >> 4 == COMMAND_DFTID_WITH_PARAM2 then
        obj.Param = tail.param
    end
    return obj
end

function ipmi_handler.get_obj_by_req(req, HostId)
    if not req.Tail or req.Tail ~= "" then
        return ipmi_handler.get_test_item_info_by_long(req, HostId)
    end
    local manufacture_service = factory.get_obj("manufacture_service")
    -- 检查类型是否存在
    if not manufacture_service:check_type_exist(req.Type, HostId) then
        return nil
    end
    return manufacture_service:get_obj_form_type_list_by_count(req.Type, req.Index, HostId)
end

function ipmi_handler.start_dft_test(req, ctx)
    log:debug("start dft test")
    local obj = ipmi_handler.get_obj_by_req(req, ctx.HostId or 0)
    if not obj then
        return response_error(cc.InvalidFieldRequest)
    end
    local ok
    if req.Command & 1 ==  1 then
        ok = obj.pcall:Start_PACKED(context.new())
    else
        ok = obj.pcall:Stop_PACKED(context.new())
    end
    if not ok then
        return response_error(cc.InvalidFieldRequest)
    end
    return ipmi.StartDftTestRsp.new(cc.Success, END_MASK, obj.PrompteFinish)
end

function ipmi_handler.start_test_by_dftid(req)
    return response_error(cc.InvalidFieldRequest)
end

return ipmi_handler