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

// VoipApplicationServiceProfileClassID is the 16-bit ID for the OMCI
// Managed entity VoIP application service profile
const VoipApplicationServiceProfileClassID ClassID = ClassID(146)

var voipapplicationserviceprofileBME *ManagedEntityDefinition

// VoipApplicationServiceProfile (class ID #146)
//	The VoIP application service profile defines attributes of calling features used in conjunction
//	with a VoIP line service. It is optional for ONUs that support VoIP services. If a non-OMCI
//	interface is used to manage SIP for VoIP, this ME is unnecessary.
//
//	An instance of this ME is created and deleted by the OLT. A VoIP application service profile
//	instance is needed for each unique set of profile attributes.
//
//	Relationships
//		An instance of this ME is associated with zero or more SIP user data MEs.
//
//	Attributes
//		Managed Entity Id
//			Managed entity ID: This attribute uniquely identifies each instance of this ME. (R, setbycreate)
//			(mandatory) (2-bytes)
//
//		Cid Features
//			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
//
//		Call Waiting Features
//			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
//
//		Call Progress Or Transfer Features
//			The recommended default value is 0x0000. (R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Call Presentation Features
//			The recommended default value is 0x0000. (R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Direct Connect Feature
//			The recommended default value is 0x00. (R,-W, setbycreate) (mandatory) (1-byte)
//
//		Direct Connect Uri Pointer
//			Direct connect URI pointer: This attribute points to a network address ME that specifies the URI
//			of the direct connect. If this attribute is set to a null pointer, no URI is defined. (R,-W,
//			setbycreate) (mandatory) (2-bytes)
//
//		Bridged Line Agent Uri Pointer
//			Bridged line agent URI pointer: This attribute points to a network address ME that specifies the
//			URI of the bridged line agent. If this attribute is set to a null pointer, no URI is defined.
//			(R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Conference Factory Uri Pointer
//			Conference factory URI pointer: This attribute points to a network address ME that specifies the
//			URI of the conference factory. If this attribute is set to a null pointer, no URI is defined.
//			(R,-W, setbycreate) (mandatory) (2-bytes)
//
//		Dial Tone Feature Delay_ W Armline Timer New
//			Dial tone feature delay/warmline timer (new): This attribute defines the warmline timer/dial
//			tone feature delay timer (seconds). The default value 0 specifies vendor-specific
//			implementation. (R,-W) (optional) (2-bytes)
//
type VoipApplicationServiceProfile struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	voipapplicationserviceprofileBME = &ManagedEntityDefinition{
		Name:    "VoipApplicationServiceProfile",
		ClassID: 146,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			Set,
		),
		AllowedAttributeMask: 0xff80,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1: ByteField("CidFeatures", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 1),
			2: ByteField("CallWaitingFeatures", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
			3: Uint16Field("CallProgressOrTransferFeatures", UnsignedIntegerAttributeType, 0x2000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 3),
			4: Uint16Field("CallPresentationFeatures", UnsignedIntegerAttributeType, 0x1000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 4),
			5: ByteField("DirectConnectFeature", UnsignedIntegerAttributeType, 0x0800, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 5),
			6: Uint16Field("DirectConnectUriPointer", UnsignedIntegerAttributeType, 0x0400, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 6),
			7: Uint16Field("BridgedLineAgentUriPointer", UnsignedIntegerAttributeType, 0x0200, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 7),
			8: Uint16Field("ConferenceFactoryUriPointer", UnsignedIntegerAttributeType, 0x0100, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 8),
			9: Uint16Field("DialToneFeatureDelayWArmlineTimerNew", UnsignedIntegerAttributeType, 0x0080, 0, mapset.NewSetWith(Read, Write), false, true, false, 9),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

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