-- 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 Properties = {}

---@class Properties.ObjectName
---@field ObjectName string
local TObjectName = {}
TObjectName.__index = TObjectName
TObjectName.group = {}

local function TObjectName_from_obj(obj)
    return setmetatable(obj, TObjectName)
end

function TObjectName.new(ObjectName)
    return TObjectName_from_obj({ObjectName = ObjectName})
end
---@param obj Properties.ObjectName
function TObjectName:init_from_obj(obj)
    self.ObjectName = obj.ObjectName
end

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

TObjectName.from_obj = TObjectName_from_obj

TObjectName.proto_property = {'ObjectName'}

TObjectName.default = {''}

TObjectName.struct = {{name = 'ObjectName', is_array = false, struct = nil}}

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

    validate.Optional(prefix .. 'ObjectName', self.ObjectName, 'string', true, errs, need_convert)

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

function TObjectName:unpack(_)
    return self.ObjectName
end

Properties.ObjectName = TObjectName

---@class Properties.ClassName
---@field ClassName string
local TClassName = {}
TClassName.__index = TClassName
TClassName.group = {}

local function TClassName_from_obj(obj)
    return setmetatable(obj, TClassName)
end

function TClassName.new(ClassName)
    return TClassName_from_obj({ClassName = ClassName})
end
---@param obj Properties.ClassName
function TClassName:init_from_obj(obj)
    self.ClassName = obj.ClassName
end

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

TClassName.from_obj = TClassName_from_obj

TClassName.proto_property = {'ClassName'}

TClassName.default = {''}

TClassName.struct = {{name = 'ClassName', is_array = false, struct = nil}}

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

    validate.Optional(prefix .. 'ClassName', self.ClassName, 'string', true, errs, need_convert)

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

function TClassName:unpack(_)
    return self.ClassName
end

Properties.ClassName = TClassName

---@class Properties.GetPropertiesByOptionsRsp
---@field Properties string[]
local TGetPropertiesByOptionsRsp = {}
TGetPropertiesByOptionsRsp.__index = TGetPropertiesByOptionsRsp
TGetPropertiesByOptionsRsp.group = {}

local function TGetPropertiesByOptionsRsp_from_obj(obj)
    return setmetatable(obj, TGetPropertiesByOptionsRsp)
end

function TGetPropertiesByOptionsRsp.new(Properties)
    return TGetPropertiesByOptionsRsp_from_obj({Properties = Properties})
end
---@param obj Properties.GetPropertiesByOptionsRsp
function TGetPropertiesByOptionsRsp:init_from_obj(obj)
    self.Properties = obj.Properties
end

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

TGetPropertiesByOptionsRsp.from_obj = TGetPropertiesByOptionsRsp_from_obj

TGetPropertiesByOptionsRsp.proto_property = {'Properties'}

TGetPropertiesByOptionsRsp.default = {{}}

TGetPropertiesByOptionsRsp.struct = {{name = 'Properties', is_array = true, struct = nil}}

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

    validate.OptionalArray(prefix .. 'Properties', self.Properties, 'string', false, errs, need_convert)

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

function TGetPropertiesByOptionsRsp:unpack(_)
    return self.Properties
end

Properties.GetPropertiesByOptionsRsp = TGetPropertiesByOptionsRsp

---@class Properties.GetOptionsReq
---@field Interface string
---@field Property string
local TGetOptionsReq = {}
TGetOptionsReq.__index = TGetOptionsReq
TGetOptionsReq.group = {}

local function TGetOptionsReq_from_obj(obj)
    return setmetatable(obj, TGetOptionsReq)
end

function TGetOptionsReq.new(Interface, Property)
    return TGetOptionsReq_from_obj({Interface = Interface, Property = Property})
end
---@param obj Properties.GetOptionsReq
function TGetOptionsReq:init_from_obj(obj)
    self.Interface = obj.Interface
    self.Property = obj.Property
end

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

TGetOptionsReq.from_obj = TGetOptionsReq_from_obj

TGetOptionsReq.proto_property = {'Interface', 'Property'}

TGetOptionsReq.default = {'', ''}

TGetOptionsReq.struct = {
    {name = 'Interface', is_array = false, struct = nil}, {name = 'Property', is_array = false, struct = nil}
}

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

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

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

function TGetOptionsReq:unpack(_)
    return self.Interface, self.Property
end

Properties.GetOptionsReq = TGetOptionsReq

---@class Properties.Options
---@field volatile boolean
---@field deprecated boolean
---@field explicit boolean
---@field emitsChangedSignal string
local TOptions = {}
TOptions.__index = TOptions
TOptions.group = {}

local function TOptions_from_obj(obj)
    return setmetatable(obj, TOptions)
end

function TOptions.new(volatile, deprecated, explicit, emitsChangedSignal)
    return TOptions_from_obj({
        volatile = volatile,
        deprecated = deprecated,
        explicit = explicit,
        emitsChangedSignal = emitsChangedSignal
    })
end
---@param obj Properties.Options
function TOptions:init_from_obj(obj)
    self.volatile = obj.volatile
    self.deprecated = obj.deprecated
    self.explicit = obj.explicit
    self.emitsChangedSignal = obj.emitsChangedSignal
end

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

TOptions.from_obj = TOptions_from_obj

TOptions.proto_property = {'volatile', 'deprecated', 'explicit', 'emitsChangedSignal'}

TOptions.default = {false, false, false, ''}

TOptions.struct = {
    {name = 'volatile', is_array = false, struct = nil}, {name = 'deprecated', is_array = false, struct = nil},
    {name = 'explicit', is_array = false, struct = nil}, {name = 'emitsChangedSignal', is_array = false, struct = nil}
}

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

    validate.Optional(prefix .. 'volatile', self.volatile, 'bool', false, errs, need_convert)
    validate.Optional(prefix .. 'deprecated', self.deprecated, 'bool', false, errs, need_convert)
    validate.Optional(prefix .. 'explicit', self.explicit, 'bool', false, errs, need_convert)
    validate.Optional(prefix .. 'emitsChangedSignal', self.emitsChangedSignal, 'string', false, errs, need_convert)

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

function TOptions:unpack(_)
    return self.volatile, self.deprecated, self.explicit, self.emitsChangedSignal
end

Properties.Options = TOptions

---@class Properties.GetPropertiesByOptionsReq
---@field Interface string
---@field Options Properties.Options
local TGetPropertiesByOptionsReq = {}
TGetPropertiesByOptionsReq.__index = TGetPropertiesByOptionsReq
TGetPropertiesByOptionsReq.group = {}

local function TGetPropertiesByOptionsReq_from_obj(obj)
    obj.Options = utils.from_obj(Properties.Options, obj.Options)
    return setmetatable(obj, TGetPropertiesByOptionsReq)
end

function TGetPropertiesByOptionsReq.new(Interface, Options)
    return TGetPropertiesByOptionsReq_from_obj({Interface = Interface, Options = Options})
end
---@param obj Properties.GetPropertiesByOptionsReq
function TGetPropertiesByOptionsReq:init_from_obj(obj)
    self.Interface = obj.Interface
    self.Options = obj.Options
end

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

TGetPropertiesByOptionsReq.from_obj = TGetPropertiesByOptionsReq_from_obj

TGetPropertiesByOptionsReq.proto_property = {'Interface', 'Options'}

TGetPropertiesByOptionsReq.default = {'', Properties.Options.default}

TGetPropertiesByOptionsReq.struct = {
    {name = 'Interface', is_array = false, struct = nil},
    {name = 'Options', is_array = false, struct = Properties.Options.struct}
}

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

    Properties.Options.new(self.Options.volatile, self.Options.deprecated, self.Options.explicit,
        self.Options.emitsChangedSignal):validate(prefix, errs, need_convert)

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

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

function TGetPropertiesByOptionsReq:unpack(raw)
    return self.Interface, utils.unpack(raw, self.Options)
end

Properties.GetPropertiesByOptionsReq = TGetPropertiesByOptionsReq

---@class Properties.GetOptionsRsp
---@field Options Properties.Options
local TGetOptionsRsp = {}
TGetOptionsRsp.__index = TGetOptionsRsp
TGetOptionsRsp.group = {}

local function TGetOptionsRsp_from_obj(obj)
    obj.Options = utils.from_obj(Properties.Options, obj.Options)
    return setmetatable(obj, TGetOptionsRsp)
end

function TGetOptionsRsp.new(Options)
    return TGetOptionsRsp_from_obj({Options = Options})
end
---@param obj Properties.GetOptionsRsp
function TGetOptionsRsp:init_from_obj(obj)
    self.Options = obj.Options
end

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

TGetOptionsRsp.from_obj = TGetOptionsRsp_from_obj

TGetOptionsRsp.proto_property = {'Options'}

TGetOptionsRsp.default = {Properties.Options.default}

TGetOptionsRsp.struct = {{name = 'Options', is_array = false, struct = Properties.Options.struct}}

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

    Properties.Options.new(self.Options.volatile, self.Options.deprecated, self.Options.explicit,
        self.Options.emitsChangedSignal):validate(prefix, errs, need_convert)

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

function TGetOptionsRsp:unpack(raw)
    return utils.unpack(raw, self.Options)
end

Properties.GetOptionsRsp = TGetOptionsRsp

---@class Properties.StructIdentifier
---@field SystemId integer
---@field ManagerId string
---@field ChassisId string
---@field Position string
local TStructIdentifier = {}
TStructIdentifier.__index = TStructIdentifier
TStructIdentifier.group = {}

local function TStructIdentifier_from_obj(obj)
    return setmetatable(obj, TStructIdentifier)
end

function TStructIdentifier.new(SystemId, ManagerId, ChassisId, Position)
    return TStructIdentifier_from_obj({
        SystemId = SystemId,
        ManagerId = ManagerId,
        ChassisId = ChassisId,
        Position = Position
    })
end
---@param obj Properties.StructIdentifier
function TStructIdentifier:init_from_obj(obj)
    self.SystemId = obj.SystemId
    self.ManagerId = obj.ManagerId
    self.ChassisId = obj.ChassisId
    self.Position = obj.Position
end

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

TStructIdentifier.from_obj = TStructIdentifier_from_obj

TStructIdentifier.proto_property = {'SystemId', 'ManagerId', 'ChassisId', 'Position'}

TStructIdentifier.default = {0, '', '', ''}

TStructIdentifier.struct = {
    {name = 'SystemId', is_array = false, struct = nil}, {name = 'ManagerId', is_array = false, struct = nil},
    {name = 'ChassisId', is_array = false, struct = nil}, {name = 'Position', is_array = false, struct = nil}
}

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

    validate.Optional(prefix .. 'SystemId', self.SystemId, 'uint8', true, errs, need_convert)
    validate.Optional(prefix .. 'ManagerId', self.ManagerId, 'string', true, errs, need_convert)
    validate.Optional(prefix .. 'ChassisId', self.ChassisId, 'string', true, errs, need_convert)
    validate.Optional(prefix .. 'Position', self.Position, 'string', true, errs, need_convert)

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

function TStructIdentifier:unpack(_)
    return self.SystemId, self.ManagerId, self.ChassisId, self.Position
end

Properties.StructIdentifier = TStructIdentifier

---@class Properties.ObjectIdentifier
---@field ObjectIdentifier Properties.StructIdentifier
local TObjectIdentifier = {}
TObjectIdentifier.__index = TObjectIdentifier
TObjectIdentifier.group = {}

local function TObjectIdentifier_from_obj(obj)
    obj.ObjectIdentifier = utils.from_obj(Properties.StructIdentifier, obj.ObjectIdentifier)
    return setmetatable(obj, TObjectIdentifier)
end

function TObjectIdentifier.new(ObjectIdentifier)
    return TObjectIdentifier_from_obj({ObjectIdentifier = ObjectIdentifier})
end
---@param obj Properties.ObjectIdentifier
function TObjectIdentifier:init_from_obj(obj)
    self.ObjectIdentifier = obj.ObjectIdentifier
end

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

TObjectIdentifier.from_obj = TObjectIdentifier_from_obj

TObjectIdentifier.proto_property = {'ObjectIdentifier'}

TObjectIdentifier.default = {Properties.StructIdentifier.default}

TObjectIdentifier.struct = {{name = 'ObjectIdentifier', is_array = false, struct = Properties.StructIdentifier.struct}}

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

    Properties.StructIdentifier.new(self.ObjectIdentifier.SystemId, self.ObjectIdentifier.ManagerId,
        self.ObjectIdentifier.ChassisId, self.ObjectIdentifier.Position):validate(prefix, errs, need_convert)

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

function TObjectIdentifier:unpack(raw)
    return utils.unpack(raw, self.ObjectIdentifier)
end

Properties.ObjectIdentifier = TObjectIdentifier

Properties.interface = mdb.register_interface('bmc.kepler.Object.Properties', {
    ClassName = {'s', nil, true, nil, false},
    ObjectName = {'s', nil, true, nil, false},
    ObjectIdentifier = {'(ysss)', nil, true, nil, false}
}, {
    GetOptions = {'a{ss}ss', '(bbbs)', TGetOptionsReq, TGetOptionsRsp},
    GetPropertiesByOptions = {'a{ss}s(bbbs)', 'as', TGetPropertiesByOptionsReq, TGetPropertiesByOptionsRsp}
}, {})

return Properties
