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

// FastXtuCPerformanceMonitoringHistoryDataClassID is the 16-bit ID for the OMCI
// Managed entity FAST xTU-C performance monitoring history data
const FastXtuCPerformanceMonitoringHistoryDataClassID = ClassID(437) // 0x01b5

var fastxtucperformancemonitoringhistorydataBME *ManagedEntityDefinition

// FastXtuCPerformanceMonitoringHistoryData (Class ID: #437 / 0x01b5)
//	This ME collects PM data on the xTU C to xTU R path as seen from the xTU-C. Instances of this ME
//	are created and deleted by the OLT.
//
//	Relationships
//		An instance of this ME is associated with an xDSL UNI.
//
//	Attributes
//		Managed Entity Id
//			This attribute uniquely identifies each instance of this ME. Through an identical ID, this ME is
//			implicitly linked to an instance of the PPTP xDSL UNI part 1. (R, set-by-create) (mandatory) (2
//			bytes)
//
//		Interval End Time
//			This attribute identifies the most recently finished 15-min interval. (R) (mandatory) (1 byte)
//
//		Threshold Data 1_2 Id
//			Threshold data 1/2 ID: This attribute points to an instance of the threshold data 1 and 2 MEs
//			that contain PM threshold values. (R, W, set-by-create) (mandatory) (2 bytes)
//
//		Successful Fra Counter
//			This attribute counts the successful FRA primitives (success_FRA). The successful FRA primitive
//			(success_FRA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.22 of [ITU-T
//			G.997.2]. (R) (mandatory) (4-bytes)
//
//		Successful Rpa Counter
//			This attribute counts the successful RPA primitives (success_RPA). The successful RPA primitive
//			(success_RPA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. See clause 7.7.23 of [ITU-T
//			G.997.2] (R) (optional) (4 bytes)
//
//		Successful Tiga Counter
//			This attribute counts the successful TIGA primitives (success_TIGA). The successful TIGA
//			primitive (success_TIGA) is defined in clause 11.3.1.6 of [ITU-T G.9701]. Reported only with the
//			near-end measured time, invalid data flag and timestamp. See clause 7.7.24 of [ITUT-G.997.2] (R)
//			(optional) (4 bytes)
//
type FastXtuCPerformanceMonitoringHistoryData struct {
	ManagedEntityDefinition
	Attributes AttributeValueMap
}

func init() {
	fastxtucperformancemonitoringhistorydataBME = &ManagedEntityDefinition{
		Name:    "FastXtuCPerformanceMonitoringHistoryData",
		ClassID: 437,
		MessageTypes: mapset.NewSetWith(
			Create,
			Delete,
			Get,
			Set,
		),
		AllowedAttributeMask: 0xf800,
		AttributeDefinitions: AttributeDefinitionMap{
			0: Uint16Field("ManagedEntityId", PointerAttributeType, 0x0000, 0, mapset.NewSetWith(Read, SetByCreate), false, false, false, 0),
			1: ByteField("IntervalEndTime", UnsignedIntegerAttributeType, 0x8000, 0, mapset.NewSetWith(Read), false, false, false, 1),
			2: Uint16Field("ThresholdData12Id", UnsignedIntegerAttributeType, 0x4000, 0, mapset.NewSetWith(Read, SetByCreate, Write), false, false, false, 2),
			3: Uint32Field("SuccessfulFraCounter", CounterAttributeType, 0x2000, 0, mapset.NewSetWith(Read), false, false, false, 3),
			4: Uint32Field("SuccessfulRpaCounter", CounterAttributeType, 0x1000, 0, mapset.NewSetWith(Read), false, true, false, 4),
			5: Uint32Field("SuccessfulTigaCounter", CounterAttributeType, 0x0800, 0, mapset.NewSetWith(Read), false, true, false, 5),
		},
		Access:  CreatedByOlt,
		Support: UnknownSupport,
	}
}

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