/*
 * 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
	ImageSize    uint32
	CircuitPacks []uint16 // slot (upper 8 bits) and instance (lower 8 bits)
	Results      []DownloadResults
}

var defaultSoftwareOptions = SoftwareOptions{
	WindowSize:   0,
	ImageSize:    0,
	CircuitPacks: nil,
	Results:      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			- 4 octets
	// MIC                  - 4 octets
	return MaxExtendedLength - 16
}

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) {
	// 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(),
		},
		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) {
	meLayer := &CreateResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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) {
	meLayer := &DeleteRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	return meLayer, nil
}

func DeleteResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	meLayer := &DeleteResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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

	meLayer := &SetRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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) {
	meLayer := &SetResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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(),
		},
		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(),
		},
		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) {
	// Common for all MEs
	meLayer := &GetAllAlarmsRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		AlarmRetrievalMode: opt.mode,
	}
	return meLayer, nil
}

func GetAllAlarmsResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &GetAllAlarmsResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		NumberOfCommands: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetAllAlarmsNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &GetAllAlarmsNextRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetAllAlarmsNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &GetAllAlarmsNextResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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) {
	// Common for all MEs
	meLayer := &MibUploadRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
		},
	}
	return meLayer, nil
}

func MibUploadResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &MibUploadResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
		},
		NumberOfCommands: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func MibUploadNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &MibUploadNextRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: 0,
		},
		CommandSequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func MibUploadNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &MibUploadNextResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	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) {
	// Common for all MEs
	meLayer := &MibResetRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	return meLayer, nil
}

func MibResetResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &MibResetResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		Result: opt.result,
	}
	return meLayer, nil
}

func AlarmNotificationFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	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(),
		},
	}
	// 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) {
	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(),
		},
		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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	// Common for all MEs
	meLayer := &StartSoftwareDownloadRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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) {
	// Common for all MEs
	meLayer := &StartSoftwareDownloadResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		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) {
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &DownloadSectionRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	// 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 DownloadSectionResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &DownloadSectionResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	// 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 EndSoftwareDownloadRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	// Common for all MEs
	meLayer := &SynchronizeTimeRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	// 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) {
	// Common for all MEs
	meLayer := &SynchronizeTimeResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		Result:         opt.result,
		SuccessResults: opt.mode,
	}
	return meLayer, nil
}

func RebootRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &RebootRequest{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		RebootCondition: opt.mode,
	}
	return meLayer, nil
}

func RebootResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// Common for all MEs
	meLayer := &RebootResponse{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
		Result: opt.result,
	}
	return meLayer, nil
}

func GetNextRequestFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// 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(),
		},
		AttributeMask:  mask,
		SequenceNumber: opt.sequenceNumberCountOrSize,
	}
	return meLayer, nil
}

func GetNextResponseFrame(m *me.ManagedEntity, opt options) (gopacket.SerializableLayer, error) {
	// 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(),
		},
		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) {
	mask, err := checkAttributeMask(m, opt.attributeMask)
	if err != nil {
		return nil, err
	}
	// Common for all MEs
	meLayer := &TestResultMsg{
		MeBasePacket: MeBasePacket{
			EntityClass:    m.GetClassID(),
			EntityInstance: m.GetEntityID(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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) {
	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(),
		},
	}
	// 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")
	}
	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(),
		},
	}
	// 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 Messaging")
	}
	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(),
		},
	}
	// 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")
}
