/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation

 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at

 * http://www.apache.org/licenses/LICENSE-2.0

 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import (
	"errors"
	"fmt"
	"github.com/deckarep/golang-set"
	"github.com/google/gopacket"
	"math/bits"
)

// ManagedEntityDefinition defines a Manage Entity
type ManagedEntityDefinition struct {
	Name         string
	ClassID      ClassID
	MessageTypes mapset.Set // Mandatory
	// TODO: Support Optional Message types  (this has just been fixed in the code generator)
	AllowedAttributeMask uint16
	AttributeDefinitions AttributeDefinitionMap
	Access               ClassAccess
	Support              ClassSupport
}

func (bme *ManagedEntityDefinition) String() string {
	return fmt.Sprintf("Definition: %s: CID: %v, Attributes: %v",
		bme.Name, bme.ClassID, bme.AttributeDefinitions)
}

// GetName retrieves the name of a managed entity from a ME Definition
func (bme ManagedEntityDefinition) GetName() string {
	return bme.Name
}

// GetClassID retrieves the 16-bit class ID of a managed entity from a ME Definition
func (bme ManagedEntityDefinition) GetClassID() ClassID {
	return bme.ClassID
}

// SetClassID assigns the 16-bit class ID of a managed entity from a ME Definition
func (bme *ManagedEntityDefinition) SetClassID(classID ClassID) {
	bme.ClassID = classID
}

// GetMessageTypes retrieves the OMCI Message Types supporte3d by a managed entity from a ME Definition
func (bme ManagedEntityDefinition) GetMessageTypes() mapset.Set {
	return bme.MessageTypes
}

// GetAllowedAttributeMask retrieves the allowed/valid 16-bit attribute mask of a managed entity
// from a ME Definition
func (bme ManagedEntityDefinition) GetAllowedAttributeMask() uint16 {
	return bme.AllowedAttributeMask
}

// GetAttributeDefinitions retrieves the attribute definitions of a managed entity from a ME Definition
func (bme ManagedEntityDefinition) GetAttributeDefinitions() AttributeDefinitionMap {
	return bme.AttributeDefinitions
}

func (bme ManagedEntityDefinition) DecodeAttributes(mask uint16, data []byte, p gopacket.PacketBuilder, msgType byte) (AttributeValueMap, error) {
	if (mask | bme.GetAllowedAttributeMask()) != bme.GetAllowedAttributeMask() {
		// TODO: Provide custom error code so a response 'result' can properly be coded
		return nil, errors.New("unsupported attribute mask")
	}
	keyList := GetAttributeDefinitionMapKeys(bme.AttributeDefinitions)

	attrMap := make(AttributeValueMap, bits.OnesCount16(mask))
	for _, index := range keyList {
		if index == 0 {
			continue // Skip Entity ID
		}
		attrDef := bme.AttributeDefinitions[index]
		name := attrDef.GetName()

		if mask&attrDef.Mask != 0 {
			value, err := attrDef.Decode(data, p, msgType)
			if err != nil {
				return nil, err
			}
			if attrDef.IsTableAttribute() {
				switch msgType {
				default:
					return nil, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)

				case byte(Get) | AK: // Get Response
					attrMap[name] = value
					data = data[4:]

				case byte(GetNext) | AK: // Get Next Response
					// Value is a partial octet buffer we need to collect and at
					// the end (last segment) pull it up into more appropriate table
					// rows
					valueBuffer, ok := value.([]byte)
					if !ok {
						panic("unexpected type already returned as get-next-response attribute data")
					}
					if existing, found := attrMap[name]; found {
						prev, ok := existing.([]byte)
						if !ok {
							panic("unexpected type already in attribute value map")
						}
						attrMap[name] = append(prev, valueBuffer...)
					} else {
						attrMap[name] = valueBuffer
					}
					if size := attrDef.GetSize(); size != 0 && size > len(valueBuffer) {
						panic("unexpected size difference")
					}
					data = data[len(valueBuffer):]

				case byte(Set) | AR: // Set Request
					fmt.Println("TODO")

				case byte(SetTable) | AR: // Set Table Request
					// TODO: Only baseline supported at this time
					return nil, errors.New("attribute encode for set-table-request not yet supported")
				}
			} else {
				attrMap[name] = value
				data = data[attrDef.GetSize():]
			}
		}
	}
	return attrMap, nil
}

func (bme ManagedEntityDefinition) SerializeAttributes(attr AttributeValueMap, mask uint16,
	b gopacket.SerializeBuffer, msgType byte, bytesAvailable int, packData bool) (error, uint16) {

	if (mask | bme.GetAllowedAttributeMask()) != bme.GetAllowedAttributeMask() {
		// TODO: Provide custom error code so a response 'result' can properly be coded
		return errors.New("unsupported attribute mask"), 0
	}
	// TODO: Need to limit number of bytes appended to not exceed packet size
	// Is there space/metadata info in 'b' parameter to allow this?
	keyList := GetAttributeDefinitionMapKeys(bme.AttributeDefinitions)
	var failedMask uint16

	for _, index := range keyList {
		if index == 0 {
			continue // Skip Entity ID
		}
		attrDef := bme.AttributeDefinitions[index]

		if mask&attrDef.Mask != 0 {
			value, ok := attr[attrDef.GetName()]
			if !ok {
				msg := fmt.Sprintf("attribute not found: '%v'", attrDef.GetName())
				return errors.New(msg), failedMask
			}
			size, err := attrDef.SerializeTo(value, b, msgType, bytesAvailable)
			if err != nil {
				failedMask |= attrDef.Mask
				if packData {
					continue
				}
				return err, failedMask
			}
			bytesAvailable -= size
		}
	}
	return nil, failedMask
}
