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

package omci

import (
	"encoding/binary"
	"errors"
	"fmt"
	me "github.com/cboling/omci/generated"
	"github.com/google/gopacket"
)

// MessageType is the OMCI Message Type or'ed with the AR/AK flags as appropriate.
type MessageType byte

const (
	CreateRequestType                 = MessageType(byte(me.Create) | me.AR)
	CreateResponseType                = MessageType(byte(me.Create) | me.AK)
	DeleteRequestType                 = MessageType(byte(me.Delete) | me.AR)
	DeleteResponseType                = MessageType(byte(me.Delete) | me.AK)
	SetRequestType                    = MessageType(byte(me.Set) | me.AR)
	SetResponseType                   = MessageType(byte(me.Set) | me.AK)
	GetRequestType                    = MessageType(byte(me.Get) | me.AR)
	GetResponseType                   = MessageType(byte(me.Get) | me.AK)
	GetAllAlarmsRequestType           = MessageType(byte(me.GetAllAlarms) | me.AR)
	GetAllAlarmsResponseType          = MessageType(byte(me.GetAllAlarms) | me.AK)
	GetAllAlarmsNextRequestType       = MessageType(byte(me.GetAllAlarmsNext) | me.AR)
	GetAllAlarmsNextResponseType      = MessageType(byte(me.GetAllAlarmsNext) | me.AK)
	MibUploadRequestType              = MessageType(byte(me.MibUpload) | me.AR)
	MibUploadResponseType             = MessageType(byte(me.MibUpload) | me.AK)
	MibUploadNextRequestType          = MessageType(byte(me.MibUploadNext) | me.AR)
	MibUploadNextResponseType         = MessageType(byte(me.MibUploadNext) | me.AK)
	MibResetRequestType               = MessageType(byte(me.MibReset) | me.AR)
	MibResetResponseType              = MessageType(byte(me.MibReset) | me.AK)
	TestRequestType                   = MessageType(byte(me.Test) | me.AR)
	TestResponseType                  = MessageType(byte(me.Test) | me.AK)
	StartSoftwareDownloadRequestType  = MessageType(byte(me.StartSoftwareDownload) | me.AR)
	StartSoftwareDownloadResponseType = MessageType(byte(me.StartSoftwareDownload) | me.AK)
	DownloadSectionRequestType        = MessageType(byte(me.DownloadSection) | me.AR)
	DownloadSectionResponseType       = MessageType(byte(me.DownloadSection) | me.AK)
	EndSoftwareDownloadRequestType    = MessageType(byte(me.EndSoftwareDownload) | me.AR)
	EndSoftwareDownloadResponseType   = MessageType(byte(me.EndSoftwareDownload) | me.AK)
	ActivateSoftwareRequestType       = MessageType(byte(me.ActivateSoftware) | me.AR)
	ActivateSoftwareResponseType      = MessageType(byte(me.ActivateSoftware) | me.AK)
	CommitSoftwareRequestType         = MessageType(byte(me.CommitSoftware) | me.AR)
	CommitSoftwareResponseType        = MessageType(byte(me.CommitSoftware) | me.AK)
	SynchronizeTimeRequestType        = MessageType(byte(me.SynchronizeTime) | me.AR)
	SynchronizeTimeResponseType       = MessageType(byte(me.SynchronizeTime) | me.AK)
	RebootRequestType                 = MessageType(byte(me.Reboot) | me.AR)
	RebootResponseType                = MessageType(byte(me.Reboot) | me.AK)
	GetNextRequestType                = MessageType(byte(me.GetNext) | me.AR)
	GetNextResponseType               = MessageType(byte(me.GetNext) | me.AK)
	GetCurrentDataRequestType         = MessageType(byte(me.GetCurrentData) | me.AR)
	GetCurrentDataResponseType        = MessageType(byte(me.GetCurrentData) | me.AK)
	SetTableRequestType               = MessageType(byte(me.SetTable) | me.AR)
	SetTableResponseType              = MessageType(byte(me.SetTable) | me.AK)
	// Autonomous ONU messages
	AlarmNotificationType    = MessageType(byte(me.AlarmNotification))
	AttributeValueChangeType = MessageType(byte(me.AttributeValueChange))
	TestResultType           = MessageType(byte(me.TestResult))
)

func (mt MessageType) String() string {
	switch mt {
	default:
		return "Unknown"

	case CreateRequestType:
		return "Create Request"
	case CreateResponseType:
		return "Create Response"
	case DeleteRequestType:
		return "Delete Request"
	case DeleteResponseType:
		return "Delete Response"
	case SetRequestType:
		return "Set Request"
	case SetResponseType:
		return "Set Response"
	case GetRequestType:
		return "Get Request"
	case GetResponseType:
		return "Get Response"
	case GetAllAlarmsRequestType:
		return "Get All Alarms Request"
	case GetAllAlarmsResponseType:
		return "Get All Alarms Response"
	case GetAllAlarmsNextRequestType:
		return "Get All Alarms Next Request"
	case GetAllAlarmsNextResponseType:
		return "Get All Alarms Next Response"
	case MibUploadRequestType:
		return "MIB Upload Request"
	case MibUploadResponseType:
		return "MIB Upload Response"
	case MibUploadNextRequestType:
		return "MIB Upload Next Request"
	case MibUploadNextResponseType:
		return "MIB Upload Next Response"
	case MibResetRequestType:
		return "MIB Reset Request"
	case MibResetResponseType:
		return "MIB Reset Response"
	case TestRequestType:
		return "Test Request"
	case TestResponseType:
		return "Test Response"
	case StartSoftwareDownloadRequestType:
		return "Start Software Download Request"
	case StartSoftwareDownloadResponseType:
		return "Start Software Download Response"
	case DownloadSectionRequestType:
		return "Download Section Request"
	case DownloadSectionResponseType:
		return "Download Section Response"
	case EndSoftwareDownloadRequestType:
		return "End Software Download Request"
	case EndSoftwareDownloadResponseType:
		return "End Software Download Response"
	case ActivateSoftwareRequestType:
		return "Activate Software Request"
	case ActivateSoftwareResponseType:
		return "Activate Software Response"
	case CommitSoftwareRequestType:
		return "Commit Software Request"
	case CommitSoftwareResponseType:
		return "Commit Software Response"
	case SynchronizeTimeRequestType:
		return "Synchronize Time Request"
	case SynchronizeTimeResponseType:
		return "Synchronize Time Response"
	case RebootRequestType:
		return "Reboot Request"
	case RebootResponseType:
		return "Reboot Response"
	case GetNextRequestType:
		return "Get Next Request"
	case GetNextResponseType:
		return "Get Next Response"
	case GetCurrentDataRequestType:
		return "Get Current Data Request"
	case GetCurrentDataResponseType:
		return "Get Current Data Response"
	case SetTableRequestType:
		return "Set Table Request"
	case SetTableResponseType:
		return "Set Table Response"
	case AlarmNotificationType:
		return "Alarm Notification"
	case AttributeValueChangeType:
		return "Attribute Value Change"
	case TestResultType:
		return "Test Result"
	}
}

/////////////////////////////////////////////////////////////////////////////
// CreateRequest
type CreateRequest struct {
	MeBasePacket
	Attributes me.AttributeValueMap
}

func (omci *CreateRequest) String() string {
	return fmt.Sprintf("%v, attributes: %v", omci.MeBasePacket.String(), omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of a Create Request into this layer
func (omci *CreateRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	// Create attribute mask for all set-by-create entries
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Create
	if !me.SupportsMsgType(meDefinition, me.Create) {
		return me.NewProcessingError("managed entity does not support Create Message-Type")
	}
	var sbcMask uint16
	for index, attr := range meDefinition.GetAttributeDefinitions() {
		if me.SupportsAttributeAccess(attr, me.SetByCreate) {
			if index == 0 {
				continue // Skip Entity ID
			}
			sbcMask |= attr.Mask
		}
	}
	// Attribute decode
	omci.Attributes, err = meDefinition.DecodeAttributes(sbcMask, data[4:], p, byte(CreateRequestType))
	if err != nil {
		return err
	}
	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
		return nil
	}
	panic("All Managed Entities have an EntityID attribute")
}

func decodeCreateRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &CreateRequest{}
	omci.MsgLayerType = LayerTypeCreateRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Create Request Message
func (omci *CreateRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// Create attribute mask of SetByCreate attributes that should be present in the provided
	// attributes.
	var sbcMask uint16
	for index, attr := range meDefinition.GetAttributeDefinitions() {
		if me.SupportsAttributeAccess(attr, me.SetByCreate) {
			if index == 0 {
				continue // Skip Entity ID
			}
			sbcMask |= attr.Mask
		}
	}
	// Attribute serialization
	// TODO: Only Baseline supported at this time
	bytesAvailable := MaxBaselineLength - 8 - 8
	err, _ = meDefinition.SerializeAttributes(omci.Attributes, sbcMask, b, byte(CreateRequestType), bytesAvailable, false)
	return err
}

/////////////////////////////////////////////////////////////////////////////
// CreateResponse
type CreateResponse struct {
	MeBasePacket
	Result                 me.Results
	AttributeExecutionMask uint16 // Used when Result == ParameterError
}

func (omci *CreateResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Mask: %#x",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeExecutionMask)
}

// DecodeFromBytes decodes the given bytes of a Create Response into this layer
func (omci *CreateResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Create
	if !me.SupportsMsgType(entity, me.Create) {
		return me.NewProcessingError("managed entity does not support the Create Message-Type")
	}
	omci.Result = me.Results(data[4])
	if omci.Result == me.ParameterError {
		omci.AttributeExecutionMask = binary.BigEndian.Uint16(data[5:])
		// TODO: validation that attributes set in mask are SetByCreate would be good here
	}
	return nil
}

func decodeCreateResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &CreateResponse{}
	omci.MsgLayerType = LayerTypeCreateResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Create Response message
func (omci *CreateResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Create
	if !me.SupportsMsgType(entity, me.Create) {
		return me.NewProcessingError("managed entity does not support the Create Message-Type")
	}
	bytes, err := b.AppendBytes(3)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	if omci.Result == me.ParameterError {
		// TODO: validation that attributes set in mask are SetByCreate would be good here
		binary.BigEndian.PutUint16(bytes[1:], omci.AttributeExecutionMask)
	} else {
		binary.BigEndian.PutUint16(bytes[1:], 0)
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// DeleteRequest
type DeleteRequest struct {
	MeBasePacket
}

func (omci *DeleteRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Delete Request into this layer
func (omci *DeleteRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Delete
	if !me.SupportsMsgType(entity, me.Delete) {
		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
	}
	return nil
}

func decodeDeleteRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &DeleteRequest{}
	omci.MsgLayerType = LayerTypeDeleteRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Delete Request message
func (omci *DeleteRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Delete
	if !me.SupportsMsgType(entity, me.Delete) {
		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// DeleteResponse
type DeleteResponse struct {
	MeBasePacket
	Result me.Results
}

func (omci *DeleteResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v)",
		omci.MeBasePacket.String(), omci.Result, omci.Result)
}

// DecodeFromBytes decodes the given bytes of a Delete Response into this layer
func (omci *DeleteResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Delete
	if !me.SupportsMsgType(entity, me.Delete) {
		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
	}
	omci.Result = me.Results(data[4])
	return nil
}

func decodeDeleteResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &DeleteResponse{}
	omci.MsgLayerType = LayerTypeDeleteResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Delete Response message
func (omci *DeleteResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Delete
	if !me.SupportsMsgType(entity, me.Delete) {
		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// SetRequest
type SetRequest struct {
	MeBasePacket
	AttributeMask uint16
	Attributes    me.AttributeValueMap
}

func (omci *SetRequest) String() string {
	return fmt.Sprintf("%v, Mask: %#x, attributes: %v",
		omci.MeBasePacket.String(), omci.AttributeMask, omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of a Set Request into this layer
func (omci *SetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(meDefinition, me.Set) {
		return me.NewProcessingError("managed entity does not support Set Message-Type")
	}
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])

	// Attribute decode
	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:], p, byte(SetRequestType))
	if err != nil {
		return err
	}
	// Validate all attributes support write
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
			msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
		return nil
	}
	panic("All Managed Entities have an EntityID attribute")
}

func decodeSetRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &SetRequest{}
	omci.MsgLayerType = LayerTypeSetRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Set Request message
func (omci *SetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(meDefinition, me.Set) {
		return me.NewProcessingError("managed entity does not support Set Message-Type")
	}
	// Validate all attributes support write
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		// Do not test for write of Entity ID in the attribute list
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Write) {
			// TODO: Check ITU spec to see if this should be listed as a failed
			//       attribute and not a processing error.
			msg := fmt.Sprintf("attribute '%v' does not support write access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)

	// Attribute serialization
	// TODO: Only Baseline supported at this time
	bytesAvailable := MaxBaselineLength - 10 - 8

	err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
		byte(SetRequestType), bytesAvailable, false)
	return err
}

/////////////////////////////////////////////////////////////////////////////
// SetResponse
type SetResponse struct {
	MeBasePacket
	Result                   me.Results
	UnsupportedAttributeMask uint16
	FailedAttributeMask      uint16
}

func (omci *SetResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Unsupported Mask: %#x, Failed Mask: %#x",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.UnsupportedAttributeMask,
		omci.FailedAttributeMask)
}

// DecodeFromBytes decodes the given bytes of a Set Response into this layer
func (omci *SetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(entity, me.Set) {
		return me.NewProcessingError("managed entity does not support the Delete Message-Type")
	}
	omci.Result = me.Results(data[4])

	if omci.Result == me.AttributeFailure {
		omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[5:7])
		omci.FailedAttributeMask = binary.BigEndian.Uint16(data[7:9])
	}
	return nil
}

func decodeSetResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &SetResponse{}
	omci.MsgLayerType = LayerTypeSetResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Set Response message
func (omci *SetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(entity, me.Set) {
		return me.NewProcessingError("managed entity does not support the Set Message-Type")
	}
	bytes, err := b.AppendBytes(5)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	binary.BigEndian.PutUint16(bytes[1:3], omci.UnsupportedAttributeMask)
	binary.BigEndian.PutUint16(bytes[3:5], omci.FailedAttributeMask)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetRequest
type GetRequest struct {
	MeBasePacket
	AttributeMask uint16
}

func (omci *GetRequest) String() string {
	return fmt.Sprintf("%v, Mask: %#x",
		omci.MeBasePacket.String(), omci.AttributeMask)
}

// DecodeFromBytes decodes the given bytes of a Get Request into this layer
func (omci *GetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.Get) {
		return me.NewProcessingError("managed entity does not support Get Message-Type")
	}
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeGetRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetRequest{}
	omci.MsgLayerType = LayerTypeGetRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Request message
func (omci *GetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(meDefinition, me.Get) {
		return me.NewProcessingError("managed entity does not support Get Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetResponse
type GetResponse struct {
	MeBasePacket
	Result                   me.Results
	AttributeMask            uint16
	Attributes               me.AttributeValueMap
	UnsupportedAttributeMask uint16
	FailedAttributeMask      uint16
}

func (omci *GetResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Mask: %#x, Unsupported: %#x, Failed: %#x, attributes: %v",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeMask,
		omci.UnsupportedAttributeMask, omci.FailedAttributeMask, omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of a Get Response into this layer
func (omci *GetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.Get) {
		return me.NewProcessingError("managed entity does not support Get Message-Type")
	}
	omci.Result = me.Results(data[4])
	omci.AttributeMask = binary.BigEndian.Uint16(data[5:7])

	// Attribute decode. Note that the ITU-T G.988 specification states that the
	//                   Unsupported and Failed attribute masks are always present
	//                   but only valid if the status code== 9.  However some XGS
	//                   ONUs (T&W and Alpha, perhaps more) will use these last 4
	//                   octets for data if the status code == 0.  So accommodate
	//                   this behaviour in favor of greater interoperability.
	lastOctet := 36
	if omci.Result == me.AttributeFailure {
		lastOctet = 32
	}
	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[7:lastOctet], p, byte(GetResponseType))
	if err != nil {
		return err
	}
	// If Attribute failed or Unknown, decode optional attribute mask
	if omci.Result == me.AttributeFailure {
		omci.UnsupportedAttributeMask = binary.BigEndian.Uint16(data[32:34])
		omci.FailedAttributeMask = binary.BigEndian.Uint16(data[34:36])
	}
	// Validate all attributes support read
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
		return nil
	}
	panic("All Managed Entities have an EntityID attribute")
}

func decodeGetResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetResponse{}
	omci.MsgLayerType = LayerTypeGetResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Response message
func (omci *GetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	if err := omci.MeBasePacket.SerializeTo(b); err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})

	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.Get) {
		return me.NewProcessingError("managed entity does not support the Get Message-Type")
	}
	bytes, err := b.AppendBytes(3)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)

	// Validate all attributes support read
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	// Attribute serialization
	switch omci.Result {
	default:
		break

	case me.Success, me.AttributeFailure:
		// TODO: Baseline only supported at this time)
		available := MaxBaselineLength - 11 - 4 - 8

		// Serialize to temporary buffer if we may need to reset values due to
		// recoverable truncation errors
		origBuffer := b
		b := gopacket.NewSerializeBuffer()

		err, failedMask := meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b, byte(GetResponseType),
			available, opts.FixLengths)

		if err == nil && failedMask != 0 && opts.FixLengths {
			// Not all attributes would fit
			omci.FailedAttributeMask |= failedMask
			omci.AttributeMask &= ^failedMask
			omci.Result = me.AttributeFailure

			// Adjust already recorded values
			bytes[0] = byte(omci.Result)
			binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)
		} else if err != nil {
			return err
		}
		// Copy over attributes to the original serialization buffer
		newSpace, err := origBuffer.AppendBytes(len(b.Bytes()))
		if err != nil {
			return err
		}
		copy(newSpace, b.Bytes())
		b = origBuffer

		// Calculate space left. Max  - msgType header - OMCI trailer - spacedUsedSoFar
		bytesLeft := MaxBaselineLength - 4 - 8 - len(b.Bytes())

		remainingBytes, err := b.AppendBytes(bytesLeft + 4)
		if err != nil {
			return me.NewMessageTruncatedError(err.Error())
		}
		copy(remainingBytes, lotsOfZeros[:])

		if omci.Result == me.AttributeFailure {
			binary.BigEndian.PutUint16(remainingBytes[bytesLeft-4:bytesLeft-2], omci.UnsupportedAttributeMask)
			binary.BigEndian.PutUint16(remainingBytes[bytesLeft-2:bytesLeft], omci.FailedAttributeMask)
		}
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetAllAlarms
type GetAllAlarmsRequest struct {
	MeBasePacket
	AlarmRetrievalMode byte
}

func (omci *GetAllAlarmsRequest) String() string {
	return fmt.Sprintf("%v, Retrieval Mode: %v",
		omci.MeBasePacket.String(), omci.AlarmRetrievalMode)
}

// DecodeFromBytes decodes the given bytes of a Get All Alarms Request into this layer
func (omci *GetAllAlarmsRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
		return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms request: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms request: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.AlarmRetrievalMode = data[4]
	if omci.AlarmRetrievalMode > 1 {
		msg := fmt.Sprintf("invalid Alarm Retrieval Mode for Get All Alarms request: %v, must be 0..1",
			omci.AlarmRetrievalMode)
		return errors.New(msg)
	}
	return nil
}

func decodeGetAllAlarmsRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetAllAlarmsRequest{}
	omci.MsgLayerType = LayerTypeGetAllAlarmsRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get All Alarms Request message
func (omci *GetAllAlarmsRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(entity, me.GetAllAlarms) {
		return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = omci.AlarmRetrievalMode
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetAllAlarms
type GetAllAlarmsResponse struct {
	MeBasePacket
	NumberOfCommands uint16
}

func (omci *GetAllAlarmsResponse) String() string {
	return fmt.Sprintf("%v, NumberOfCommands: %d",
		omci.MeBasePacket.String(), omci.NumberOfCommands)
}

// DecodeFromBytes decodes the given bytes of a Get All Alarms Response into this layer
func (omci *GetAllAlarmsResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(meDefinition, me.GetAllAlarms) {
		return me.NewProcessingError("managed entity does not support Get All Alarms Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms response: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms response: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.NumberOfCommands = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeGetAllAlarmsResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetAllAlarmsResponse{}
	omci.MsgLayerType = LayerTypeGetAllAlarmsResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get All Alarms Response message
func (omci *GetAllAlarmsResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(entity, me.GetAllAlarms) {
		return me.NewProcessingError("managed entity does not support the Get All Alarms Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], omci.NumberOfCommands)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetAllAlarms
type GetAllAlarmsNextRequest struct {
	MeBasePacket
	CommandSequenceNumber uint16
}

func (omci *GetAllAlarmsNextRequest) String() string {
	return fmt.Sprintf("%v, Sequence Number: %d",
		omci.MeBasePacket.String(), omci.CommandSequenceNumber)
}

// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Request into this layer
func (omci *GetAllAlarmsNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
		return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next request: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next request: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeGetAllAlarmsNextRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetAllAlarmsNextRequest{}
	omci.MsgLayerType = LayerTypeGetAllAlarmsNextRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get All Alarms Next Request message
func (omci *GetAllAlarmsNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms Next
	if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
		return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.CommandSequenceNumber)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// GetAllAlarms
type GetAllAlarmsNextResponse struct {
	MeBasePacket
	AlarmEntityClass    me.ClassID
	AlarmEntityInstance uint16
	AlarmBitMap         [28]byte // 224 bits
}

func (omci *GetAllAlarmsNextResponse) String() string {
	return fmt.Sprintf("%v, CID: %v, EID: (%d/%#x), Bitmap: %v",
		omci.MeBasePacket.String(), omci.AlarmEntityClass, omci.AlarmEntityInstance,
		omci.AlarmEntityInstance, omci.AlarmBitMap)
}

// DecodeFromBytes decodes the given bytes of a Get All Alarms Next Response into this layer
func (omci *GetAllAlarmsNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms Next
	if !me.SupportsMsgType(meDefinition, me.GetAllAlarmsNext) {
		return me.NewProcessingError("managed entity does not support Get All Alarms Next Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for Get All Alarms Next response: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for Get All Alarms Next response: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.AlarmEntityClass = me.ClassID(binary.BigEndian.Uint16(data[4:6]))
	omci.AlarmEntityInstance = binary.BigEndian.Uint16(data[6:8])

	copy(omci.AlarmBitMap[:], data[8:36])
	return nil
}

func decodeGetAllAlarmsNextResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetAllAlarmsNextResponse{}
	omci.MsgLayerType = LayerTypeGetAllAlarmsNextResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get All Alarms Next Response message
func (omci *GetAllAlarmsNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms Next
	if !me.SupportsMsgType(entity, me.GetAllAlarmsNext) {
		return me.NewProcessingError("managed entity does not support the Get All Alarms Next Message-Type")
	}
	bytes, err := b.AppendBytes(2 + 2 + 28)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:], uint16(omci.AlarmEntityClass))
	binary.BigEndian.PutUint16(bytes[2:], omci.AlarmEntityInstance)
	copy(bytes[4:], omci.AlarmBitMap[:])
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// MibUploadRequest
type MibUploadRequest struct {
	MeBasePacket
}

func (omci *MibUploadRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a MIB Upload Request into this layer
func (omci *MibUploadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB Upload
	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
		return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload request: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload request: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	return nil
}

func decodeMibUploadRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibUploadRequest{}
	omci.MsgLayerType = LayerTypeMibUploadRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Upload Request message
func (omci *MibUploadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
		return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// MibUploadResponse
type MibUploadResponse struct {
	MeBasePacket
	NumberOfCommands uint16
}

func (omci *MibUploadResponse) String() string {
	return fmt.Sprintf("%v, NumberOfCommands: %#v",
		omci.MeBasePacket.String(), omci.NumberOfCommands)
}

// DecodeFromBytes decodes the given bytes of a MIB Upload Response into this layer
func (omci *MibUploadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB Upload
	if !me.SupportsMsgType(meDefinition, me.MibUpload) {
		return me.NewProcessingError("managed entity does not support MIB Upload Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload response: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload response: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.NumberOfCommands = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeMibUploadResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibUploadResponse{}
	omci.MsgLayerType = LayerTypeMibUploadResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Upload Response message
func (omci *MibUploadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB Upload
	if !me.SupportsMsgType(entity, me.MibUpload) {
		return me.NewProcessingError("managed entity does not support the MIB Upload Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], omci.NumberOfCommands)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type MibUploadNextRequest struct {
	MeBasePacket
	CommandSequenceNumber uint16
}

func (omci *MibUploadNextRequest) String() string {
	return fmt.Sprintf("%v, SequenceNumberCountOrSize: %v",
		omci.MeBasePacket.String(), omci.CommandSequenceNumber)
}

// DecodeFromBytes decodes the given bytes of a MIB Upload Next Request into this layer
func (omci *MibUploadNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get All Alarms
	if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
		return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload Next request: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next request: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	omci.CommandSequenceNumber = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeMibUploadNextRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibUploadNextRequest{}
	omci.MsgLayerType = LayerTypeMibUploadNextRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Upload Next Request message
func (omci *MibUploadNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB upload
	if !me.SupportsMsgType(entity, me.MibUploadNext) {
		return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], omci.CommandSequenceNumber)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type MibUploadNextResponse struct {
	MeBasePacket
	ReportedME me.ManagedEntity
}

func (omci *MibUploadNextResponse) String() string {
	return fmt.Sprintf("%v, ReportedME: [%v]",
		omci.MeBasePacket.String(), omci.ReportedME.String())
}

// DecodeFromBytes decodes the given bytes of a MIB Upload Next Response into this layer
func (omci *MibUploadNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MibUploadNext
	if !me.SupportsMsgType(meDefinition, me.MibUploadNext) {
		return me.NewProcessingError("managed entity does not support MIB Upload Next Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for  MIB Upload Next response: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for MIB Upload Next response: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	// Decode reported ME.  If an out-of-range sequence number was sent, this will
	// contain an ME with class ID and entity ID of zero and you should get an
	// error of "managed entity definition not found" returned.
	return omci.ReportedME.DecodeFromBytes(data[4:], p, byte(MibUploadNextResponseType))
}

func decodeMibUploadNextResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibUploadNextResponse{}
	omci.MsgLayerType = LayerTypeMibUploadNextResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Upload Next Response message
func (omci *MibUploadNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB Upload
	if !me.SupportsMsgType(entity, me.MibUploadNext) {
		return me.NewProcessingError("managed entity does not support the MIB Upload Next Message-Type")
	}
	// TODO: Only Baseline supported at this time
	bytesAvailable := MaxBaselineLength - 8 - 8

	return omci.ReportedME.SerializeTo(b, byte(MibUploadNextResponseType), bytesAvailable, opts)
}

/////////////////////////////////////////////////////////////////////////////
// MibResetRequest
type MibResetRequest struct {
	MeBasePacket
}

func (omci *MibResetRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a MIB Reset Request into this layer
func (omci *MibResetRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB reset
	if !me.SupportsMsgType(meDefinition, me.MibReset) {
		return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
	}
	// Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		msg := fmt.Sprintf("invalid Entity Class for MIB Reset request: %v",
			omci.EntityClass)
		return me.NewProcessingError(msg)
	}
	if omci.EntityInstance != 0 {
		msg := fmt.Sprintf("invalid Entity Instance for MIB Reset request: %v",
			omci.EntityInstance)
		return me.NewUnknownInstanceError(msg)
	}
	return nil
}

func decodeMibResetRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibResetRequest{}
	omci.MsgLayerType = LayerTypeMibResetRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Reset Request message
func (omci *MibResetRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Add class ID and entity ID
	return omci.MeBasePacket.SerializeTo(b)
}

/////////////////////////////////////////////////////////////////////////////
// MibResetResponse
type MibResetResponse struct {
	MeBasePacket
	Result me.Results
}

func (omci *MibResetResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v)",
		omci.MeBasePacket.String(), omci.Result, omci.Result)
}

// DecodeFromBytes decodes the given bytes of a MIB Reset Response into this layer
func (omci *MibResetResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support MIB reset
	if !me.SupportsMsgType(meDefinition, me.MibReset) {
		return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
	}
	// MIB Reset Response Entity Class always ONU DATA (2) and
	// Entity Instance of 0
	if omci.EntityClass != me.OnuDataClassID {
		return me.NewProcessingError("invalid Entity Class for MIB Reset Response")
	}
	if omci.EntityInstance != 0 {
		return me.NewUnknownInstanceError("invalid Entity Instance for MIB Reset Response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results code: %v, must be 0..8", omci.Result)
		return errors.New(msg)
	}
	return nil
}

func decodeMibResetResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &MibResetResponse{}
	omci.MsgLayerType = LayerTypeMibResetResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an MIB Reset Response message
func (omci *MibResetResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(entity, me.MibReset) {
		return me.NewProcessingError("managed entity does not support the MIB Reset Message-Type")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// AlarmNotificationMsg
const AlarmBitmapSize = 224

type AlarmNotificationMsg struct {
	MeBasePacket
	AlarmBitmap         [AlarmBitmapSize / 8]byte
	zeroPadding         [3]byte
	AlarmSequenceNumber byte
}

func (omci *AlarmNotificationMsg) String() string {
	return fmt.Sprintf("%v, Sequence Number: %d, Alarm Bitmap: %v",
		omci.MeBasePacket.String(), omci.AlarmSequenceNumber, omci.AlarmBitmap)
}

func (omci *AlarmNotificationMsg) IsAlarmActive(alarmNumber uint8) (bool, error) {
	if alarmNumber >= AlarmBitmapSize {
		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
		return false, errors.New(msg)
	}
	octet := alarmNumber / 8
	bit := 7 - (alarmNumber % 8)
	return omci.AlarmBitmap[octet]>>bit == 1, nil
}

func (omci *AlarmNotificationMsg) IsAlarmClear(alarmNumber uint8) (bool, error) {
	if alarmNumber >= AlarmBitmapSize {
		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
		return false, errors.New(msg)
	}
	octet := alarmNumber / 8
	bit := 7 - (alarmNumber % 8)
	return omci.AlarmBitmap[octet]>>bit == 0, nil
}

func (omci *AlarmNotificationMsg) ActivateAlarm(alarmNumber uint8) error {
	if alarmNumber >= AlarmBitmapSize {
		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
		return errors.New(msg)
	}
	octet := alarmNumber / 8
	bit := 7 - (alarmNumber % 8)
	omci.AlarmBitmap[octet] |= 1 << bit
	return nil
}

func (omci *AlarmNotificationMsg) ClearAlarm(alarmNumber uint8) error {
	if alarmNumber >= AlarmBitmapSize {
		msg := fmt.Sprintf("invalid alarm number: %v, must be 0..224", alarmNumber)
		return errors.New(msg)
	}
	octet := alarmNumber / 8
	bit := 7 - (alarmNumber % 8)
	omci.AlarmBitmap[octet] &= ^(1 << bit)
	return nil
}

// DecodeFromBytes decodes the given bytes of an Alarm Notification into this layer
func (omci *AlarmNotificationMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	//var meDefinition me.IManagedEntityDefinition
	//meDefinition, err = me.LoadManagedEntityDefinition(omci.EntityClass,
	//	me.ParamData{EntityID: omci.EntityInstance})
	//if err != nil {
	//	return err
	//}
	// ME needs to support Alarms
	// TODO: Add attribute to ME to specify that alarm is allowed
	//if !me.SupportsMsgType(meDefinition, me.MibReset) {
	//	return me.NewProcesssingError("managed entity does not support MIB Reset Message-Type")
	//}
	for index, octet := range data[4 : (AlarmBitmapSize/8)-4] {
		omci.AlarmBitmap[index] = octet
	}
	padOffset := 4 + (AlarmBitmapSize / 8)
	omci.zeroPadding[0] = data[padOffset]
	omci.zeroPadding[1] = data[padOffset+1]
	omci.zeroPadding[2] = data[padOffset+2]

	omci.AlarmSequenceNumber = data[padOffset+3]
	return nil
}

func decodeAlarmNotification(data []byte, p gopacket.PacketBuilder) error {
	omci := &AlarmNotificationMsg{}
	omci.MsgLayerType = LayerTypeAlarmNotification
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Alarm Notification message
func (omci *AlarmNotificationMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	//var meDefinition me.IManagedEntityDefinition
	//meDefinition, err = me.LoadManagedEntityDefinition(omci.EntityClass,
	//	me.ParamData{EntityID: omci.EntityInstance})
	//if err != nil {
	//	return err
	//}
	// ME needs to support Alarms
	// TODO: Add attribute to ME to specify that alarm is allowed
	//if !me.SupportsMsgType(meDefinition, me.MibReset) {
	//	return me.NewProcessingError("managed entity does not support MIB Reset Message-Type")
	//}
	bytes, err := b.AppendBytes((AlarmBitmapSize / 8) + 3 + 1)
	if err != nil {
		return err
	}
	for index, octet := range omci.AlarmBitmap {
		bytes[index] = octet
	}
	padOffset := AlarmBitmapSize / 8
	bytes[padOffset] = 0
	bytes[padOffset+1] = 0
	bytes[padOffset+2] = 0
	bytes[padOffset+3] = omci.AlarmSequenceNumber
	return nil
}

/////////////////////////////////////////////////////////////////////////////
// AttributeValueChangeMsg
type AttributeValueChangeMsg struct {
	MeBasePacket
	AttributeMask uint16
	Attributes    me.AttributeValueMap
}

func (omci *AttributeValueChangeMsg) String() string {
	return fmt.Sprintf("%v, Mask: %#x, attributes: %v",
		omci.MeBasePacket.String(), omci.AttributeMask, omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of an Attribute Value Change notification into this layer
func (omci *AttributeValueChangeMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
	// Attribute decode
	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:40], p, byte(AttributeValueChangeType))
	// TODO: Add support for attributes that can have an AVC associated with them and then add a check here
	// Validate all attributes support AVC
	//for attrName := range omci.attributes {
	//	attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
	//	if err != nil {
	//		return err
	//	}
	//	if attr.Index != 0 && !me.SupportsAttributeAVC(attr) {
	//		msg := fmt.Sprintf("attribute '%v' does not support AVC notifications", attrName)
	//		return me.NewProcessingError(msg)
	//	}
	//}
	return err
}

func decodeAttributeValueChange(data []byte, p gopacket.PacketBuilder) error {
	omci := &AttributeValueChangeMsg{}
	omci.MsgLayerType = LayerTypeAttributeValueChange
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Attribute Value Change Notification message
func (omci *AttributeValueChangeMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// TODO: Add support for attributes that can have an AVC associated with them and then add a check here
	// Validate all attributes support AVC
	//for attrName := range omci.attributes {
	//	attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
	//	if err != nil {
	//		return err
	//	}
	//	if attr.Index != 0 && !me.SupportsAttributeAVC(attr) {
	//		msg := fmt.Sprintf("attribute '%v' does not support AVC notifications", attrName)
	//		return me.NewProcessingError(msg)
	//	}
	//}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)

	// Attribute serialization
	// TODO: Only Baseline supported at this time
	bytesAvailable := MaxBaselineLength - 10 - 8

	err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
		byte(AttributeValueChangeType), bytesAvailable, false)
	return err
}

/////////////////////////////////////////////////////////////////////////////
// TestRequest:		TODO: Not yet implemented
type TestRequest struct {
	MeBasePacket
}

func (omci *TestRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Test Request into this layer
func (omci *TestRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // return nil
}

func decodeTestRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &TestRequest{}
	omci.MsgLayerType = LayerTypeTestRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Test Request message
func (omci *TestRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
}

/////////////////////////////////////////////////////////////////////////////
// TestResponse:		TODO: Not yet implemented
type TestResponse struct {
	MeBasePacket
}

func (omci *TestResponse) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Test Response into this layer
func (omci *TestResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // return nil
}

func decodeTestResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &TestResponse{}
	omci.MsgLayerType = LayerTypeTestResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Test Response message
func (omci *TestResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
}

/////////////////////////////////////////////////////////////////////////////
//
type StartSoftwareDownloadRequest struct {
	MeBasePacket                // Note: EntityInstance for software download is two specific values
	WindowSize           byte   // Window Size -1
	ImageSize            uint32 // Octets
	NumberOfCircuitPacks byte
	CircuitPacks         []uint16 // MSB & LSB of software image instance
}

func (omci *StartSoftwareDownloadRequest) String() string {
	return fmt.Sprintf("%v, Window Size: %v, Image Size: %v, # Circuit Packs: %v",
		omci.MeBasePacket.String(), omci.WindowSize, omci.ImageSize, omci.NumberOfCircuitPacks)
}

// DecodeFromBytes decodes the given bytes of a Start Software Download Request into this layer
func (omci *StartSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Start Software Download
	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Start Software Download request")
	}
	omci.WindowSize = data[4]
	omci.ImageSize = binary.BigEndian.Uint32(data[5:9])
	omci.NumberOfCircuitPacks = data[9]
	if omci.NumberOfCircuitPacks < 1 || omci.NumberOfCircuitPacks > 9 {
		return me.NewProcessingError(fmt.Sprintf("invalid number of Circuit Packs: %v, must be 1..9",
			omci.NumberOfCircuitPacks))
	}
	omci.CircuitPacks = make([]uint16, omci.NumberOfCircuitPacks)
	for index := 0; index < int(omci.NumberOfCircuitPacks); index++ {
		omci.CircuitPacks[index] = binary.BigEndian.Uint16(data[10+(index*2):])
	}
	return nil
}

func decodeStartSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &StartSoftwareDownloadRequest{}
	omci.MsgLayerType = LayerTypeStartSoftwareDownloadRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Start Software Download Request message
func (omci *StartSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Start Software Download
	if !me.SupportsMsgType(entity, me.StartSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support the SStart Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Start Software Download request")
	}
	if omci.NumberOfCircuitPacks < 1 || omci.NumberOfCircuitPacks > 9 {
		return me.NewProcessingError(fmt.Sprintf("invalid number of Circuit Packs: %v, must be 1..9",
			omci.NumberOfCircuitPacks))
	}
	bytes, err := b.AppendBytes(6 + (2 * int(omci.NumberOfCircuitPacks)))
	if err != nil {
		return err
	}
	bytes[0] = omci.WindowSize
	binary.BigEndian.PutUint32(bytes[1:], omci.ImageSize)
	bytes[5] = omci.NumberOfCircuitPacks
	for index := 0; index < int(omci.NumberOfCircuitPacks); index++ {
		binary.BigEndian.PutUint16(bytes[6+(index*2):], omci.CircuitPacks[index])
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type downloadResults struct {
	ManagedEntityID uint16 // ME ID of software image entity instance (slot number plus instance 0..1 or 2..254 vendor-specific)
	Result          me.Results
}

func (dr *downloadResults) String() string {
	return fmt.Sprintf("ME: %v (%#x), Results: %d (%v)", dr.ManagedEntityID, dr.ManagedEntityID,
		dr.Result, dr.Result)
}

type StartSoftwareDownloadResponse struct {
	MeBasePacket      // Note: EntityInstance for software download is two specific values
	Result            me.Results
	WindowSize        byte // Window Size -1
	NumberOfInstances byte
	MeResults         []downloadResults
}

func (omci *StartSoftwareDownloadResponse) String() string {
	return fmt.Sprintf("%v, Results: %v, Window Size: %v, # of Instances: %v, ME Results: %v",
		omci.MeBasePacket.String(), omci.Result, omci.WindowSize, omci.NumberOfInstances, omci.MeResults)
}

// DecodeFromBytes decodes the given bytes of a Start Software Download Response into this layer
func (omci *StartSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Start Software Download
	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Start Software Download response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for Start Software Download response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	omci.WindowSize = data[5]
	omci.NumberOfInstances = data[6]

	if omci.NumberOfInstances > 9 {
		msg := fmt.Sprintf("invalid number of Circuit Packs: %v, must be 0..9",
			omci.NumberOfInstances)
		return errors.New(msg)
	}
	if omci.NumberOfInstances > 0 {
		omci.MeResults = make([]downloadResults, omci.NumberOfInstances)

		for index := 0; index < int(omci.NumberOfInstances); index++ {
			omci.MeResults[index].ManagedEntityID = binary.BigEndian.Uint16(data[7+(index*3):])
			omci.MeResults[index].Result = me.Results(data[9+(index*3)])
			if omci.MeResults[index].Result > me.DeviceBusy {
				msg := fmt.Sprintf("invalid results for Start Software Download instance %v response: %v, must be 0..6",
					index, omci.MeResults[index])
				return errors.New(msg)
			}
		}
	}
	return nil
}

func decodeStartSoftwareDownloadResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &StartSoftwareDownloadResponse{}
	omci.MsgLayerType = LayerTypeStartSoftwareDownloadResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Start Software Download Response message
func (omci *StartSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Start Software Download
	if !me.SupportsMsgType(meDefinition, me.StartSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support Start Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Start Software Download response")
	}
	bytes, err := b.AppendBytes(3 + (3 * int(omci.NumberOfInstances)))
	if err != nil {
		return err
	}
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for Start Software Download response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	bytes[0] = byte(omci.Result)
	bytes[1] = omci.WindowSize
	bytes[2] = omci.NumberOfInstances

	if omci.NumberOfInstances > 9 {
		msg := fmt.Sprintf("invalid number of Circuit Packs: %v, must be 0..9",
			omci.NumberOfInstances)
		return errors.New(msg)
	}
	if omci.NumberOfInstances > 0 {
		for index := 0; index < int(omci.NumberOfInstances); index++ {
			binary.BigEndian.PutUint16(bytes[3+(3*index):], omci.MeResults[index].ManagedEntityID)

			if omci.MeResults[index].Result > me.DeviceBusy {
				msg := fmt.Sprintf("invalid results for Start Software Download instance %v response: %v, must be 0..6",
					index, omci.MeResults[index])
				return errors.New(msg)
			}
			bytes[5+(3*index)] = byte(omci.MeResults[index].Result)
		}
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type DownloadSectionRequest struct {
	MeBasePacket  // Note: EntityInstance for software download is two specific values
	SectionNumber byte
	SectionData   [29]byte // 0 padding if final transfer requires only a partial block
}

func (omci *DownloadSectionRequest) String() string {
	return fmt.Sprintf("%v, Section #: %v",
		omci.MeBasePacket.String(), omci.SectionNumber)
}

// DecodeFromBytes decodes the given bytes of a Download Section Request into this layer
func (omci *DownloadSectionRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Download section
	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Download Section request")
	}
	omci.SectionNumber = data[4]
	copy(omci.SectionData[0:], data[5:])
	return nil
}

func decodeDownloadSectionRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &DownloadSectionRequest{}
	omci.MsgLayerType = LayerTypeDownloadSectionRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Download Section Request message
func (omci *DownloadSectionRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Download section
	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Download Section response")
	}
	bytes, err := b.AppendBytes(1 + 29)
	if err != nil {
		return err
	}
	bytes[0] = omci.SectionNumber
	copy(bytes[1:], omci.SectionData[0:])
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type DownloadSectionResponse struct {
	MeBasePacket  // Note: EntityInstance for software download is two specific values
	Result        me.Results
	SectionNumber byte
}

func (omci *DownloadSectionResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Section #: %v",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.SectionNumber)
}

// DecodeFromBytes decodes the given bytes of a Download Section Response into this layer
func (omci *DownloadSectionResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Download section
	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Download Section response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for Download Section response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	omci.SectionNumber = data[5]
	return nil
}

func decodeDownloadSectionResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &DownloadSectionResponse{}
	omci.MsgLayerType = LayerTypeDownloadSectionResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Download Section Response message
func (omci *DownloadSectionResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Download section
	if !me.SupportsMsgType(meDefinition, me.DownloadSection) {
		return me.NewProcessingError("managed entity does not support Download Section Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Download Section response")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	bytes[0] = omci.SectionNumber
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for Download Section response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	bytes[1] = byte(omci.Result)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type EndSoftwareDownloadRequest struct {
	MeBasePacket      // Note: EntityInstance for software download is two specific values
	CRC32             uint32
	ImageSize         uint32
	NumberOfInstances byte
	ImageInstances    []uint16
}

func (omci *EndSoftwareDownloadRequest) String() string {
	return fmt.Sprintf("%v, CRC: %#x, Image Size: %v, Number of Instances: %v, Instances: %v",
		omci.MeBasePacket.String(), omci.CRC32, omci.ImageSize, omci.NumberOfInstances, omci.ImageInstances)
}

// DecodeFromBytes decodes the given bytes of an End Software Download Request into this layer
func (omci *EndSoftwareDownloadRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support End Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for End Software Download request")
	}
	omci.CRC32 = binary.BigEndian.Uint32(data[4:8])
	omci.ImageSize = binary.BigEndian.Uint32(data[8:12])
	omci.NumberOfInstances = data[13]

	if omci.NumberOfInstances < 1 || omci.NumberOfInstances > 9 {
		return me.NewProcessingError(fmt.Sprintf("invalid number of Instances: %v, must be 1..9",
			omci.NumberOfInstances))
	}
	omci.ImageInstances = make([]uint16, omci.NumberOfInstances)

	for index := 0; index < int(omci.NumberOfInstances); index++ {
		omci.ImageInstances[index] = binary.BigEndian.Uint16(data[14+(index*2):])
	}
	return nil
}

func decodeEndSoftwareDownloadRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &EndSoftwareDownloadRequest{}
	omci.MsgLayerType = LayerTypeEndSoftwareDownloadRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an End Software Download Request message
func (omci *EndSoftwareDownloadRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support Start End Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for End Software Download response")
	}
	if omci.NumberOfInstances < 1 || omci.NumberOfInstances > 9 {
		return me.NewProcessingError(fmt.Sprintf("invalid number of Instances: %v, must be 1..9",
			omci.NumberOfInstances))
	}
	bytes, err := b.AppendBytes(9 + (2 * int(omci.NumberOfInstances)))
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint32(bytes[4:8], omci.CRC32)
	binary.BigEndian.PutUint32(bytes[8:12], omci.ImageSize)
	bytes[13] = omci.NumberOfInstances
	for index := 0; index < int(omci.NumberOfInstances); index++ {
		binary.BigEndian.PutUint16(bytes[14+(index*2):], omci.ImageInstances[index])
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type EndSoftwareDownloadResponse struct {
	MeBasePacket      // Note: EntityInstance for software download is two specific values
	Result            me.Results
	NumberOfInstances byte
	MeResults         []downloadResults
}

func (omci *EndSoftwareDownloadResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Number of Instances: %v, ME Results: %v",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.NumberOfInstances, omci.MeResults)
}

// DecodeFromBytes decodes the given bytes of an End Software Download Response into this layer
func (omci *EndSoftwareDownloadResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support End Software Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for End Software Download response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for End Software Download response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	omci.NumberOfInstances = data[5]

	if omci.NumberOfInstances > 9 {
		msg := fmt.Sprintf("invalid number of Instances: %v, must be 0..9",
			omci.NumberOfInstances)
		return errors.New(msg)
	}
	if omci.NumberOfInstances > 0 {
		omci.MeResults = make([]downloadResults, omci.NumberOfInstances)

		for index := 0; index < int(omci.NumberOfInstances); index++ {
			omci.MeResults[index].ManagedEntityID = binary.BigEndian.Uint16(data[6+(index*3):])
			omci.MeResults[index].Result = me.Results(data[8+(index*3)])
			if omci.MeResults[index].Result > me.DeviceBusy {
				msg := fmt.Sprintf("invalid results for End Software Download instance %v response: %v, must be 0..6",
					index, omci.MeResults[index])
				return errors.New(msg)
			}
		}
	}
	return nil
}

func decodeEndSoftwareDownloadResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &EndSoftwareDownloadResponse{}
	omci.MsgLayerType = LayerTypeEndSoftwareDownloadResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an End Software Download Response message
func (omci *EndSoftwareDownloadResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.EndSoftwareDownload) {
		return me.NewProcessingError("managed entity does not support End End Download Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for End Download response")
	}
	bytes, err := b.AppendBytes(3 + (3 * int(omci.NumberOfInstances)))
	if err != nil {
		return err
	}
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results for End Software Download response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	bytes[0] = byte(omci.Result)
	bytes[1] = omci.NumberOfInstances

	if omci.NumberOfInstances > 9 {
		msg := fmt.Sprintf("invalid number of Instances: %v, must be 0..9",
			omci.NumberOfInstances)
		return errors.New(msg)
	}
	if omci.NumberOfInstances > 0 {
		for index := 0; index < int(omci.NumberOfInstances); index++ {
			binary.BigEndian.PutUint16(bytes[2+(3*index):], omci.MeResults[index].ManagedEntityID)

			if omci.MeResults[index].Result > me.DeviceBusy {
				msg := fmt.Sprintf("invalid results for End Software Download instance %v response: %v, must be 0..6",
					index, omci.MeResults[index])
				return errors.New(msg)
			}
			bytes[4+(3*index)] = byte(omci.MeResults[index].Result)
		}
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type ActivateSoftwareRequest struct {
	MeBasePacket  // Note: EntityInstance for software download is two specific values
	ActivateFlags byte
}

func (omci *ActivateSoftwareRequest) String() string {
	return fmt.Sprintf("%v, Flags: %#x",
		omci.MeBasePacket.String(), omci.ActivateFlags)
}

// DecodeFromBytes decodes the given bytes of an Activate Software Request into this layer
func (omci *ActivateSoftwareRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
		return me.NewProcessingError("managed entity does not support Activate Software Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Activate Software request")
	}
	omci.ActivateFlags = data[4]
	if omci.ActivateFlags > 2 {
		return me.NewProcessingError(fmt.Sprintf("invalid number of Activation flangs: %v, must be 0..2",
			omci.ActivateFlags))
	}
	return nil
}

func decodeActivateSoftwareRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &ActivateSoftwareRequest{}
	omci.MsgLayerType = LayerTypeActivateSoftwareRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Activate Software message
func (omci *ActivateSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
		return me.NewProcessingError("managed entity does not support Activate Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Activate Software request")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = omci.ActivateFlags
	if omci.ActivateFlags > 2 {
		msg := fmt.Sprintf("invalid results for Activate Software request: %v, must be 0..2",
			omci.ActivateFlags)
		return errors.New(msg)
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type ActivateSoftwareResponse struct {
	MeBasePacket
	Result me.Results
}

func (omci *ActivateSoftwareResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v)",
		omci.MeBasePacket.String(), omci.Result, omci.Result)
}

// DecodeFromBytes decodes the given bytes of an Activate Softwre Response into this layer
func (omci *ActivateSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
		return me.NewProcessingError("managed entity does not support Activate Software Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Activate Software response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.Results(6) {
		msg := fmt.Sprintf("invalid results for Activate Software response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	return nil
}

func decodeActivateSoftwareResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &ActivateSoftwareResponse{}
	omci.MsgLayerType = LayerTypeActivateSoftwareResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Activate Software Response message
func (omci *ActivateSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.ActivateSoftware) {
		return me.NewProcessingError("managed entity does not support Activate Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Activate Software response")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	if omci.Result > me.Results(6) {
		msg := fmt.Sprintf("invalid results for Activate Software response: %v, must be 0..6",
			omci.Result)
		return errors.New(msg)
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type CommitSoftwareRequest struct {
	MeBasePacket
}

func (omci *CommitSoftwareRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Commit Software Request into this layer
func (omci *CommitSoftwareRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
		return me.NewProcessingError("managed entity does not support Commit Software Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Commit Software request")
	}
	return nil
}

func decodeCommitSoftwareRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &CommitSoftwareRequest{}
	omci.MsgLayerType = LayerTypeCommitSoftwareRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Commit Software Request message
func (omci *CommitSoftwareRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
		return me.NewProcessingError("managed entity does not support Commit Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Commit Software request")
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type CommitSoftwareResponse struct {
	MeBasePacket
}

func (omci *CommitSoftwareResponse) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Commit Softwar Response into this layer
func (omci *CommitSoftwareResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
		return me.NewProcessingError("managed entity does not support Commit Software Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Commit Software response")
	}
	return nil
}

func decodeCommitSoftwareResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &CommitSoftwareResponse{}
	omci.MsgLayerType = LayerTypeCommitSoftwareResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Commit Software Response message
func (omci *CommitSoftwareResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support End Software Download
	if !me.SupportsMsgType(meDefinition, me.CommitSoftware) {
		return me.NewProcessingError("managed entity does not support Commit Message-Type")
	}
	// Software Image Entity Class are always use the Software Image
	if omci.EntityClass != me.SoftwareImageClassID {
		return me.NewProcessingError("invalid Entity Class for Commit Software response")
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type SynchronizeTimeRequest struct {
	MeBasePacket
	Year   uint16
	Month  uint8
	Day    uint8
	Hour   uint8
	Minute uint8
	Second uint8
}

func (omci *SynchronizeTimeRequest) String() string {
	return fmt.Sprintf("%v, Date-Time: %d/%d/%d-%02d:%02d:%02d",
		omci.MeBasePacket.String(), omci.Year, omci.Month, omci.Day, omci.Hour, omci.Minute, omci.Second)
}

// DecodeFromBytes decodes the given bytes of a Synchronize Time Request into this layer
func (omci *SynchronizeTimeRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Synchronize Time
	if !me.SupportsMsgType(meDefinition, me.SynchronizeTime) {
		return me.NewProcessingError("managed entity does not support Synchronize Time Message-Type")
	}
	// Synchronize Time Entity Class are always ONU-G (256) and Entity Instance of 0
	if omci.EntityClass != me.OnuGClassID {
		return me.NewProcessingError("invalid Entity Class for Synchronize Time request")
	}
	if omci.EntityInstance != 0 {
		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time request")
	}
	omci.Year = binary.BigEndian.Uint16(data[4:6])
	omci.Month = data[6]
	omci.Day = data[7]
	omci.Hour = data[8]
	omci.Minute = data[9]
	omci.Second = data[10]
	return nil
}

func decodeSynchronizeTimeRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &SynchronizeTimeRequest{}
	omci.MsgLayerType = LayerTypeSynchronizeTimeRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Synchronize Time Request message
func (omci *SynchronizeTimeRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Synchronize Time
	if !me.SupportsMsgType(entity, me.SynchronizeTime) {
		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
	}
	bytes, err := b.AppendBytes(7)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], omci.Year)
	bytes[2] = omci.Month
	bytes[3] = omci.Day
	bytes[4] = omci.Hour
	bytes[5] = omci.Minute
	bytes[6] = omci.Second
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type SynchronizeTimeResponse struct {
	MeBasePacket
	Result         me.Results
	SuccessResults uint8 // Only if 'Result' is 0 -> success
}

func (omci *SynchronizeTimeResponse) String() string {
	return fmt.Sprintf("%v, Results: %d (%v), Success: %d",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.SuccessResults)
}

// DecodeFromBytes decodes the given bytes of a Synchronize Time Response into this layer
func (omci *SynchronizeTimeResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Synchronize Time
	if !me.SupportsMsgType(meDefinition, me.SynchronizeTime) {
		return me.NewProcessingError("managed entity does not support Synchronize Time Message-Type")
	}
	// Synchronize Time Entity Class are always ONU-G (256) and Entity Instance of 0
	if omci.EntityClass != me.OnuGClassID {
		return me.NewProcessingError("invalid Entity Class for Synchronize Time response")
	}
	if omci.EntityInstance != 0 {
		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time response")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > me.DeviceBusy {
		msg := fmt.Sprintf("invalid results code: %v, must be 0..8", omci.Result)
		return errors.New(msg)
	}
	omci.SuccessResults = data[5]
	return nil
}

func decodeSynchronizeTimeResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &SynchronizeTimeResponse{}
	omci.MsgLayerType = LayerTypeSynchronizeTimeResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Synchronize Time Response message
func (omci *SynchronizeTimeResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// Synchronize Time Entity Class are always ONU DATA (2) and Entity Instance of 0
	if omci.EntityClass != me.OnuGClassID {
		return me.NewProcessingError("invalid Entity Class for Synchronize Time response")
	}
	if omci.EntityInstance != 0 {
		return me.NewUnknownInstanceError("invalid Entity Instance for Synchronize Time response")
	}
	// ME needs to support Synchronize Time
	if !me.SupportsMsgType(entity, me.SynchronizeTime) {
		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
	}
	numBytes := 2
	if omci.Result != me.Success {
		numBytes = 1
	}
	bytes, err := b.AppendBytes(numBytes)
	if err != nil {
		return err
	}
	bytes[0] = uint8(omci.Result)
	if omci.Result == me.Success {
		bytes[1] = omci.SuccessResults
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type RebootRequest struct {
	MeBasePacket
	RebootCondition byte
}

func (omci *RebootRequest) String() string {
	return fmt.Sprintf("%v, Reboot Condition: %v",
		omci.MeBasePacket.String(), omci.RebootCondition)
}

// DecodeFromBytes decodes the given bytes of a Reboot Request into this layer
func (omci *RebootRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Reboot
	if !me.SupportsMsgType(meDefinition, me.Reboot) {
		return me.NewProcessingError("managed entity does not support Reboot Message-Type")
	}
	omci.RebootCondition = data[4]
	if omci.RebootCondition > 3 {
		msg := fmt.Sprintf("invalid reboot condition code: %v, must be 0..3", omci.RebootCondition)
		return errors.New(msg)
	}
	return nil
}

func decodeRebootRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &RebootRequest{}
	omci.MsgLayerType = LayerTypeRebootRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Reboot Request message
func (omci *RebootRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Reboot
	if !me.SupportsMsgType(entity, me.Reboot) {
		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	if omci.RebootCondition > 3 {
		return me.NewProcessingError(fmt.Sprintf("invalid reboot condition code: %v, must be 0..3",
			omci.RebootCondition))
	}
	bytes[0] = omci.RebootCondition
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type RebootResponse struct {
	MeBasePacket
	Result me.Results
}

// DecodeFromBytes decodes the given bytes of a Reboot Response into this layer
func (omci *RebootResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v)",
		omci.MeBasePacket.String(), omci.Result, omci.Result)
}

// DecodeFromBytes decodes the given bytes of a Reboot Response into this layer
func (omci *RebootResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Reboot
	if !me.SupportsMsgType(meDefinition, me.Reboot) {
		return me.NewProcessingError("managed entity does not support Reboot Message-Type")
	}
	if omci.Result > 6 {
		msg := fmt.Sprintf("invalid reboot results code: %v, must be 0..6", omci.Result)
		return errors.New(msg)
	}
	omci.Result = me.Results(data[4])
	return nil
}

func decodeRebootResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &RebootResponse{}
	omci.MsgLayerType = LayerTypeRebootResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Reboot Response message
func (omci *RebootResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	entity, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Reboot
	if !me.SupportsMsgType(entity, me.Reboot) {
		return me.NewProcessingError("managed entity does not support the Synchronize Time Message-Type")
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	if omci.Result > 6 {
		msg := fmt.Sprintf("invalid reboot results code: %v, must be 0..6", omci.Result)
		return errors.New(msg)
	}
	bytes[0] = byte(omci.Result)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type GetNextRequest struct {
	MeBasePacket
	AttributeMask  uint16
	SequenceNumber uint16
}

func (omci *GetNextRequest) String() string {
	return fmt.Sprintf("%v, Attribute Mask: %#x, Sequence Number: %v",
		omci.MeBasePacket.String(), omci.AttributeMask, omci.SequenceNumber)
}

// DecodeFromBytes decodes the given bytes of a Get Next Request into this layer
func (omci *GetNextRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support GetNext
	if !me.SupportsMsgType(meDefinition, me.GetNext) {
		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
	}
	// Note: G.988 specifies that an error code of (3) should result if more
	//       than one attribute is requested
	// TODO: Return error.  Have flag to optionally allow it to be encoded
	// TODO: Check that the attribute is a table attirbute.  Issue warning or return error
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
	omci.SequenceNumber = binary.BigEndian.Uint16(data[6:8])
	return nil
}

func decodeGetNextRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetNextRequest{}
	omci.MsgLayerType = LayerTypeGetNextRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Next Message Type Request
func (omci *GetNextRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support GetNext
	if !me.SupportsMsgType(meDefinition, me.GetNext) {
		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
	}
	bytes, err := b.AppendBytes(4)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
	binary.BigEndian.PutUint16(bytes[2:], omci.SequenceNumber)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type GetNextResponse struct {
	MeBasePacket
	Result        me.Results
	AttributeMask uint16
	Attributes    me.AttributeValueMap
}

// SerializeTo provides serialization of an Get Next Message Type Response
func (omci *GetNextResponse) String() string {
	return fmt.Sprintf("%v, Result: %v, Attribute Mask: %#x, Attributes: %v",
		omci.MeBasePacket.String(), omci.Result, omci.AttributeMask, omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of a Get Next Response into this layer
func (omci *GetNextResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(meDefinition, me.GetNext) {
		return me.NewProcessingError("managed entity does not support Get Next Message-Type")
	}
	omci.Result = me.Results(data[4])
	if omci.Result > 6 {
		msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
		return errors.New(msg)
	}
	omci.AttributeMask = binary.BigEndian.Uint16(data[5:7])

	// Attribute decode
	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[7:], p, byte(GetNextResponseType))
	if err != nil {
		return err
	}
	// Validate all attributes support read
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	if eidDef, eidDefOK := meDefinition.GetAttributeDefinitions()[0]; eidDefOK {
		omci.Attributes[eidDef.GetName()] = omci.EntityInstance
		return nil
	}
	panic("All Managed Entities have an EntityID attribute")
}

func decodeGetNextResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetNextResponse{}
	omci.MsgLayerType = LayerTypeGetNextResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Next Message Type Response
func (omci *GetNextResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.GetNext) {
		return me.NewProcessingError("managed entity does not support the Get Next Message-Type")
	}
	bytes, err := b.AppendBytes(3)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	if omci.Result > 6 {
		msg := fmt.Sprintf("invalid get next results code: %v, must be 0..6", omci.Result)
		return errors.New(msg)
	}
	binary.BigEndian.PutUint16(bytes[1:3], omci.AttributeMask)

	// Validate all attributes support read
	for attrName := range omci.Attributes {
		attr, err := me.GetAttributeDefinitionByName(meDefinition.GetAttributeDefinitions(), attrName)
		if err != nil {
			return err
		}
		if attr.Index != 0 && !me.SupportsAttributeAccess(*attr, me.Read) {
			msg := fmt.Sprintf("attribute '%v' does not support read access", attrName)
			return me.NewProcessingError(msg)
		}
	}
	// Attribute serialization
	switch omci.Result {
	default:
		break

	case me.Success:
		// TODO: Only Baseline supported at this time
		bytesAvailable := MaxBaselineLength - 11 - 8

		err, _ = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
			byte(GetNextResponseType), bytesAvailable, false)
		if err != nil {
			return err
		}
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type TestResultMsg struct {
	MeBasePacket
}

func (omci *TestResultMsg) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Test Result Notification into this layer
func (omci *TestResultMsg) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // return nil
}

func decodeTestResult(data []byte, p gopacket.PacketBuilder) error {
	omci := &TestResultMsg{}
	omci.MsgLayerType = LayerTypeTestResult
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Test Result notification message
func (omci *TestResultMsg) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me) // omci.cachedME.SerializeTo(mask, b)
}

/////////////////////////////////////////////////////////////////////////////
//
type GetCurrentDataRequest struct {
	MeBasePacket
	AttributeMask uint16
}

func (omci *GetCurrentDataRequest) String() string {
	return fmt.Sprintf("%v, Attribute Mask: %#x",
		omci.MeBasePacket.String(), omci.AttributeMask)
}

// DecodeFromBytes decodes the given bytes of a Get Current Data Request into this layer
func (omci *GetCurrentDataRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support GetNext
	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
	}
	// Note: G.988 specifies that an error code of (3) should result if more
	//       than one attribute is requested
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])
	return nil
}

func decodeGetCurrentDataRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetCurrentDataRequest{}
	omci.MsgLayerType = LayerTypeGetCurrentDataRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Current Data Request message
func (omci *GetCurrentDataRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support GetNext
	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes, omci.AttributeMask)
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type GetCurrentDataResponse struct {
	MeBasePacket
	Result        me.Results
	AttributeMask uint16
	Attributes    me.AttributeValueMap
}

func (omci *GetCurrentDataResponse) String() string {
	return fmt.Sprintf("%v, Result: %d (%v), Attribute Mask: %#x, Attributes: %v",
		omci.MeBasePacket.String(), omci.Result, omci.Result, omci.AttributeMask, omci.Attributes)
}

// DecodeFromBytes decodes the given bytes of a Get Current Data Respnse into this layer
func (omci *GetCurrentDataResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Set
	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
		return me.NewProcessingError("managed entity does not support Get Current Data Message-Type")
	}
	omci.AttributeMask = binary.BigEndian.Uint16(data[4:6])

	// Attribute decode
	omci.Attributes, err = meDefinition.DecodeAttributes(omci.AttributeMask, data[6:], p, byte(GetCurrentDataResponseType))
	if err != nil {
		return err
	}
	return nil
}

func decodeGetCurrentDataResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &GetCurrentDataResponse{}
	omci.MsgLayerType = LayerTypeGetCurrentDataResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Get Current Data Message Type Response
func (omci *GetCurrentDataResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	meDefinition, omciErr := me.LoadManagedEntityDefinition(omci.EntityClass,
		me.ParamData{EntityID: omci.EntityInstance})
	if omciErr.StatusCode() != me.Success {
		return omciErr.GetError()
	}
	// ME needs to support Get
	if !me.SupportsMsgType(meDefinition, me.GetCurrentData) {
		return me.NewProcessingError("managed entity does not support the Get Current Data Message-Type")
	}
	bytes, err := b.AppendBytes(2)
	if err != nil {
		return err
	}
	binary.BigEndian.PutUint16(bytes[0:2], omci.AttributeMask)

	// Attribute serialization
	// TODO: Only Baseline supported at this time
	bytesAvailable := MaxBaselineLength - 9 - 8
	var failedMask uint16

	err, failedMask = meDefinition.SerializeAttributes(omci.Attributes, omci.AttributeMask, b,
		byte(GetCurrentDataResponseType), bytesAvailable, opts.FixLengths)

	if failedMask != 0 {
		// TODO: See GetResponse serialization above for the steps here
		return me.NewMessageTruncatedError("getCurrentData attribute truncation not yet supported")
	}
	if err != nil {
		return err
	}
	return nil
}

/////////////////////////////////////////////////////////////////////////////
//
type SetTableRequest struct {
	MeBasePacket
	// TODO: Fix me when extended messages supported)
}

func (omci *SetTableRequest) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Set Table Request into this layer
func (omci *SetTableRequest) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
}

func decodeSetTableRequest(data []byte, p gopacket.PacketBuilder) error {
	omci := &SetTableRequest{}
	omci.MsgLayerType = LayerTypeSetTableRequest
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Set Table Message Type Request
func (omci *SetTableRequest) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	return errors.New("need to implement") /// TODO: Fix me when extended messages supported)
}

/////////////////////////////////////////////////////////////////////////////
//
type SetTableResponse struct {
	MeBasePacket
	// TODO: Fix me when extended messages supported)
}

func (omci *SetTableResponse) String() string {
	return fmt.Sprintf("%v", omci.MeBasePacket.String())
}

// DecodeFromBytes decodes the given bytes of a Set Table Response into this layer
func (omci *SetTableResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	// Common ClassID/EntityID decode in msgBase
	err := omci.MeBasePacket.DecodeFromBytes(data, p)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
}

func decodeSetTableResponse(data []byte, p gopacket.PacketBuilder) error {
	omci := &SetTableResponse{}
	omci.MsgLayerType = LayerTypeSetTableResponse
	return decodingLayerDecoder(omci, data, p)
}

// SerializeTo provides serialization of an Set Table Message Type Response
func (omci *SetTableResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	return errors.New("need to implement") // TODO: Fix me when extended messages supported)
}

/////////////////////////////////////////////////////////////////////////////
//
type UnsupportedMessageTypeResponse struct {
	MeBasePacket
	Result me.Results
}

// DecodeFromBytes decodes the given bytes of an Unsupported Message Type Response into this layer
func (omci *UnsupportedMessageTypeResponse) DecodeFromBytes(data []byte, p gopacket.PacketBuilder) error {
	return errors.New("you should never really decode this")
}

// SerializeTo provides serialization of an Unsupported Message Type Response
func (omci *UnsupportedMessageTypeResponse) SerializeTo(b gopacket.SerializeBuffer, opts gopacket.SerializeOptions) error {
	// Basic (common) OMCI Header is 8 octets, 10
	err := omci.MeBasePacket.SerializeTo(b)
	if err != nil {
		return err
	}
	bytes, err := b.AppendBytes(1)
	if err != nil {
		return err
	}
	bytes[0] = byte(omci.Result)
	return nil
}
