/*
 * 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 (
	"encoding/base64"
	"encoding/binary"
	"errors"
	"fmt"
	"reflect"
	"sort"
	"strings"

	mapset "github.com/deckarep/golang-set"
	"github.com/google/gopacket"
)

// Attribute types
type AttributeType uint8

const (
	UnknownAttributeType         AttributeType = iota // Not known
	OctetsAttributeType                               // Series of zero or more octets
	StringAttributeType                               // Readable String
	UnsignedIntegerAttributeType                      // Integer (0..max)
	TableAttributeType                                // Table (of Octets)
	SignedIntegerAttributeType                        // Signed integer, often expressed as 2's complement
	PointerAttributeType                              // Managed Entity ID or pointer to a Managed instance
	BitFieldAttributeType                             // Bitfield
	EnumerationAttributeType                          // Fixed number of values (Unsigned Integers)
	CounterAttributeType                              // Incrementing counter
)

// AttributeDefinitionMap is a map of attribute definitions with the attribute index (0..16)
// as the key
type AttributeDefinitionMap map[uint]AttributeDefinition

// AttributeDefinition defines a single specific Managed Entity's attributes
type AttributeDefinition struct {
	Name          string
	AttributeType AttributeType
	Index         uint
	Mask          uint16
	DefValue      interface{}
	Size          int        // Size of attribute in bytes. 0 indicates variable/unknown
	Access        mapset.Set // AttributeAccess...
	Constraint    func(interface{}) *ParamError
	Avc           bool // If true, an AVC notification can occur for the attribute
	Tca           bool // If true, a threshold crossing alert alarm notification can occur for the attribute
	Optional      bool // If true, attribute is option, else mandatory
	Deprecated    bool // If true, attribute is deprecated
}

// TableRows is used by the SetTable request/response
type TableRows struct {
	NumRows int    // Number of rows of 'AttributeDefinition.Size' length
	Rows    []byte // 0..NumRows rows of attribute data of size 'AttributeDefinition.Size'
}

func (attr *AttributeDefinition) String() string {
	return fmt.Sprintf("AttributeDefinition: %v (%v/%v): Size: %v, Default: %v, Access: %v",
		attr.GetName(), attr.AttributeType, attr.GetIndex(), attr.GetSize(), attr.GetDefault(), attr.GetAccess())
}

// GetName returns the attribute's name
func (attr AttributeDefinition) GetName() string { return attr.Name }

// GetIndex returns the attribute index )0..16)
func (attr AttributeDefinition) GetIndex() uint { return attr.Index }

// GetDefault provides the default value for an attribute if not specified
// during its creation
func (attr AttributeDefinition) GetDefault() interface{} { return attr.DefValue }

// GetSize returns the size of the attribute. For table attributes, the size is
// the size of a single table.
func (attr AttributeDefinition) GetSize() int { return attr.Size }

// GetAccess provides the access information (Read, Write, ...)
func (attr AttributeDefinition) GetAccess() mapset.Set { return attr.Access }

// GetConstraints returns a function that can be called for the attribute
// that will validate the value. An appropriate error is returned if the
// constraint fails, otherwise nil is returned to indicate that the value
// is valid.
func (attr AttributeDefinition) GetConstraints() func(interface{}) *ParamError {
	return attr.Constraint
}

// IsTableAttribute returns true if the attribute is a table
func (attr AttributeDefinition) IsTableAttribute() bool {
	return attr.AttributeType == TableAttributeType
}

// IsCounter returns true if the attribute is a counter (usually expressed as an
// unsigned integer)
func (attr AttributeDefinition) IsCounter() bool {
	return attr.AttributeType == CounterAttributeType
}

// IsBitField returns true if the attribute is a bitfield
func (attr AttributeDefinition) IsBitField() bool {
	return attr.AttributeType == BitFieldAttributeType
}

// IsString returns true if the attribute is a string. Strings are typically encoded
// into fixed length files and padded with 0's
func (attr AttributeDefinition) IsString() bool {
	return attr.AttributeType == StringAttributeType
}

// Decode takes a slice of bytes and converts them into a value appropriate for
// the attribute, or returns an error on failure
func (attr *AttributeDefinition) Decode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
	if attr.IsTableAttribute() {
		value, err := attr.tableAttributeDecode(data, df, msgType)
		if err != nil {
			return nil, err
		}
		if attr.GetConstraints() != nil {
			if omciErr := attr.GetConstraints()(value); omciErr != nil {
				return nil, omciErr.GetError()
			}
		}
		return value, nil
	}
	size := attr.GetSize()

	if len(data) < size {
		df.SetTruncated()
		return nil, NewMessageTruncatedError("packet too small for field")
	}
	switch attr.AttributeType {
	case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
		value := make([]byte, size)
		copy(value, data[:size])
		if attr.GetConstraints() != nil {
			if omciErr := attr.GetConstraints()(value); omciErr != nil {
				return nil, omciErr.GetError()
			}
		}
		return value, nil

	default:
		switch attr.GetSize() {
		default:
			value := make([]byte, size)
			copy(value, data[:size])
			if attr.GetConstraints() != nil {
				if omciErr := attr.GetConstraints()(value); omciErr != nil {
					return nil, omciErr.GetError()
				}
			}
			return value, nil
		case 1:
			value := data[0]
			if attr.GetConstraints() != nil {
				if omciErr := attr.GetConstraints()(value); omciErr != nil {
					return nil, omciErr.GetError()
				}
			}
			return value, nil
		case 2:
			value := binary.BigEndian.Uint16(data[0:2])
			if attr.GetConstraints() != nil {
				if omciErr := attr.GetConstraints()(value); omciErr != nil {
					return nil, omciErr.GetError()
				}
			}
			return value, nil
		case 4:
			value := binary.BigEndian.Uint32(data[0:4])
			if attr.GetConstraints() != nil {
				if omciErr := attr.GetConstraints()(value); omciErr != nil {
					return nil, omciErr.GetError()
				}
			}
			return value, nil
		case 8:
			value := binary.BigEndian.Uint64(data[0:8])
			if attr.GetConstraints() != nil {
				omciErr := attr.GetConstraints()(value)
				if omciErr != nil {
					return nil, omciErr.GetError()
				}
			}
			return value, nil
		}
	}
}

// IOctetStream interface defines a way to convert a custom type to/from an octet
// stream.
type IOctetStream interface {
	ToOctetString() ([]byte, error)
	FromOctetString([]byte) (interface{}, error)
}

// InterfaceToOctets converts an attribute value to a string of octets
func InterfaceToOctets(input interface{}) ([]byte, error) {
	switch values := input.(type) {
	case []byte:
		return values, nil

	case []uint16:
		stream := make([]byte, 2*len(values))
		for index, value := range values {
			binary.BigEndian.PutUint16(stream[index*2:], value)
		}
		return stream, nil

	case []uint32:
		stream := make([]byte, 4*len(values))
		for index, value := range values {
			binary.BigEndian.PutUint32(stream[index*4:], value)
		}
		return stream, nil

	case []uint64:
		stream := make([]byte, 8*len(values))
		for index, value := range values {
			binary.BigEndian.PutUint64(stream[index*8:], value)
		}
		return stream, nil

	case IOctetStream:
		return values.ToOctetString()

	default:
		var typeName string
		if t := reflect.TypeOf(input); t.Kind() == reflect.Ptr {
			typeName = "*" + t.Elem().Name()
		} else {
			typeName = t.Name()
		}
		return nil, fmt.Errorf("unable to convert input to octet string: %v", typeName)
	}
}

// SerializeTo takes an attribute value and converts it to a slice of bytes ready
// for transmission
func (attr *AttributeDefinition) SerializeTo(value interface{}, b gopacket.SerializeBuffer,
	msgType byte, bytesAvailable int) (int, error) {
	if attr.IsTableAttribute() {
		return attr.tableAttributeSerializeTo(value, b, msgType, bytesAvailable)
	}
	if value == nil {
		return 0, fmt.Errorf("attribute: %v is nil", attr.Name)
	}
	size := attr.GetSize()
	if bytesAvailable < size {
		return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
	}
	bytes, err := b.AppendBytes(size)
	if err != nil {
		return 0, err
	}
	switch attr.AttributeType {
	case StringAttributeType, OctetsAttributeType, UnknownAttributeType:
		byteStream, err := InterfaceToOctets(value)
		if err != nil {
			return 0, err
		}
		copy(bytes, byteStream)

	default:
		switch size {
		default:
			byteStream, err := InterfaceToOctets(value)
			if err != nil {
				return 0, err
			}
			copy(bytes, byteStream)
		case 1:
			switch value.(type) {
			case int:
				bytes[0] = byte(value.(int))
			default:
				bytes[0] = value.(byte)
			}
		case 2:
			switch value.(type) {
			case int:
				binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
			default:
				binary.BigEndian.PutUint16(bytes, value.(uint16))
			}
		case 4:
			switch value.(type) {
			case int:
				binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
			default:
				binary.BigEndian.PutUint32(bytes, value.(uint32))
			}
		case 8:
			switch value.(type) {
			case int:
				binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
			default:
				binary.BigEndian.PutUint64(bytes, value.(uint64))
			}
		}
	}
	return size, nil
}

// BufferToTableAttributes takes the reconstructed octet buffer transmitted for
// a table attribute (over many GetNextResponses) and converts it into the desired
// format for each table row
func (attr *AttributeDefinition) BufferToTableAttributes(data []byte) (interface{}, error) {
	// Source is network byte order octets. Convert to proper array of slices
	rowSize := attr.GetSize()
	dataSize := len(data)
	index := 0

	switch rowSize {
	default:
		value := make([][]byte, dataSize/rowSize)
		for offset := 0; offset < dataSize; offset += rowSize {
			value[index] = make([]byte, rowSize)
			copy(value[index], data[offset:])
			index++
		}
		return value, nil
	case 1:
		value := make([]byte, dataSize)
		copy(value, data)
		return value, nil
	case 2:
		value := make([]uint16, dataSize/2)
		for offset := 0; offset < dataSize; offset += rowSize {
			value[offset] = binary.BigEndian.Uint16(data[offset:])
			index++
		}
		return value, nil
	case 4:
		value := make([]uint32, dataSize/4)
		for offset := 0; offset < dataSize; offset += rowSize {
			value[offset] = binary.BigEndian.Uint32(data[offset:])
			index++
		}
		return value, nil
	case 8:
		value := make([]uint64, dataSize/8)
		for offset := 0; offset < dataSize; offset += rowSize {
			value[offset] = binary.BigEndian.Uint64(data[offset:])
			index++
		}
		return value, nil
	}
}

func (attr *AttributeDefinition) tableAttributeDecode(data []byte, df gopacket.DecodeFeedback, msgType byte) (interface{}, error) {
	// Serialization of a table depends on the type of message. A
	// Review of ITU-T G.988 shows that access on tables are
	// either Read and/or Write, never Set-by-Create
	switch msgType {
	default:
		return nil, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)

	case byte(Get) | AK: // Get Response
		// Size
		value := binary.BigEndian.Uint32(data[0:4])
		return value, nil

	case byte(Set) | AR: // Set Request
		fallthrough

	case byte(GetNext) | AK: // Get Next Response
		// Block of data (octets) that need to be reassembled before conversion
		// to table/row-data.  If table attribute is not explicitly given a value
		// we have to assume the entire data buffer is the value. The receiver of
		// this frame will need to trim off any addtional information at the end
		// of the last frame sequence since they (and the ONU) are the only ones
		// who know how long the data really is.
		size := attr.GetSize()
		if size != 0 && len(data) < attr.GetSize() {
			df.SetTruncated()
			return nil, NewMessageTruncatedError("packet too small for field")
		}
		if size == 0 {
			return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
		}
		return data, nil

	case byte(SetTable) | AR: // Set Table Request
		// SetTableRequestType will be composed of zero or more row of a fixed size (based on ME)
		// and will be saved to a TableRow struct for the consumer's use
		size := attr.GetSize()
		if size == 0 {
			return nil, NewProcessingError("table attributes with no size are not supported: %v", attr.Name)
		}
		if len(data)%size != 0 {
			df.SetTruncated()
			return nil, NewMessageTruncatedError("packet does not contain an integral number of rows")
		}
		if len(data) == 0 {
			return TableRows{}, nil
		}
		rows := TableRows{
			NumRows: len(data) / size,
			Rows:    make([]byte, len(data)),
		}
		copy(rows.Rows, data)
		return rows, nil
	}
}

func (attr *AttributeDefinition) tableAttributeSerializeTo(value interface{}, b gopacket.SerializeBuffer, msgType byte,
	bytesAvailable int) (int, error) {
	// Serialization of a table depends on the type of message. A
	// Review of ITU-T G.988 shows that access on tables are
	// either Read and/or Write, never Set-by-Create
	switch msgType {
	default:
		return 0, fmt.Errorf("unsupported Message Type '%v' for table serialization", msgType)

	case byte(Get) | AK: // Get Response
		// Size
		if bytesAvailable < 4 {
			return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
		}
		if dwordSize, ok := value.(uint32); ok {
			bytes, err := b.AppendBytes(4)
			if err != nil {
				return 0, err
			}
			binary.BigEndian.PutUint32(bytes, dwordSize)
			return 4, nil
		}
		return 0, errors.New("unexpected type for table serialization")

	case byte(GetNext) | AK: // Get Next Response
		// Values are already in network by order form
		if data, ok := value.([]byte); ok {
			if bytesAvailable < len(data) {
				return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
			}
			bytes, err := b.AppendBytes(len(data))
			if err != nil {
				return 0, err
			}
			copy(bytes, data)
			return len(data), nil
		}
		return 0, errors.New("unexpected type for table serialization")

	case byte(Set) | AR: // Set Request
		// TODO: For complex table types (such as extended vlan tagging config) create an
		//       interface definition. Provide a switch type to look for that as well as for
		//       value being a byte slice...  For now, just byte slice provided
		break

	case byte(SetTable) | AR: // Set Table Request
		if rows, ok := value.(TableRows); ok {
			size := attr.GetSize()
			if size != 0 && len(rows.Rows)%size != 0 {
				return 0, NewMessageTruncatedError("packet does not contain an integral number of rows")
			}
			if bytesAvailable < len(rows.Rows) {
				return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
			}
			bytes, err := b.AppendBytes(len(rows.Rows))
			if err != nil {
				return 0, err
			}
			copy(bytes, rows.Rows)
			return len(rows.Rows), nil
		}
		return 0, errors.New("unexpected type for table serialization")
	}
	size := attr.GetSize()
	if bytesAvailable < size {
		return 0, NewMessageTruncatedError(fmt.Sprintf("not enough space for attribute: %v", attr.Name))
	}
	bytes, err := b.AppendBytes(size)
	if err != nil {
		return 0, err
	}
	switch attr.GetSize() {
	default:
		copy(bytes, value.([]byte))
	case 1:
		switch value.(type) {
		case int:
			bytes[0] = byte(value.(int))
		default:
			bytes[0] = value.(byte)
		}
	case 2:
		switch value.(type) {
		case int:
			binary.BigEndian.PutUint16(bytes, uint16(value.(int)))
		default:
			binary.BigEndian.PutUint16(bytes, value.(uint16))
		}
	case 4:
		switch value.(type) {
		case int:
			binary.BigEndian.PutUint32(bytes, uint32(value.(int)))
		default:
			binary.BigEndian.PutUint32(bytes, value.(uint32))
		}
	case 8:
		switch value.(type) {
		case int:
			binary.BigEndian.PutUint64(bytes, uint64(value.(int)))
		default:
			binary.BigEndian.PutUint64(bytes, value.(uint64))
		}
	}
	return size, nil
}

// GetAttributeDefinitionByName searches the attribute definition map for the
// attribute with the specified name (case insensitive)
func GetAttributeDefinitionByName(attrMap AttributeDefinitionMap, name string) (*AttributeDefinition, error) {
	nameLower := strings.ToLower(name)
	for _, attrVal := range attrMap {
		if nameLower == strings.ToLower(attrVal.GetName()) {
			return &attrVal, nil
		}
	}
	return nil, errors.New(fmt.Sprintf("attribute '%s' not found", name))
}

// GetAttributeDefinitionMapKeys is a convenience functions since we may need to
// iterate a map in key index order. Maps in Go since v1.0 the iteration order
// of maps have been randomized.
func GetAttributeDefinitionMapKeys(attrMap AttributeDefinitionMap) []uint {
	var keys []uint
	for k := range attrMap {
		keys = append(keys, k)
	}
	sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
	return keys
}

// GetAttributeBitmap returns the attribute bitmask for a single attribute
func GetAttributeBitmap(attrMap AttributeDefinitionMap, name string) (uint16, error) {
	attrDef, err := GetAttributeDefinitionByName(attrMap, name)
	if err != nil {
		return 0, err
	}
	index := attrDef.GetIndex()
	if index == 0 {
		return 0, errors.New("managed entity ID should not be used in an attribute bitmask")
	}
	return uint16(1 << (16 - index)), nil
}

// GetAttributesBitmap is a convenience functions to scan a list of attributes
// and return the bitmask that represents them
func GetAttributesBitmap(attrMap AttributeDefinitionMap, attributes mapset.Set) (uint16, error) {
	var mask uint16
	for _, def := range attrMap {
		if attributes.Contains(def.Name) {
			mask |= def.Mask
			attributes.Remove(def.Name)
		}
	}
	if attributes.Cardinality() > 0 {
		return 0, fmt.Errorf("unsupported attributes: %v", attributes)
	}
	return mask, nil
}

// GetAttributesValueMap returns the attribute value map with uninitialized values based
// on the attribute bitmask
func GetAttributesValueMap(attrDefs AttributeDefinitionMap, mask uint16, access mapset.Set) (AttributeValueMap, OmciErrors) {
	attrMap := make(AttributeValueMap, 0)
	for index, def := range attrDefs {
		if index == 0 {
			continue
		}
		checkMask := def.Mask
		accessOk := access == nil || def.GetAccess().Intersect(access).Cardinality() > 0

		if (mask&checkMask) != 0 && accessOk {
			attrMap[def.GetName()] = nil
			mask &= ^checkMask
		}
	}
	if mask != 0 {
		// Return map, but signaled failed attributes
		return attrMap, NewParameterError(mask)
	}
	return attrMap, NewOmciSuccess()
}

///////////////////////////////////////////////////////////////////////
// Packet definitions for attributes of various types/sizes
func toOctets(str string) []byte {
	data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		panic(fmt.Sprintf("Invalid Base-64 string: '%v'", str))
	}
	return data
}

///////////////////////////////////////////////////////////////////////
// Packet definitions for attributes of various types/sizes

// ByteField returns an AttributeDefinition for an attribute that is encoded as a single
// octet (8-bits).
func ByteField(name string, attrType AttributeType, mask uint16, defVal uint8, access mapset.Set, avc bool,
	optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      defVal,
		Size:          1,
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// Uint16Field returns an AttributeDefinition for an attribute that is encoded as two
// octet (16-bits).
func Uint16Field(name string, attrType AttributeType, mask uint16, defVal uint16, access mapset.Set, avc bool,
	optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      defVal,
		Size:          2,
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// Uint32Field returns an AttributeDefinition for an attribute that is encoded as four
// octet (32-bits).
func Uint32Field(name string, attrType AttributeType, mask uint16, defVal uint32, access mapset.Set, avc bool,
	optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      defVal,
		Size:          4,
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// Uint64Field returns an AttributeDefinition for an attribute that is encoded as eight
// octet (64-bits).
func Uint64Field(name string, attrType AttributeType, mask uint16, defVal uint64, access mapset.Set, avc bool,
	optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      defVal,
		Size:          8,
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// MultiByteField returns an AttributeDefinition for an attribute that is encoded as multiple
// octets that do not map into fields with a length that is 1, 2, 4, or 8 octets.
func MultiByteField(name string, attrType AttributeType, mask uint16, size uint, defVal []byte, access mapset.Set, avc bool,
	optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      defVal,
		Size:          int(size),
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// Notes on various OMCI ME Table attribute fields.  This comment will eventually be
// removed once a good table solution is implemented.  These are not all the MEs with
// table attributes, but probably ones I care about to support initially.
//
//   ME                     Notes
//  --------------------------------------------------------------------------------------------
//	Port-mapping package -> Combined Port table -> N * 25 sized rows (port (1) + ME(2) * 12)
//  ONU Remote Debug     -> Reply table (N bytes)
//  ONU3-G               -> Status snapshot recordtable M x N bytes
//  MCAST Gem interworkTP-> IPv4 multicast adress table (12*n) (two 2 byte fields, two 4 byte fields)
//                          IPv6 multicast adress table (24*n) (various sub-fields)
//  L2 mcast gem TP      -> MCAST MAC addr filtering table (11 * n) (various sub-fields)
//  MAC Bridge Port Filt -> MAC Filter table (8 * n) (3 fields, some are bits)      *** BITS ***
//  MAC Bridge Port data -> Bridge Table (8*M) (vaius fields, some are bits)        *** BITS ***
//  VLAN tagging filter  -> Rx Vlan tag op table (16 * n) Lots of bit fields        *** BITS ***
//  MCAST operations profile
//  MCAST Subscriber config info
//  MCAST subscriber monitor
//  OMCI                -> Two tables (N bytes and 2*N bytes)
//  General pupose buffer   -> N bytes
//  Enhanced security control (17 * N bytes), (16 * P Bytes) , (16 * Q bytes), and more...
//
// An early example of info to track

// TableInfo is an early prototype of how to better model some tables that are
// difficult to code.
//
// The Value member may be one of the following:
//   nil    : Empty, no default, ...
//   value  : A specific value that equates to one row, ie) 6  or toOctets("base64")
//   array  : One or more rows of values.  [2]uint16{2, 3}
type TableInfo struct {
	Value interface{} // See comment above
	Size  int         // Table Row Size
}

func (t *TableInfo) String() string {
	return fmt.Sprintf("TableInfo: Size: %d, Value(s): %v", t.Size, t.Value)
}

// TableField is used to define an attribute that is a table
func TableField(name string, attrType AttributeType, mask uint16, tableInfo TableInfo, access mapset.Set,
	avc bool, optional bool, deprecated bool, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: attrType,
		Mask:          mask,
		Index:         index,
		DefValue:      tableInfo.Value,
		Size:          tableInfo.Size, //Number of elements
		Access:        access,
		Avc:           avc,
		Optional:      optional,
		Deprecated:    deprecated,
	}
}

// UnknownField is currently not used and may be deprecated. Its original intent
// was to be a placeholder during table attribute development
func UnknownField(name string, mask uint16, size int, index uint) AttributeDefinition {
	return AttributeDefinition{
		Name:          name,
		AttributeType: UnknownAttributeType, // Stored as octet string
		Mask:          mask,
		Index:         index,
		DefValue:      nil,
		Size:          size,
		Access:        mapset.NewSet(Read, Write),
		Avc:           false,
		Optional:      false,
		Deprecated:    false,
	}
}

// AttributeValueMap maps an attribute (by name) to its value
type AttributeValueMap map[string]interface{}

// MergeInDefaultValues will examine the Manage Entity defaults (for non-SetByCreate attributes). This
// function is called on a MIB Create request but is provide for external use in case it is needed
// before the MIB entry is created
func MergeInDefaultValues(classID ClassID, attributes AttributeValueMap) OmciErrors {
	// Get default values for non-SetByCreate attributes
	attrDefs, err := GetAttributesDefinitions(classID)
	if err.StatusCode() != Success {
		return err
	} else if attributes == nil {
		return NewProcessingError("Invalid (nil) Attribute Value Map referenced")
	}
	nilAllowed := mapset.NewSet(StringAttributeType, OctetsAttributeType, TableAttributeType)
	for index, attrDef := range attrDefs {
		if !attrDef.Access.Contains(SetByCreate) && index != 0 &&
			(attrDef.DefValue != nil || nilAllowed.Contains(attrDef.AttributeType)) {
			name := attrDef.GetName()
			if existing, found := attributes[name]; !found || existing == nil {
				attributes[name] = attrDef.DefValue
			}
		}
	}
	return err
}

// AttributeValueMapBufferSize will determine how much space is needed to encode all
// of the attributes
func AttributeValueMapBufferSize(classID ClassID, attributes AttributeValueMap, msgType uint8) (int, error) {
	attrDefs, err := GetAttributesDefinitions(classID)
	if err.StatusCode() != Success {
		return 0, err
	} else if attributes == nil {
		return 0, NewProcessingError("Invalid (nil) Attribute Value Map referenced")
	}
	bufferSize := 0
	isGetResponse := msgType == 0x29

	for _, attrDef := range attrDefs {
		if isGetResponse && attrDef.IsTableAttribute() {
			bufferSize += 4
		} else {
			bufferSize += attrDef.GetSize()
		}
	}
	return bufferSize, nil
}
