/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import "github.com/deckarep/golang-set"

// OnuGClassID is the 16-bit ID for the OMCI
// Managed entity ONU-G
const OnuGClassID ClassID = ClassID(256)

var onugBME *ManagedEntityDefinition

// OnuG (class ID #256)
//	This ME represents the ONU as equipment. The ONU automatically creates an instance of this ME.
//	It assigns values to read-only attributes according to data within the ONU itself.
//
//	This ME has evolved from the ONT-G of [ITUT G.984.4].
//
//	Relationships
//		In ITU-T GTC based PON applications, all other MEs in this Recommendation are related directly
//		or indirectly to the ONU-G entity.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. There is only
//			one instance, number 0. (R) (mandatory) (2-bytes)
//
//		Vendor Id
//			Vendor ID:	This attribute identifies the vendor of the ONU. It is the same as the four most
//			significant bytes of the ONU serial number as specified in the respective transmission
//			convergence (TC) layer specification. (R) (mandatory) (4-bytes)
//
//		Version
//			Version:	This attribute identifies the version of the ONU as defined by the vendor. The
//			character value 0 indicates that version information is not available or applicable. (R)
//			(mandatory) (14-bytes)
//
//		Serial Number
//			Serial number: The serial number is unique for each ONU. It is defined in the respective TC
//			layer specification and contains the vendor ID and version number. The first four bytes are an
//			ASCII-encoded four-letter vendor ID. The second four bytes are a binary encoded serial number,
//			under the control of the ONU vendor. (R) (mandatory) (8-bytes)
//
//		Traffic Management Option
//			Upon ME instantiation, the ONU sets this attribute to the value that describes its
//			implementation. The OLT must adapt its model to conform to the ONU's selection. (R) (mandatory)
//			(1-byte)
//
//		Deprecated
//			Deprecated:	This attribute is not used. If it is present, it should be set to 0. (R) (optional)
//			(1-byte)
//
//		Battery Backup
//			Battery backup: This Boolean attribute controls whether the ONU performs backup battery
//			monitoring (assuming it is capable of doing so). False disables battery alarm monitoring; true
//			enables battery alarm monitoring. (R,-W) (mandatory) (1-byte)
//
//		Administrative State
//			Administrative state: This attribute locks (1) and unlocks (0) the functions performed by the
//			ONU as an entirety. Administrative state is further described in clause A.1.6. (R,-W)
//			(mandatory) (1-byte)
//
//		Operational State
//			Operational state: This attribute reports whether the ME is currently capable of performing its
//			function. Valid values are enabled (0) and disabled (1). (R) (optional) (1-byte)
//
//		Onu Survival Time
//			ONU survival time: This attribute indicates the minimum guaranteed time in milliseconds between
//			the loss of external power and the silence of the ONU. This does not include survival time
//			attributable to a backup battery. The value zero implies that the actual time is not known. (R)
//			(optional) (1-byte)
//
//		Logical Onu Id
//			Logical ONU ID: This attribute provides a way for the ONU to identify itself. It is a text
//			string, null terminated if it is shorter than 24 bytes, with a null default value. The mechanism
//			for creation or modification of this information is beyond the scope of this Recommendation, but
//			might include, for example, a web page displayed to a user. (R) (optional) (24 bytes)
//
//		Logical Password
//			Logical password: This attribute provides a way for the ONU to submit authentication
//			credentials. It is a text string, null terminated if it is shorter than 12 bytes, with a null
//			default value. The mechanism for creation or modification of this information is beyond the
//			scope of this Recommendation. (R) (optional) (12-bytes)
//
//		Credentials Status
//			Other values are reserved.
//
//		Extended Tc_Layer Options
//			(R) (optional) (2-bytes)
//
type OnuG struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	onugBME = &ManagedEntityDefinition{
		Name:    "OnuG",
		ClassID: 256,
		MessageTypes: mapset.NewSetWith(
			Get,
			Reboot,
			Set,
			SynchronizeTime,
			Test,
		),
		AllowedAttributeMask: 0xfff8,
		AttributeDefinitions: AttributeDefinitionMap{
			0:  Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1:  MultiByteField("VendorId", StringAttributeType, 0x8000, 4, toOctets("ICAgIA=="), mapset.NewSetWith(Read), false, false, false, 1),
			2:  MultiByteField("Version", StringAttributeType, 0x4000, 14, toOctets("MAAAAAAAAAAAAAAAAAA="), mapset.NewSetWith(Read), false, false, false, 2),
			3:  MultiByteField("SerialNumber", OctetsAttributeType, 0x2000, 8, toOctets("AAAAAAAAAAA="), mapset.NewSetWith(Read), false, false, false, 3),
			4:  ByteField("TrafficManagementOption", EnumerationAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
			5:  ByteField("Deprecated", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, true, true, 5),
			6:  ByteField("BatteryBackup", EnumerationAttributeType, 0x0400, 0, mapset.NewSetWith(Read, Write), false, false, false, 6),
			7:  ByteField("AdministrativeState", EnumerationAttributeType, 0x0200, 0, mapset.NewSetWith(Read, Write), false, false, false, 7),
			8:  ByteField("OperationalState", EnumerationAttributeType, 0x0100, 0, mapset.NewSetWith(Read), false, true, false, 8),
			9:  ByteField("OnuSurvivalTime", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read), false, true, false, 9),
			10: MultiByteField("LogicalOnuId", OctetsAttributeType, 0x0040, 24, toOctets("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read), false, true, false, 10),
			11: MultiByteField("LogicalPassword", OctetsAttributeType, 0x0020, 12, toOctets("AAAAAAAAAAAAAAAA"), mapset.NewSetWith(Read), false, true, false, 11),
			12: ByteField("CredentialsStatus", EnumerationAttributeType, 0x0010, 0, mapset.NewSetWith(Read, Write), false, true, false, 12),
			13: Uint16Field("ExtendedTcLayerOptions", BitFieldAttributeType, 0x0008, 0, mapset.NewSetWith(Read), false, true, false, 13),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
	}
}

// NewOnuG (class ID 256) creates the basic
// Managed Entity definition that is used to validate an ME of this type that
// is received from or transmitted to the OMCC.
func NewOnuG(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*onugBME, params...)
}
