-- 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 validate = require 'mc.validate'
local utils = require 'mc.utils'
local mdb = require 'mc.mdb'

local NVMe = {}

---@class NVMe.LifeUsedPercentage
---@field LifeUsedPercentage integer
local TLifeUsedPercentage = {}
TLifeUsedPercentage.__index = TLifeUsedPercentage
TLifeUsedPercentage.group = {}

local function TLifeUsedPercentage_from_obj(obj)
    return setmetatable(obj, TLifeUsedPercentage)
end

function TLifeUsedPercentage.new(LifeUsedPercentage)
    return TLifeUsedPercentage_from_obj({LifeUsedPercentage = LifeUsedPercentage})
end
---@param obj NVMe.LifeUsedPercentage
function TLifeUsedPercentage:init_from_obj(obj)
    self.LifeUsedPercentage = obj.LifeUsedPercentage
end

function TLifeUsedPercentage:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TLifeUsedPercentage.group)
end

TLifeUsedPercentage.from_obj = TLifeUsedPercentage_from_obj

TLifeUsedPercentage.proto_property = {'LifeUsedPercentage'}

TLifeUsedPercentage.default = {0}

TLifeUsedPercentage.struct = {{name = 'LifeUsedPercentage', is_array = false, struct = nil}}

function TLifeUsedPercentage:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'LifeUsedPercentage', self.LifeUsedPercentage, 'uint8', true, errs, need_convert)

    TLifeUsedPercentage:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TLifeUsedPercentage.proto_property, errs, need_convert)
    return self
end

function TLifeUsedPercentage:unpack(_)
    return self.LifeUsedPercentage
end

NVMe.LifeUsedPercentage = TLifeUsedPercentage

---@class NVMe.GetIdentifyDataRsp
---@field MessageResponse integer[]
local TGetIdentifyDataRsp = {}
TGetIdentifyDataRsp.__index = TGetIdentifyDataRsp
TGetIdentifyDataRsp.group = {}

local function TGetIdentifyDataRsp_from_obj(obj)
    return setmetatable(obj, TGetIdentifyDataRsp)
end

function TGetIdentifyDataRsp.new(MessageResponse)
    return TGetIdentifyDataRsp_from_obj({MessageResponse = MessageResponse})
end
---@param obj NVMe.GetIdentifyDataRsp
function TGetIdentifyDataRsp:init_from_obj(obj)
    self.MessageResponse = obj.MessageResponse
end

function TGetIdentifyDataRsp:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetIdentifyDataRsp.group)
end

TGetIdentifyDataRsp.from_obj = TGetIdentifyDataRsp_from_obj

TGetIdentifyDataRsp.proto_property = {'MessageResponse'}

TGetIdentifyDataRsp.default = {{}}

TGetIdentifyDataRsp.struct = {{name = 'MessageResponse', is_array = true, struct = nil}}

function TGetIdentifyDataRsp:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.OptionalArray(prefix .. 'MessageResponse', self.MessageResponse, 'uint8', false, errs, need_convert)

    TGetIdentifyDataRsp:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetIdentifyDataRsp.proto_property, errs, need_convert)
    return self
end

function TGetIdentifyDataRsp:unpack(_)
    return self.MessageResponse
end

NVMe.GetIdentifyDataRsp = TGetIdentifyDataRsp

---@class NVMe.GetIdentifyDataReq
---@field CNSValue integer
local TGetIdentifyDataReq = {}
TGetIdentifyDataReq.__index = TGetIdentifyDataReq
TGetIdentifyDataReq.group = {}

local function TGetIdentifyDataReq_from_obj(obj)
    return setmetatable(obj, TGetIdentifyDataReq)
end

function TGetIdentifyDataReq.new(CNSValue)
    return TGetIdentifyDataReq_from_obj({CNSValue = CNSValue})
end
---@param obj NVMe.GetIdentifyDataReq
function TGetIdentifyDataReq:init_from_obj(obj)
    self.CNSValue = obj.CNSValue
end

function TGetIdentifyDataReq:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetIdentifyDataReq.group)
end

TGetIdentifyDataReq.from_obj = TGetIdentifyDataReq_from_obj

TGetIdentifyDataReq.proto_property = {'CNSValue'}

TGetIdentifyDataReq.default = {0}

TGetIdentifyDataReq.struct = {{name = 'CNSValue', is_array = false, struct = nil}}

function TGetIdentifyDataReq:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'CNSValue', self.CNSValue, 'uint8', false, errs, need_convert)

    TGetIdentifyDataReq:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetIdentifyDataReq.proto_property, errs, need_convert)
    return self
end

function TGetIdentifyDataReq:unpack(_)
    return self.CNSValue
end

NVMe.GetIdentifyDataReq = TGetIdentifyDataReq

---@class NVMe.GetTelemetryDataRsp
---@field TaskId integer
local TGetTelemetryDataRsp = {}
TGetTelemetryDataRsp.__index = TGetTelemetryDataRsp
TGetTelemetryDataRsp.group = {}

local function TGetTelemetryDataRsp_from_obj(obj)
    return setmetatable(obj, TGetTelemetryDataRsp)
end

function TGetTelemetryDataRsp.new(TaskId)
    return TGetTelemetryDataRsp_from_obj({TaskId = TaskId})
end
---@param obj NVMe.GetTelemetryDataRsp
function TGetTelemetryDataRsp:init_from_obj(obj)
    self.TaskId = obj.TaskId
end

function TGetTelemetryDataRsp:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetTelemetryDataRsp.group)
end

TGetTelemetryDataRsp.from_obj = TGetTelemetryDataRsp_from_obj

TGetTelemetryDataRsp.proto_property = {'TaskId'}

TGetTelemetryDataRsp.default = {0}

TGetTelemetryDataRsp.struct = {{name = 'TaskId', is_array = false, struct = nil}}

function TGetTelemetryDataRsp:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'TaskId', self.TaskId, 'uint32', false, errs, need_convert)

    TGetTelemetryDataRsp:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetTelemetryDataRsp.proto_property, errs, need_convert)
    return self
end

function TGetTelemetryDataRsp:unpack(_)
    return self.TaskId
end

NVMe.GetTelemetryDataRsp = TGetTelemetryDataRsp

---@class NVMe.GetTelemetryDataReq
---@field DataType string
local TGetTelemetryDataReq = {}
TGetTelemetryDataReq.__index = TGetTelemetryDataReq
TGetTelemetryDataReq.group = {}

local function TGetTelemetryDataReq_from_obj(obj)
    return setmetatable(obj, TGetTelemetryDataReq)
end

function TGetTelemetryDataReq.new(DataType)
    return TGetTelemetryDataReq_from_obj({DataType = DataType})
end
---@param obj NVMe.GetTelemetryDataReq
function TGetTelemetryDataReq:init_from_obj(obj)
    self.DataType = obj.DataType
end

function TGetTelemetryDataReq:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetTelemetryDataReq.group)
end

TGetTelemetryDataReq.from_obj = TGetTelemetryDataReq_from_obj

TGetTelemetryDataReq.proto_property = {'DataType'}

TGetTelemetryDataReq.default = {''}

TGetTelemetryDataReq.struct = {{name = 'DataType', is_array = false, struct = nil}}

function TGetTelemetryDataReq:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'DataType', self.DataType, 'string', false, errs, need_convert)

    if self.DataType ~= nil then
        validate.Enum(prefix .. 'DataType', self.DataType, '', {'Host', 'Controller'}, errs, need_convert)
    end

    TGetTelemetryDataReq:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetTelemetryDataReq.proto_property, errs, need_convert)
    return self
end

function TGetTelemetryDataReq:unpack(_)
    return self.DataType
end

NVMe.GetTelemetryDataReq = TGetTelemetryDataReq

---@class NVMe.SendNvmeMICommandRsp
---@field Status integer
---@field NVMeResponse integer
---@field ResponseData integer[]
local TSendNvmeMICommandRsp = {}
TSendNvmeMICommandRsp.__index = TSendNvmeMICommandRsp
TSendNvmeMICommandRsp.group = {}

local function TSendNvmeMICommandRsp_from_obj(obj)
    return setmetatable(obj, TSendNvmeMICommandRsp)
end

function TSendNvmeMICommandRsp.new(Status, NVMeResponse, ResponseData)
    return TSendNvmeMICommandRsp_from_obj({Status = Status, NVMeResponse = NVMeResponse, ResponseData = ResponseData})
end
---@param obj NVMe.SendNvmeMICommandRsp
function TSendNvmeMICommandRsp:init_from_obj(obj)
    self.Status = obj.Status
    self.NVMeResponse = obj.NVMeResponse
    self.ResponseData = obj.ResponseData
end

function TSendNvmeMICommandRsp:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TSendNvmeMICommandRsp.group)
end

TSendNvmeMICommandRsp.from_obj = TSendNvmeMICommandRsp_from_obj

TSendNvmeMICommandRsp.proto_property = {'Status', 'NVMeResponse', 'ResponseData'}

TSendNvmeMICommandRsp.default = {0, 0, {}}

TSendNvmeMICommandRsp.struct = {
    {name = 'Status', is_array = false, struct = nil}, {name = 'NVMeResponse', is_array = false, struct = nil},
    {name = 'ResponseData', is_array = true, struct = nil}
}

function TSendNvmeMICommandRsp:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'Status', self.Status, 'uint8', false, errs, need_convert)
    validate.Optional(prefix .. 'NVMeResponse', self.NVMeResponse, 'uint32', false, errs, need_convert)
    validate.OptionalArray(prefix .. 'ResponseData', self.ResponseData, 'uint8', false, errs, need_convert)

    TSendNvmeMICommandRsp:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TSendNvmeMICommandRsp.proto_property, errs, need_convert)
    return self
end

function TSendNvmeMICommandRsp:unpack(_)
    return self.Status, self.NVMeResponse, self.ResponseData
end

NVMe.SendNvmeMICommandRsp = TSendNvmeMICommandRsp

---@class NVMe.SendNvmeMICommandReq
---@field Opcode integer
---@field Dword0 integer
---@field Dword1 integer
---@field RequestData integer[]
local TSendNvmeMICommandReq = {}
TSendNvmeMICommandReq.__index = TSendNvmeMICommandReq
TSendNvmeMICommandReq.group = {}

local function TSendNvmeMICommandReq_from_obj(obj)
    return setmetatable(obj, TSendNvmeMICommandReq)
end

function TSendNvmeMICommandReq.new(Opcode, Dword0, Dword1, RequestData)
    return
        TSendNvmeMICommandReq_from_obj({Opcode = Opcode, Dword0 = Dword0, Dword1 = Dword1, RequestData = RequestData})
end
---@param obj NVMe.SendNvmeMICommandReq
function TSendNvmeMICommandReq:init_from_obj(obj)
    self.Opcode = obj.Opcode
    self.Dword0 = obj.Dword0
    self.Dword1 = obj.Dword1
    self.RequestData = obj.RequestData
end

function TSendNvmeMICommandReq:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TSendNvmeMICommandReq.group)
end

TSendNvmeMICommandReq.from_obj = TSendNvmeMICommandReq_from_obj

TSendNvmeMICommandReq.proto_property = {'Opcode', 'Dword0', 'Dword1', 'RequestData'}

TSendNvmeMICommandReq.default = {0, 0, 0, {}}

TSendNvmeMICommandReq.struct = {
    {name = 'Opcode', is_array = false, struct = nil}, {name = 'Dword0', is_array = false, struct = nil},
    {name = 'Dword1', is_array = false, struct = nil}, {name = 'RequestData', is_array = true, struct = nil}
}

function TSendNvmeMICommandReq:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'Opcode', self.Opcode, 'uint8', false, errs, need_convert)
    validate.Optional(prefix .. 'Dword0', self.Dword0, 'uint32', false, errs, need_convert)
    validate.Optional(prefix .. 'Dword1', self.Dword1, 'uint32', false, errs, need_convert)
    validate.OptionalArray(prefix .. 'RequestData', self.RequestData, 'uint8', false, errs, need_convert)

    TSendNvmeMICommandReq:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TSendNvmeMICommandReq.proto_property, errs, need_convert)
    return self
end

function TSendNvmeMICommandReq:unpack(_)
    return self.Opcode, self.Dword0, self.Dword1, self.RequestData
end

NVMe.SendNvmeMICommandReq = TSendNvmeMICommandReq

---@class NVMe.GetSmartInfoRsp
---@field MessageResponse integer[]
local TGetSmartInfoRsp = {}
TGetSmartInfoRsp.__index = TGetSmartInfoRsp
TGetSmartInfoRsp.group = {}

local function TGetSmartInfoRsp_from_obj(obj)
    return setmetatable(obj, TGetSmartInfoRsp)
end

function TGetSmartInfoRsp.new(MessageResponse)
    return TGetSmartInfoRsp_from_obj({MessageResponse = MessageResponse})
end
---@param obj NVMe.GetSmartInfoRsp
function TGetSmartInfoRsp:init_from_obj(obj)
    self.MessageResponse = obj.MessageResponse
end

function TGetSmartInfoRsp:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetSmartInfoRsp.group)
end

TGetSmartInfoRsp.from_obj = TGetSmartInfoRsp_from_obj

TGetSmartInfoRsp.proto_property = {'MessageResponse'}

TGetSmartInfoRsp.default = {{}}

TGetSmartInfoRsp.struct = {{name = 'MessageResponse', is_array = true, struct = nil}}

function TGetSmartInfoRsp:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.OptionalArray(prefix .. 'MessageResponse', self.MessageResponse, 'uint8', false, errs, need_convert)

    TGetSmartInfoRsp:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetSmartInfoRsp.proto_property, errs, need_convert)
    return self
end

function TGetSmartInfoRsp:unpack(_)
    return self.MessageResponse
end

NVMe.GetSmartInfoRsp = TGetSmartInfoRsp

---@class NVMe.GetSmartInfoReq
---@field Vendor integer
local TGetSmartInfoReq = {}
TGetSmartInfoReq.__index = TGetSmartInfoReq
TGetSmartInfoReq.group = {}

local function TGetSmartInfoReq_from_obj(obj)
    return setmetatable(obj, TGetSmartInfoReq)
end

function TGetSmartInfoReq.new(Vendor)
    return TGetSmartInfoReq_from_obj({Vendor = Vendor})
end
---@param obj NVMe.GetSmartInfoReq
function TGetSmartInfoReq:init_from_obj(obj)
    self.Vendor = obj.Vendor
end

function TGetSmartInfoReq:remove_error_props(errs, obj)
    utils.remove_obj_error_property(obj, errs, TGetSmartInfoReq.group)
end

TGetSmartInfoReq.from_obj = TGetSmartInfoReq_from_obj

TGetSmartInfoReq.proto_property = {'Vendor'}

TGetSmartInfoReq.default = {0}

TGetSmartInfoReq.struct = {{name = 'Vendor', is_array = false, struct = nil}}

function TGetSmartInfoReq:validate(prefix, errs, need_convert)
    prefix = prefix or ''

    validate.Optional(prefix .. 'Vendor', self.Vendor, 'uint16', false, errs, need_convert)

    TGetSmartInfoReq:remove_error_props(errs, self)
    validate.CheckUnknowProperty(self, TGetSmartInfoReq.proto_property, errs, need_convert)
    return self
end

function TGetSmartInfoReq:unpack(_)
    return self.Vendor
end

NVMe.GetSmartInfoReq = TGetSmartInfoReq

NVMe.interface = mdb.register_interface('bmc.kepler.Systems.Storage.Drive.NVMe',
    {LifeUsedPercentage = {'y', nil, true, nil}}, {
        GetSmartInfo = {'a{ss}q', 'ay', TGetSmartInfoReq, TGetSmartInfoRsp},
        SendNvmeMICommand = {'a{ss}yuuay', 'yuay', TSendNvmeMICommandReq, TSendNvmeMICommandRsp},
        GetTelemetryData = {'a{ss}s', 'u', TGetTelemetryDataReq, TGetTelemetryDataRsp},
        GetIdentifyData = {'a{ss}y', 'ay', TGetIdentifyDataReq, TGetIdentifyDataRsp}
    }, {})

return NVMe
