/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 *
 * 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/opencord/omci-lib-go/OMCI-parser/README.md
 */

package omci

import (
	"errors"
	"fmt"
	"github.com/deckarep/golang-set"
	"github.com/google/gopacket"
	me "github.com/opencord/omci-lib-go/generated"
	"time"
)

var encoderMap map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error)

func init() {
	encoderMap = make(map[MessageType]func(*me.ManagedEntity, options) (gopacket.SerializableLayer, error))

	encoderMap[CreateRequestType] = CreateRequestFrame
	encoderMap[DeleteRequestType] = DeleteRequestFrame
	encoderMap[SetRequestType] = SetRequestFrame
	encoderMap[GetRequestType] = GetRequestFrame
	encoderMap[GetAllAlarmsRequestType] = GetAllAlarmsRequestFrame
	encoderMap[GetAllAlarmsNextRequestType] = GetAllAlarmsNextRequestFrame
	encoderMap[MibUploadRequestType] = MibUploadRequestFrame
	encoderMap[MibUploadNextRequestType] = MibUploadNextRequestFrame
	encoderMap[MibResetRequestType] = MibResetRequestFrame
	//encoderMap[TestRequestType] = TestRequestFrame
	encoderMap[StartSoftwareDownloadRequestType] = StartSoftwareDownloadRequestFrame
	encoderMap[DownloadSectionRequestType] = DownloadSectionRequestFrame
	encoderMap[EndSoftwareDownloadRequestType] = EndSoftwareDownloadRequestFrame
	encoderMap[ActivateSoftwareRequestType] = ActivateSoftwareRequestFrame
	encoderMap[CommitSoftwareRequestType] = CommitSoftwareRequestFrame
	encoderMap[SynchronizeTimeRequestType] = SynchronizeTimeRequestFrame
	encoderMap[RebootRequestType] = RebootRequestFrame
	encoderMap[GetNextRequestType] = GetNextRequestFrame
	encoderMap[GetCurrentDataRequestType] = GetCurrentDataRequestFrame
	encoderMap[SetTableRequestType] = SetTableRequestFrame
	encoderMap[CreateResponseType] = CreateResponseFrame
	encoderMap[DeleteResponseType] = DeleteResponseFrame
	encoderMap[SetResponseType] = SetResponseFrame
	encoderMap[GetResponseType] = GetResponseFrame
	encoderMap[GetAllAlarmsResponseType] = GetAllAlarmsResponseFrame
	encoderMap[GetAllAlarmsNextResponseType] = GetAllAlarmsNextResponseFrame
	encoderMap[MibUploadResponseType] = MibUploadResponseFrame
	encoderMap[MibUploadNextResponseType] = MibUploadNextResponseFrame
	encoderMap[MibResetResponseType] = MibResetResponseFrame
	//encoderMap[TestResponseType] = TestResponseFrame
	encoderMap[StartSoftwareDownloadResponseType] = StartSoftwareDownloadResponseFrame
	encoderMap[DownloadSectionResponseType] = DownloadSectionResponseFrame
	encoderMap[EndSoftwareDownloadResponseType] = EndSoftwareDownloadResponseFrame
	encoderMap[ActivateSoftwareResponseType] = ActivateSoftwareResponseFrame
	encoderMap[CommitSoftwareResponseType] = CommitSoftwareResponseFrame
	encoderMap[SynchronizeTimeResponseType] = SynchronizeTimeResponseFrame
	encoderMap[RebootResponseType] = RebootResponseFrame
	encoderMap[GetNextResponseType] = GetNextResponseFrame
	encoderMap[GetCurrentDataResponseType] = GetCurrentDataResponseFrame
	encoderMap[SetTableResponseType] = SetTableResponseFrame
	encoderMap[AlarmNotificationType] = AlarmNotificationFrame
	encoderMap[AttributeValueChangeType] = AttributeValueChangeFrame
	//encoderMap[TestResultType] = TestResultFrame
}

type options struct {
	frameFormat               DeviceIdent
	failIfTruncated           bool
	attributeMask             uint16
	result                    me.Results      // Common for many responses
	attrExecutionMask         uint16          // Create Response Only if results == 3 or Set Response only if results == 0
	unsupportedMask           uint16          // Set Response only if results == 9
	sequenceNumberCountOrSize uint16          // For get-next request frames and for frames that return number of commands or length
	transactionID             uint16          // OMCI TID
	mode                      uint8           // Get All Alarms retrieval mode
	alarm                     AlarmOptions    // Alarm related frames
	software                  SoftwareOptions // Software image related frames
	payload                   interface{}     // ME or list of MEs, alarm bitmap, timestamp, ...
	addDefaults               bool            // Add missing SetByCreate attributes for Create Requests
}

var defaultFrameOptions = options{
	frameFormat:               BaselineIdent,
	failIfTruncated:           false,
	attributeMask:             0xFFFF,
	result:                    me.Success,
	attrExecutionMask:         0,
	unsupportedMask:           0,
	sequenceNumberCountOrSize: 0,
	transactionID:             0,
	mode:                      0,
	software:                  defaultSoftwareOptions,
	alarm:                     defaultAlarmOptions,
	payload:                   nil,
	addDefaults:               false,
}

// FrameOption sets options such as frame format, etc.
type FrameOption func(*options)

// FrameFormat determines determines the OMCI message format used on the fiber.
// The default value is BaselineIdent
func FrameFormat(ff DeviceIdent) FrameOption {
	return func(o *options) {
		o.frameFormat = ff
	}
}

// FailIfTruncated determines whether a request to encode a frame that does
// not have enough room for all requested options should fail and return an
// error.
//
// If set to 'false', the behaviour depends on the message type/operation
// requested. The table below provides more information:
//
//   Request Type	Behavour
//	 ------------------------------------------------------------------------
//	 CreateRequest  A single CreateRequest struct is always returned as the
//                  CreateRequest message does not have an attributes Mask
//                  field and a Baseline OMCI message is large enough to
//                  support all Set-By-Create attributes.
//
//   GetResponse	If multiple OMCI response frames are needed to return
//					all requested attributes, only the attributes that can
//					fit will be returned and the FailedAttributeMask field
//					set to the attributes that could not be returned
//
//					If this is an ME with an attribute that is a table, the
//					first GetResponse struct will return the size of the
//					attribute and the following GetNextResponse structs will
//					contain the attribute data. The ONU application is
//					responsible for stashing these extra struct(s) away in
//					anticipation of possible GetNext Requests occurring for
//					the attribute.  See the discussion on Table attributes
//					in the GetResponse section of ITU G.988 for more
//					information.
//
// If set to 'true', no struct(s) are returned and an error is provided.
//
// The default value is 'false'
func FailIfTruncated(f bool) FrameOption {
	return func(o *options) {
		o.failIfTruncated = f
	}
}

// attributeMask determines the attributes to encode into the frame.
// The default value is 0xFFFF which specifies all available attributes
// in the frame
func AttributeMask(m uint16) FrameOption {
	return func(o *options) {
		o.attributeMask = m
	}
}

// AttributeExecutionMask is used by the Create and Set Response frames to indicate
// attributes that failed to be created/set.
func AttributeExecutionMask(m uint16) FrameOption {
	return func(o *options) {
		o.attrExecutionMask = m
	}
}

// UnsupportedAttributeMask is used by the Set Response frames to indicate
// attributes are not supported on this ONU
func UnsupportedAttributeMask(m uint16) FrameOption {
	return func(o *options) {
		o.unsupportedMask = m
	}
}

// Result is used to set returned results in responses
// that have that field
func Result(r me.Results) FrameOption {
	return func(o *options) {
		o.result = r
	}
}

// SequenceNumberCountOrSize is used by the GetNext and MibUploadGetNext request frames and for
// frames that return number of commands or length such as Get (table attribute) or
// MibUpload/GetAllAlarms/...
func SequenceNumberCountOrSize(m uint16) FrameOption {
	return func(o *options) {
		o.sequenceNumberCountOrSize = m
	}
}

// TransactionID is to specify the TID in the OMCI header. The default is
// zero which requires the caller to set it to the appropriate value if this
// is not an autonomous ONU notification frame
func TransactionID(tid uint16) FrameOption {
	return func(o *options) {
		o.transactionID = tid
	}
}

// RetrievalMode is to specify the the Alarm Retrieval Mode in a GetAllAlarms Request
func RetrievalMode(m uint8) FrameOption {
	return func(o *options) {
		o.mode = m
	}
}

// SuccessResult is to specify the the SuccessResult for a SynchronizeTime Response
func SuccessResult(m uint8) FrameOption {
	return func(o *options) {
		o.mode = m
	}
}

// RebootCondition is to specify the the Reboot Condition for a ONU Reboot request
func RebootCondition(m uint8) FrameOption {
	return func(o *options) {
		o.mode = m
	}
}

// Alarm is used to specify a collection of options related to Alarm notifications
func Alarm(ao AlarmOptions) FrameOption {
	return func(o *options) {
		o.alarm = ao
	}
}

// Software is used to specify a collection of options related to Software image
// manipulation
func Software(so SoftwareOptions) FrameOption {
	return func(o *options) {
		o.software = so
	}
}

// Payload is used to specify ME payload options that are not simple types. This
// include the ME (list of MEs) to encode into a GetNextMibUpload response, the
// alarm bitmap for alarm relates responses/notifications, alarm bitmaps, and
// for specifying the download section data when performing Software Download.
func Payload(p interface{}) FrameOption {
	return func(o *options) {
		o.payload = p
	}
}

// AddDefaults is used to specify that if a SetByCreate attribute is not
// specified in the list of attributes for a Create Request, use the attribute
// defined default
func AddDefaults(add bool) FrameOption {
	return func(o *options) {
		o.addDefaults = add
	}
}

// Alarm related frames have a wide variety of settable values. Placing them
// in a separate struct is mainly to keep the base options simple
type AlarmOptions struct {
	AlarmClassID  me.ClassID
	AlarmInstance uint16
	AlarmBitmap   []byte // Should be up to 58 octets
}

var defaultAlarmOptions = AlarmOptions{
	AlarmClassID:  0,
	AlarmInstance: 0,
	AlarmBitmap:   nil,
}

// Software related frames have a wide variety of settable values. Placing them
// in a separate struct is mainly to keep the base options simple
type SoftwareOptions struct {
	WindowSize    uint8 // Window size - 1
	SectionNumber uint8 // [0..Window size - 1]
	ImageSize     uint32
	CircuitPacks  []uint16 // slot (upper 8 bits) and instance (lower 8 bits)
	Results       []DownloadResults
	Data          []byte
}

var defaultSoftwareOptions = SoftwareOptions{
	WindowSize:    0,
	SectionNumber: 0,
	ImageSize:     0,
	CircuitPacks:  nil,
	Results:       nil,
	Data:          nil,
}

// EncodeFrame will encode the Managed Entity specific protocol struct and an
// OMCILayer struct. This struct can be provided to the gopacket.SerializeLayers()
// function to be serialized into a buffer for transmission.
func EncodeFrame(m *me.ManagedEntity, messageType MessageType, opt ...FrameOption) (*OMCI, gopacket.SerializableLayer, error) {
	// Check for message type support
	msgType := me.MsgType(messageType & me.MsgTypeMask)
	meDefinition := m.GetManagedEntityDefinition()

	if !me.SupportsMsgType(meDefinition, msgType) {
		msg := fmt.Sprintf("managed entity %v does not support %v Message-Type",
			meDefinition.GetName(), msgType)
		return nil, nil, errors.New(msg)
	}
	// Decode options
	opts := defaultFrameOptions
	for _, o := range opt {
		o(&opts)
	}
	// TODO: If AttributesMask option passed in, check for deprecated options. Allow encoding option
	//       that will ignore deprecated option.   Add additional in the get and set meframe_test,go
	//       test functions to test this. Also have it test attribute name(s) to see if the attribute
	//       is deprecated.  The OMCI-Parser now supports detection of deprecated attributes and
	//       provides that to the code-generator (and currently available in generated golang code).
	// Note: Transaction ID should be set before frame serialization
	omci := &OMCI{
		TransactionID:    opts.transactionID,
		MessageType:      messageType,
		DeviceIdentifier: opts.frameFormat,
	}
	var meInfo gopacket.SerializableLayer
	var err error

	if encoder, ok := encoderMap[messageType]; ok {
		meInfo, err = encoder(m, opts)
	} else {
		err = fmt.Errorf("message-type: %v/%#x is not supported", messageType, messageType)
	}
	if err != nil {
		return nil, nil, err
	}
	return omci, meInfo, err
}

// For most all create methods below, error checking for valid masks, attribute
// values, and other fields is left to when the frame is actually serialized.

func checkAttributeMask(m *me.ManagedEntity, mask uint16) (uint16, error) {
	if mask == defaultFrameOptions.attributeMask {
		// Scale back to just what is allowed
		return m.GetAllowedAttributeMask(), nil
	}
	if mask&m.GetManagedEntityDefinition().GetAllowedAttributeMask() != mask {
		return 0, errors.New("invalid attribute mask")
	}
	return mask & m.GetManagedEntityDefinition().GetAllowedAttributeMask(), nil
}

// return the maximum space that can be used by attributes
func maxPacketAvailable(m *me.ManagedEntity, opt options) uint {
	if opt.frameFormat == BaselineIdent {
		// OMCI Header          - 4 octets
		// Class ID/Instance ID - 4 octets
		// Length field			- 4 octets
		// MIC                  - 4 octets
		return MaxBaselineLength - 16
	}
	// OMCI Header          - 4 octets
	// Class ID/Instance ID - 4 octets
	// Length field			- 2 octets
	// MIC                  - 4 octets
	return MaxExtendedLength - 14
}

func calculateAttributeMask(m *me.ManagedEntity, requestedMask uint16) (uint16, error) {
	attrDefs := m.GetAttributeDefinitions()
	var entityIDName string
	if entry, ok := attrDefs[0]; ok {
		entityIDName = entry.GetName()
	} else {
		panic("unexpected error") // All attribute definition maps have an entity ID
	}
	attributeNames := make([]interface{}, 0)
	for attrName := range m.GetAttributeValueMap() {
		if attrName == entityIDName {
			continue // No mask for EntityID
		}
		attributeNames = append(attributeNames, attrName)
	}
	calculatedMask, err := me.GetAttributesBitmap(attrDefs, mapset.NewSetWith(attributeNames...))

	if err != nil {
		return 0, err
	}
	return calculatedMask & requestedMask, nil
}

// GenFrame is a helper function to make tests a little easier to read.
// For a real application, use the .../omci/generated/class.go 'New'
// functions to create your Managed Entity and then use it to call the
// EncodeFrame method.
func GenFrame(meInstance *me.ManagedEntity, messageType MessageType, options ...FrameOption) ([]byte, error) {
	omciLayer, msgLayer, err := EncodeFrame(meInstance, messageType, options...)
	if err != nil {
		return nil, err
	}
	// Serialize the frame and send it
	var serializeOptions gopacket.SerializeOptions
	serializeOptions.FixLengths = true

	buffer := gopacket.NewSerializeBuffer()
	err = gopacket.SerializeLayers(buffer, serializeOptions, omciLayer, msgLayer)
	if err != nil {
		return nil, err
	}
	return buffer.Bytes(), nil
}

func CreateRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// NOTE: The OMCI parser does not extract the default values of set-by-create attributes
	//       and are the zero 'default' (or nil) at this time.  For this reason, make sure
	//       you specify all non-zero default values and pass them in appropriate
	meLayer := &CreateRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Attributes: m.GetAttributeValueMap(),
	}
	// Add any missing SetByCreate options if requested
	if opt.addDefaults {
		if attrDefs, err := me.GetAttributesDefinitions(m.GetClassID()); err.StatusCode() == me.Success {
			for index, attr := range attrDefs {
				if me.SupportsAttributeAccess(attr, me.SetByCreate) {
					if index == 0 {
						continue // Skip Entity ID, if it is SetByCreate, they should always specify it
					}
					if _, found := meLayer.Attributes[attr.GetName()]; !found {
						meLayer.Attributes[attr.GetName()] = attr.DefValue
					}
				}
			}
		}
	}
	return meLayer, nil
}

func CreateResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	meLayer := &CreateResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result: opt.result,
	}
	if meLayer.Result == me.ParameterError {
		meLayer.AttributeExecutionMask = opt.attrExecutionMask
	}
	return meLayer, nil
}

func DeleteRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	meLayer := &DeleteRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	return meLayer, nil
}

func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	meLayer := &DeleteResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result: opt.result,
	}
	return meLayer, nil
}

func SetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	mask, err = calculateAttributeMask(m, mask)
	if err != nil {
		return nil, err
	}
	meDefinition := m.GetManagedEntityDefinition()
	attrDefs := meDefinition.GetAttributeDefinitions()
	attrMap := m.GetAttributeValueMap()

	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)
	payloadAvailable := int(maxPayload) - 2 // Less attribute mask
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
		// payloadAvailable -= 2				// Less length
	}
	meLayer := &SetRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AttributeMask: 0,
		Attributes:    make(me.AttributeValueMap),
	}
	for mask != 0 {
		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
		var attrIndex uint
		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
			// Is this attribute requested
			if mask&(1<<(16-attrIndex)) != 0 {
				// Get definitions since we need the name
				attrDef, ok := attrDefs[attrIndex]
				if !ok {
					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
						attrIndex, meDefinition.GetName())
					return nil, errors.New(msg)
				}
				var attrValue interface{}
				attrValue, ok = attrMap[attrDef.Name]
				if !ok {
					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
						attrDef.GetName(), meDefinition.GetName(), m)
					return nil, errors.New(msg)
				}
				// Is space available?
				if attrDef.Size <= payloadAvailable {
					// Mark bit handled
					mask &= ^attrDef.Mask
					meLayer.AttributeMask |= attrDef.Mask
					meLayer.Attributes[attrDef.Name] = attrValue
					payloadAvailable -= attrDef.Size
				} else {
					// TODO: Should we set truncate?
					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into SetRequest message",
						attrDef.GetName())
					return nil, me.NewMessageTruncatedError(msg)
				}
			}
		}
	}
	if err == nil && meLayer.AttributeMask == 0 {
		// TODO: Is a set request with no attributes valid?
		return nil, errors.New("no attributes encoded for SetRequest")
	}
	return meLayer, nil
}

func SetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	meLayer := &SetResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result: opt.result,
	}
	if meLayer.Result == me.AttributeFailure {
		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
		meLayer.FailedAttributeMask = opt.attrExecutionMask
	}
	return meLayer, nil
}

func GetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Given mask sent in (could be default of 0xFFFF) get what is allowable.
	// This will be all allowed if 0xFFFF is passed in, or a subset if a fixed
	// number of items.
	maxMask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Now scan attributes and reduce mask to only those requested
	var mask uint16
	mask, err = calculateAttributeMask(m, maxMask)
	if err != nil {
		return nil, err
	}
	if mask == 0 {
		// TODO: Is a Get request with no attributes valid?
		return nil, errors.New("no attributes requested for GetRequest")
	}
	meLayer := &GetRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AttributeMask: mask,
	}
	return meLayer, nil
}

func GetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	mask, err = calculateAttributeMask(m, mask)
	if err != nil {
		return nil, err
	}
	meLayer := &GetResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result:        opt.result,
		AttributeMask: 0,
		Attributes:    make(me.AttributeValueMap),
	}
	if meLayer.Result == me.AttributeFailure {
		meLayer.UnsupportedAttributeMask = opt.unsupportedMask
		meLayer.FailedAttributeMask = opt.attrExecutionMask
	}
	// Encode whatever we can
	if meLayer.Result == me.Success || meLayer.Result == me.AttributeFailure {
		// Encode results
		// Get payload space available
		maxPayload := maxPacketAvailable(m, opt)
		payloadAvailable := int(maxPayload) - 2 - 4 // Less attribute mask and attribute error encoding
		meDefinition := m.GetManagedEntityDefinition()
		attrDefs := meDefinition.GetAttributeDefinitions()
		attrMap := m.GetAttributeValueMap()

		if mask != 0 {
			// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
			var attrIndex uint
			for attrIndex = 1; attrIndex <= 16; attrIndex++ {
				// Is this attribute requested
				if mask&(1<<(16-attrIndex)) != 0 {
					// Get definitions since we need the name
					attrDef, ok := attrDefs[attrIndex]
					if !ok {
						msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
							attrIndex, meDefinition.GetName())
						return nil, errors.New(msg)
					}
					var attrValue interface{}
					attrValue, ok = attrMap[attrDef.Name]
					if !ok {
						msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
							attrDef.GetName(), meDefinition.GetName(), m)
						return nil, errors.New(msg)
					}
					// Is space available?
					if attrDef.Size <= payloadAvailable {
						// Mark bit handled
						mask &= ^attrDef.Mask
						meLayer.AttributeMask |= attrDef.Mask
						meLayer.Attributes[attrDef.Name] = attrValue
						payloadAvailable -= attrDef.Size

					} else if opt.failIfTruncated {
						// TODO: Should we set truncate?
						msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetResponse message",
							attrDef.GetName())
						return nil, me.NewMessageTruncatedError(msg)
					} else {
						// Add to existing 'failed' mask and update result
						meLayer.FailedAttributeMask |= attrDef.Mask
						meLayer.Result = me.AttributeFailure
					}
				}
			}
		}
	}
	return meLayer, nil
}

func GetAllAlarmsRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &GetAllAlarmsRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AlarmRetrievalMode: opt.mode,
	}
	return meLayer, nil
}

func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &GetAllAlarmsResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		NumberOfCommands: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &GetAllAlarmsNextRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &GetAllAlarmsNextResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AlarmEntityClass:    opt.alarm.AlarmClassID,
		AlarmEntityInstance: opt.alarm.AlarmInstance,
	}
	if len(opt.alarm.AlarmBitmap) > 28 {
		return nil, errors.New("invalid Alarm Bitmap Size. Must be [0..27]")
	}
	for octet := 0; octet < len(opt.alarm.AlarmBitmap); octet++ {
		meLayer.AlarmBitMap[octet] = opt.alarm.AlarmBitmap[octet]
	}
	for octet := len(opt.alarm.AlarmBitmap); octet < 28; octet++ {
		meLayer.AlarmBitMap[octet] = 0
	}
	return meLayer, nil
}

func MibUploadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibUploadRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	return meLayer, nil
}

func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibUploadResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		NumberOfCommands: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibUploadNextRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibUploadNextResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	if opt.payload == nil {
		// Shortcut used to specify the request sequence number is out of range, encode
		// a ME instance with class ID of zero to specify this per ITU G.988
		meDef := me.ManagedEntityDefinition{
			Name:                 "InvalidSequenceNumberManagedEntity",
			ClassID:              me.ClassID(0),
			MessageTypes:         nil,
			AttributeDefinitions: make(me.AttributeDefinitionMap),
		}
		opt.payload, _ = me.NewManagedEntity(meDef)
	}
	if _, ok := opt.payload.(*[]me.ManagedEntity); ok {
		if opt.frameFormat == BaselineIdent {
			return nil, errors.New("invalid payload for Baseline message")
		}
		// TODO: List of MEs. valid for extended messages only
	} else if managedEntity, ok := opt.payload.(*me.ManagedEntity); ok {
		// Single ME
		meLayer.ReportedME = *managedEntity
	} else {
		return nil, errors.New("invalid payload for MibUploadNextResponse frame")
	}
	return meLayer, nil
}

func MibResetRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibResetRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	return meLayer, nil
}

func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &MibResetResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result: opt.result,
	}
	return meLayer, nil
}

func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &AlarmNotificationMsg{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)
	payloadAvailable := int(maxPayload) - 1 // Less alarm sequence number

	// TODO: Lots of work to do
	fmt.Println(mask, maxPayload, payloadAvailable)

	return meLayer, errors.New("todo: Not implemented")
}

func AttributeValueChangeFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &AttributeValueChangeMsg{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AttributeMask: 0,
		Attributes:    make(me.AttributeValueMap),
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)
	payloadAvailable := int(maxPayload) - 2 // Less attribute mask

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload, payloadAvailable)
	return meLayer, errors.New("todo: Not implemented")
}

//func TestRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
//	if opt.frameFormat == ExtendedIdent {
//		return nil, errors.New("Extended message set for this message type is not supported")
//	}
//	mask, err := checkAttributeMask(m, opt.attributeMask)
//	if err != nil {
//		return nil, err
//	}
//	// Common for all MEs
//	meLayer := &TestRequest{
//		MeBasePacket: MeBasePacket{
//			EntityClass:    m.GetClassID(),
//			EntityInstance: m.GetEntityID(),
//			Extended:       opt.frameFormat == ExtendedIdent,
//		},
//	}
//	// Get payload space available
//	maxPayload := maxPacketAvailable(m, opt)
//
//	// TODO: Lots of work to do
//
//	fmt.Println(mask, maxPayload)
//	return meLayer, errors.New("todo: Not implemented")
//}

//func TestResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
//	if opt.frameFormat == ExtendedIdent {
//		return nil, errors.New("Extended message set for this message type is not supported")
//	}
//	mask, err := checkAttributeMask(m, opt.attributeMask)
//	if err != nil {
//		return nil, err
//	}
//	// Common for all MEs
//	meLayer := &TestResponse{
//		MeBasePacket: MeBasePacket{
//			EntityClass:    m.GetClassID(),
//			EntityInstance: m.GetEntityID(),
//			Extended:       opt.frameFormat == ExtendedIdent,
//		},
//	}
//	// Get payload space available
//	maxPayload := maxPacketAvailable(m, opt)
//
//	// TODO: Lots of work to do
//
//	fmt.Println(mask, maxPayload)
//	return meLayer, errors.New("todo: Not implemented")
//}

func StartSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &StartSoftwareDownloadRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		WindowSize:           opt.software.WindowSize,
		ImageSize:            opt.software.ImageSize,
		NumberOfCircuitPacks: byte(len(opt.software.CircuitPacks)),
		CircuitPacks:         opt.software.CircuitPacks,
	}
	// TODO: Add length check to insure we do not exceed maximum packet size
	// payloadAvailable := int(maxPacketAvailable(m, opt))
	payloadAvailable := 2
	sizeNeeded := 1
	if sizeNeeded > payloadAvailable {
		// TODO: Should we set truncate?
		msg := "out-of-space. Cannot fit Circuit Pack instances into Start Software Download Request message"
		return nil, me.NewMessageTruncatedError(msg)
	}
	return meLayer, nil
}

func StartSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &StartSoftwareDownloadResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		WindowSize:        opt.software.WindowSize,
		NumberOfInstances: byte(len(opt.software.CircuitPacks)),
		MeResults:         opt.software.Results,
	}
	// TODO: Add length check to insure we do not exceed maximum packet size
	// payloadAvailable := int(maxPacketAvailable(m, opt))
	payloadAvailable := 2
	sizeNeeded := 1
	if sizeNeeded > payloadAvailable {
		// TODO: Should we set truncate?
		msg := "out-of-space. Cannot fit Results  into Start Software Download Response message"
		return nil, me.NewMessageTruncatedError(msg)
	}
	return meLayer, nil
}

func DownloadSectionRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.software.Data == nil {
		return nil, me.NewNonStatusError("Software image data missing")
	}
	// Common for all MEs
	meLayer := &DownloadSectionRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		SectionNumber: opt.software.SectionNumber,
		SectionData:   opt.software.Data,
	}
	return meLayer, nil
}

func DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &DownloadSectionResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result:        opt.result,
		SectionNumber: opt.software.SectionNumber,
	}
	return meLayer, nil
}

func EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &EndSoftwareDownloadRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func EndSoftwareDownloadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &EndSoftwareDownloadResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func ActivateSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &ActivateSoftwareRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func ActivateSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &ActivateSoftwareResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func CommitSoftwareRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &CommitSoftwareRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func CommitSoftwareResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &CommitSoftwareResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func SynchronizeTimeRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &SynchronizeTimeRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Decode payload option. If nil, no timestamp provided
	if timestamp, ok := opt.payload.(int64); ok {
		tm := time.Unix(timestamp, 0)
		meLayer.Year = uint16(tm.UTC().Year())
		meLayer.Month = uint8(tm.UTC().Month())
		meLayer.Day = uint8(tm.UTC().Day())
		meLayer.Hour = uint8(tm.UTC().Hour())
		meLayer.Minute = uint8(tm.UTC().Minute())
		meLayer.Second = uint8(tm.UTC().Second())
	}
	return meLayer, nil
}

func SynchronizeTimeResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &SynchronizeTimeResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result:         opt.result,
		SuccessResults: opt.mode,
	}
	return meLayer, nil
}

func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &RebootRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		RebootCondition: opt.mode,
	}
	return meLayer, nil
}

func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Common for all MEs
	meLayer := &RebootResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result: opt.result,
	}
	return meLayer, nil
}

func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Validate attribute mask
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Now scan attributes and reduce mask to only those requested
	mask, err = calculateAttributeMask(m, mask)
	if err != nil {
		return nil, err
	}
	if mask == 0 {
		return nil, errors.New("no attributes requested for GetNextRequest")
	}
	// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
	// Common for all MEs
	meLayer := &GetNextRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		AttributeMask:  mask,
		SequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	// Validate attribute mask
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	mask, err = calculateAttributeMask(m, mask)
	if err != nil {
		return nil, err
	}
	//
	// Common for all MEs
	meLayer := &GetNextResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
		Result:        opt.result,
		AttributeMask: 0,
		Attributes:    make(me.AttributeValueMap),
	}
	if meLayer.Result == me.Success {
		// Get payload space available
		maxPayload := maxPacketAvailable(m, opt)
		payloadAvailable := int(maxPayload) - 3 // Less results and attribute mask
		meDefinition := m.GetManagedEntityDefinition()
		attrDefs := meDefinition.GetAttributeDefinitions()
		attrMap := m.GetAttributeValueMap()

		if mask == 0 {
			return nil, errors.New("no attributes requested for GetNextResponse")
		}
		// TODO: If more than one attribute or the attribute requested is not a table attribute, return an error
		// Iterate down the attributes (Attribute 0 is the ManagedEntity ID)
		var attrIndex uint
		for attrIndex = 1; attrIndex <= 16; attrIndex++ {
			// Is this attribute requested
			if mask&(1<<(16-attrIndex)) != 0 {
				// Get definitions since we need the name
				attrDef, ok := attrDefs[attrIndex]
				if !ok {
					msg := fmt.Sprintf("Unexpected error, index %v not valued for ME %v",
						attrIndex, meDefinition.GetName())
					return nil, errors.New(msg)
				}
				var attrValue interface{}
				attrValue, ok = attrMap[attrDef.Name]
				if !ok || attrValue == nil {
					msg := fmt.Sprintf("Unexpected error, attribute %v not provided in ME %v: %v",
						attrDef.GetName(), meDefinition.GetName(), m)
					return nil, errors.New(msg)
				}
				// Is space available?
				if attrDef.Size <= payloadAvailable {
					// Mark bit handled
					mask &= ^attrDef.Mask
					meLayer.AttributeMask |= attrDef.Mask
					meLayer.Attributes[attrDef.Name] = attrValue
					payloadAvailable -= attrDef.Size
				} else {
					// TODO: Should we set truncate?
					msg := fmt.Sprintf("out-of-space. Cannot fit attribute %v into GetNextResponse message",
						attrDef.GetName())
					return nil, me.NewMessageTruncatedError(msg)
				}
			}
		}
	}
	return meLayer, nil
}

//func TestResultFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
//	if opt.frameFormat == ExtendedIdent {
//		return nil, errors.New("Extended message set for this message type is not supported")
//	}
//	mask, err := checkAttributeMask(m, opt.attributeMask)
//	if err != nil {
//		return nil, err
//	}
//	// Common for all MEs
//	meLayer := &TestResultNotification{
//		MeBasePacket: MeBasePacket{
//			EntityClass:    m.GetClassID(),
//			EntityInstance: m.GetEntityID(),
//			Extended:       opt.frameFormat == ExtendedIdent,
//		},
//	}
//	// Get payload space available
//	maxPayload := maxPacketAvailable(m, opt)
//
//	// TODO: Lots of work to do
//
//	fmt.Println(mask, maxPayload)
//	return meLayer, errors.New("todo: Not implemented")
//}

func GetCurrentDataRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &GetCurrentDataRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func GetCurrentDataResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &GetCurrentDataResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func SetTableRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat != ExtendedIdent {
		return nil, errors.New("SetTable message type only supported with Extended OMCI Messaging")
	}
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &SetTableRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       opt.frameFormat == ExtendedIdent,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}

func SetTableResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	if opt.frameFormat != ExtendedIdent {
		return nil, errors.New("SetTable message type only supported with Extended OMCI Message Set")
	}
	if opt.frameFormat == ExtendedIdent {
		return nil, errors.New("Extended message set for this message type is not supported")
	}
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &SetTableResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
			Extended:       true,
		},
	}
	// Get payload space available
	maxPayload := maxPacketAvailable(m, opt)

	// TODO: Lots of work to do

	fmt.Println(mask, maxPayload)
	return meLayer, errors.New("todo: Not implemented")
}
