-- 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 def_types = require 'class.types.types'

local MSerDes = {}

---@class MSerDes.ModeConfigs
---@field ModeConfigs def_types.SerdesModeConfig[]
local TModeConfigs = {}
TModeConfigs.__index = TModeConfigs
TModeConfigs.group = {}

local function TModeConfigs_from_obj(obj)
    obj.ModeConfigs = utils.from_obj(def_types.SerdesModeConfig, obj.ModeConfigs, true)
    return setmetatable(obj, TModeConfigs)
end

function TModeConfigs.new(ModeConfigs)
    return TModeConfigs_from_obj({ModeConfigs = ModeConfigs})
end
---@param obj MSerDes.ModeConfigs
function TModeConfigs:init_from_obj(obj)
    self.ModeConfigs = obj.ModeConfigs
end

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

TModeConfigs.from_obj = TModeConfigs_from_obj

TModeConfigs.proto_property = {'ModeConfigs'}

TModeConfigs.default = {{}}

TModeConfigs.struct = {{name = 'ModeConfigs', is_array = true, struct = def_types.SerdesModeConfig.struct}}

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

    for _, v in pairs(self.ModeConfigs) do
        def_types.SerdesModeConfig.new(v.Mode, v.Device, v.ControllerIndex):validate(prefix, errs, need_convert)
    end

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

function TModeConfigs:unpack(raw)
    return utils.unpack(raw, self.ModeConfigs, true)
end

MSerDes.ModeConfigs = TModeConfigs

---@class MSerDes.SASPorts
---@field SASPorts def_types.PortConfig
local TSASPorts = {}
TSASPorts.__index = TSASPorts
TSASPorts.group = {}

local function TSASPorts_from_obj(obj)
    obj.SASPorts = utils.from_obj(def_types.PortConfig, obj.SASPorts)
    return setmetatable(obj, TSASPorts)
end

function TSASPorts.new(SASPorts)
    return TSASPorts_from_obj({SASPorts = SASPorts})
end
---@param obj MSerDes.SASPorts
function TSASPorts:init_from_obj(obj)
    self.SASPorts = obj.SASPorts
end

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

TSASPorts.from_obj = TSASPorts_from_obj

TSASPorts.proto_property = {'SASPorts'}

TSASPorts.default = {def_types.PortConfig.default}

TSASPorts.struct = {{name = 'SASPorts', is_array = false, struct = def_types.PortConfig.struct}}

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

    def_types.PortConfig.new(self.SASPorts.ControllerIndex, self.SASPorts.PortList):validate(prefix, errs, need_convert)

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

function TSASPorts:unpack(raw)
    return utils.unpack(raw, self.SASPorts)
end

MSerDes.SASPorts = TSASPorts

---@class MSerDes.PCIePorts
---@field PCIePorts def_types.PortConfig
local TPCIePorts = {}
TPCIePorts.__index = TPCIePorts
TPCIePorts.group = {}

local function TPCIePorts_from_obj(obj)
    obj.PCIePorts = utils.from_obj(def_types.PortConfig, obj.PCIePorts)
    return setmetatable(obj, TPCIePorts)
end

function TPCIePorts.new(PCIePorts)
    return TPCIePorts_from_obj({PCIePorts = PCIePorts})
end
---@param obj MSerDes.PCIePorts
function TPCIePorts:init_from_obj(obj)
    self.PCIePorts = obj.PCIePorts
end

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

TPCIePorts.from_obj = TPCIePorts_from_obj

TPCIePorts.proto_property = {'PCIePorts'}

TPCIePorts.default = {def_types.PortConfig.default}

TPCIePorts.struct = {{name = 'PCIePorts', is_array = false, struct = def_types.PortConfig.struct}}

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

    def_types.PortConfig.new(self.PCIePorts.ControllerIndex, self.PCIePorts.PortList):validate(prefix, errs,
        need_convert)

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

function TPCIePorts:unpack(raw)
    return utils.unpack(raw, self.PCIePorts)
end

MSerDes.PCIePorts = TPCIePorts

---@class MSerDes.WorkMode
---@field WorkMode integer
local TWorkMode = {}
TWorkMode.__index = TWorkMode
TWorkMode.group = {}

local function TWorkMode_from_obj(obj)
    return setmetatable(obj, TWorkMode)
end

function TWorkMode.new(WorkMode)
    return TWorkMode_from_obj({WorkMode = WorkMode})
end
---@param obj MSerDes.WorkMode
function TWorkMode:init_from_obj(obj)
    self.WorkMode = obj.WorkMode
end

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

TWorkMode.from_obj = TWorkMode_from_obj

TWorkMode.proto_property = {'WorkMode'}

TWorkMode.default = {0}

TWorkMode.struct = {{name = 'WorkMode', is_array = false, struct = nil}}

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

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

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

function TWorkMode:unpack(_)
    return self.WorkMode
end

MSerDes.WorkMode = TWorkMode

---@class MSerDes.LinkWidth
---@field LinkWidth integer
local TLinkWidth = {}
TLinkWidth.__index = TLinkWidth
TLinkWidth.group = {}

local function TLinkWidth_from_obj(obj)
    return setmetatable(obj, TLinkWidth)
end

function TLinkWidth.new(LinkWidth)
    return TLinkWidth_from_obj({LinkWidth = LinkWidth})
end
---@param obj MSerDes.LinkWidth
function TLinkWidth:init_from_obj(obj)
    self.LinkWidth = obj.LinkWidth
end

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

TLinkWidth.from_obj = TLinkWidth_from_obj

TLinkWidth.proto_property = {'LinkWidth'}

TLinkWidth.default = {0}

TLinkWidth.struct = {{name = 'LinkWidth', is_array = false, struct = nil}}

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

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

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

function TLinkWidth:unpack(_)
    return self.LinkWidth
end

MSerDes.LinkWidth = TLinkWidth

---@class MSerDes.SocketID
---@field SocketID integer
local TSocketID = {}
TSocketID.__index = TSocketID
TSocketID.group = {}

local function TSocketID_from_obj(obj)
    return setmetatable(obj, TSocketID)
end

function TSocketID.new(SocketID)
    return TSocketID_from_obj({SocketID = SocketID})
end
---@param obj MSerDes.SocketID
function TSocketID:init_from_obj(obj)
    self.SocketID = obj.SocketID
end

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

TSocketID.from_obj = TSocketID_from_obj

TSocketID.proto_property = {'SocketID'}

TSocketID.default = {0}

TSocketID.struct = {{name = 'SocketID', is_array = false, struct = nil}}

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

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

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

function TSocketID:unpack(_)
    return self.SocketID
end

MSerDes.SocketID = TSocketID

---@class MSerDes.ID
---@field ID integer
local TID = {}
TID.__index = TID
TID.group = {}

local function TID_from_obj(obj)
    return setmetatable(obj, TID)
end

function TID.new(ID)
    return TID_from_obj({ID = ID})
end
---@param obj MSerDes.ID
function TID:init_from_obj(obj)
    self.ID = obj.ID
end

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

TID.from_obj = TID_from_obj

TID.proto_property = {'ID'}

TID.default = {0}

TID.struct = {{name = 'ID', is_array = false, struct = nil}}

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

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

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

function TID:unpack(_)
    return self.ID
end

MSerDes.ID = TID

---@class MSerDes.Name
---@field Name string
local TName = {}
TName.__index = TName
TName.group = {}

local function TName_from_obj(obj)
    return setmetatable(obj, TName)
end

function TName.new(Name)
    return TName_from_obj({Name = Name})
end
---@param obj MSerDes.Name
function TName:init_from_obj(obj)
    self.Name = obj.Name
end

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

TName.from_obj = TName_from_obj

TName.proto_property = {'Name'}

TName.default = {''}

TName.struct = {{name = 'Name', is_array = false, struct = nil}}

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

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

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

function TName:unpack(_)
    return self.Name
end

MSerDes.Name = TName

return MSerDes
