/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */
package generated

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

type ManagedEntityDefinition struct {
	Name         string
	ClassID      ClassID
	MessageTypes mapset.Set // Mandatory
	// TODO: Support Optional Message types
	AllowedAttributeMask uint16
	AttributeDefinitions AttributeDefinitionMap
}

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

func (bme *ManagedEntityDefinition) GetName() string {
	return bme.Name
}
func (bme *ManagedEntityDefinition) GetClassID() ClassID {
	return bme.ClassID
}
func (bme *ManagedEntityDefinition) GetMessageTypes() mapset.Set {
	return bme.MessageTypes
}
func (bme *ManagedEntityDefinition) GetAllowedAttributeMask() uint16 {
	return bme.AllowedAttributeMask
}
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&(1<<(16-uint(index))) != 0 {
			value, err := attrDef.Decode(data, p, msgType)
			if err != nil {
				return nil, err
			}
			if attrDef.IsTableAttribute() {
				switch msgType {
				default:
					return nil, errors.New(fmt.Sprintf("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) error {
	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")
	}
	// 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)

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

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