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

// 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
}
