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

// VoipVoiceCtpClassID is the 16-bit ID for the OMCI
// Managed entity VoIP voice CTP
const VoipVoiceCtpClassID = ClassID(139) // 0x008b

var voipvoicectpBME *ManagedEntityDefinition

// VoipVoiceCtp (Class ID: #139 / 0x008b)
//	The VoIP voice CTP defines the attributes necessary to associate a specified VoIP service (SIP,
//	ITUT-H.248) with a POTS UNI. This entity is conditionally required for ONUs that offer VoIP
//	services. If a non-OMCI interface is used to manage VoIP signalling, this ME is unnecessary.
//
//	An instance of this ME is created and deleted by the OLT. A VoIP voice CTP ME is needed for each
//	PPTP POTS UNI served by VoIP.
//
//	Relationships
//		An instance of this ME links a PPTP POTS UNI ME with a VoIP media profile and a SIP user data or
//		media gateway controller (MGC) config data ME.
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. (R, setbycreate) (mandatory)
//			(2-bytes)
//
//		User Protocol Pointer
//			This attribute points to signalling protocol data. If the signalling protocol used attribute of
//			the VoIP config data ME specifies that the ONU's signalling protocol is SIP, this attribute
//			points to a SIP user data ME, which in turn points to a SIP agent config data ME. If the
//			signalling protocol is ITU-T-H.248, this attribute points directly to an MGC config data ME.
//			(R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Pptp Pointer
//			This attribute points to the PPTP POTS UNI ME that serves the analogue telephone port. (R,-W,
//			setbycreate) (mandatory) (2-bytes)
//
//		V O Ip Media Profile Pointer
//			VoIP media profile pointer: This attribute points to an associated VoIP media profile. (R,-W,
//			setbycreate) (mandatory) (2-bytes)
//
//		Signalling Code
//			3	Loop reverse battery
//
//			4	Coin first
//
//			5	Dial tone first
//
//			6	Multi-party
//
//			(R,-W, setbycreate) (mandatory) (1-byte)
//
//			This attribute specifies the POTS-side signalling as follows.
//
//			1	Loop start
//
//			2	Ground start
//
type VoipVoiceCtp struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

// Attribute name constants

const VoipVoiceCtp_UserProtocolPointer = "UserProtocolPointer"
const VoipVoiceCtp_PptpPointer = "PptpPointer"
const VoipVoiceCtp_VOIpMediaProfilePointer = "VOIpMediaProfilePointer"
const VoipVoiceCtp_SignallingCode = "SignallingCode"

func init() {
	voipvoicectpBME = &ManagedEntityDefinition{
		Name:    "VoipVoiceCtp",
		ClassID: VoipVoiceCtpClassID,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			Set,
		),
		AllowedAttributeMask: 0xf000,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field(ManagedEntityID, PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1: Uint16Field(VoipVoiceCtp_UserProtocolPointer, UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
			2: Uint16Field(VoipVoiceCtp_PptpPointer, UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
			3: Uint16Field(VoipVoiceCtp_VOIpMediaProfilePointer, UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
			4: ByteField(VoipVoiceCtp_SignallingCode, UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

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