/*
 * 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"

// TwdmChannelManagedEntityClassID is the 16-bit ID for the OMCI
// Managed entity TWDM channel managed entity
const TwdmChannelManagedEntityClassID ClassID = ClassID(443)

var twdmchannelmanagedentityBME *ManagedEntityDefinition

// TwdmChannelManagedEntity (class ID #443)
//	This ME provides an anchor for the MEs involved in collection of PM statistics per TWDM channel,
//	as stipulated by clause 14 of [ITU-T-G.989.3]. Instances of this ME are instantiated
//	autonomously by the ONU.
//
//	Relationships
//		One or more instances of this ME are implicitly associated with the TWDM System profile ME. The
//		number of instances created is announced by the total TWDM channel number attribute of the TWDM
//		system profile ME.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. This 2-byte
//			number is represented as 0xSSBB, where SS indicates the ONU slot ID, and BB is the TWDM channel
//			ME number assigned by the ONU itself, starting from 0 in the ascending order. (R) (mandatory)
//			(2-bytes)
//
//		Active Channel Indication
//			Active channel indication: The default value is false. The ONU sets the attribute to true when
//			it receives the Channel_Profile PLOAM messages for that channel. The ONU clears the attribute
//			when it receives the Channel_Profile PLOAM message marked ``void'' for that channel. (R)
//			(mandatory) (1-byte)
//
//		Operational Channel Indication
//			Operational channel indication: A Boolean attribute that is set to true for an active TWDM
//			channel in which the ONT is currently operating. The operational statistic is accumulated in the
//			PM history data MEs associated with that TWDM channel. (R) (mandatory) (1-byte)
//
//		Downstream Wavelength Channel
//			Downstream wavelength channel: For an active TWDM channel, this attribute identifies the
//			downstream wavelength channel in reference to Table 11-2 of [ITU-T-G.989.2]. For an inactive
//			channel it has value 0xFF. (R) (mandatory) (1-byte)
//
//		Upstream Wavelength Channel
//			Upstream wavelength channel: For an active TWDM channel, this attribute identifies the upstream
//			wavelength channel in reference to Table VIII-5 of [ITU-T-G.989.2]. For an inactive channel its
//			value of 0xFF. (R) (mandatory) (1-byte)
//
type TwdmChannelManagedEntity struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	twdmchannelmanagedentityBME = &ManagedEntityDefinition{
		Name:    "TwdmChannelManagedEntity",
		ClassID: 443,
		MessageTypes: mapset.NewSetWith(
			Get,
		),
		AllowedAttributeMask: 0xf000,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read), false, false, false, 0),
			1: ByteField("ActiveChannelIndication", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
			2: ByteField("OperationalChannelIndication", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read), false, false, false, 2),
			3: ByteField("DownstreamWavelengthChannel", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read), false, false, false, 3),
			4: ByteField("UpstreamWavelengthChannel", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, false, false, 4),
		},
		Access:  CreatedByOnu,
		Support: UnknownSupport,
	}
}

// NewTwdmChannelManagedEntity (class ID 443) 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 NewTwdmChannelManagedEntity(params ...ParamData) (*ManagedEntity, OmciErrors) {
	return NewManagedEntity(*twdmchannelmanagedentityBME, params...)
}
