/*
 * Copyright 2020-2024 Open Networking Foundation (ONF) and the ONF Contributors
 *
 * 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 devdb provides access to internal device ME DB
package devdb

import (
	"context"
	"encoding/hex"
	"fmt"
	"reflect"
	"sort"
	"sync"

	me "github.com/opencord/omci-lib-go/v2/generated"
	"github.com/opencord/voltha-lib-go/v7/pkg/log"
)

// MeDbMap type holds MEs that are known to the ONT.
type MeDbMap map[me.ClassID]map[uint16]me.AttributeValueMap

// UnknownMeAndAttribDbMap type holds MEs that are Unknown to the ONT.
type UnknownMeAndAttribDbMap map[UnknownMeOrAttribName]map[me.ClassID]map[uint16]unknownAttribs

// OnuMCmnMEDBMap type holds MEs that are classified as  Unknown to the ONT.
type OnuMCmnMEDBMap map[string]*OnuCmnMEDB

// UnknownMeOrAttribName type to be used for unknown ME and attribute names
type UnknownMeOrAttribName string

// names for unknown ME and attribute identifiers
const (
	CUnknownItuG988ManagedEntity        = "UnknownItuG988ManagedEntity"
	CUnknownVendorSpecificManagedEntity = "UnknownVendorSpecificManagedEntity"
	CUnknownAttributesManagedEntity     = "UnknownAttributesManagedEntity"
)

// CStartUnknownMeAttribsInBaseLayerPayload defines start of unknown ME attribs after ClassID, InstanceID and AttribMask
const CStartUnknownMeAttribsInBaseLayerPayload = 6

type unknownAttribs struct {
	AttribMask  string `json:"AttributeMask"`
	AttribBytes string `json:"AttributeBytes"`
}

// OnuDeviceDB structure holds information about ME's
type OnuDeviceDB struct {
	ctx                 context.Context
	deviceID            string
	CommonMeDb          *OnuCmnMEDB // Reference to OnuCmnMEDB
	OnuSpecificMeDbLock sync.RWMutex
	OnuSpecificMeDb     MeDbMap
}

// MIBUploadStatus represents the status of MIBUpload for a particular ONT.
type MIBUploadStatus int

// Values for Status of the ONT MIB Upload.
const (
	NotStarted MIBUploadStatus = iota // MIB upload has not started
	InProgress                        // MIB upload is in progress
	Failed                            // MIB upload has failed
	Completed                         // MIB upload is completed
)

// OnuCmnMEDB structure holds information about ME's common to ONT possessing same MIB Template.
type OnuCmnMEDB struct {
	MeDbLock             sync.RWMutex
	MeDb                 MeDbMap
	UnknownMeAndAttribDb UnknownMeAndAttribDbMap
	MIBUploadStatus      MIBUploadStatus
}

// NewOnuCmnMEDB returns a new instance of OnuCmnMEDB
func NewOnuCmnMEDB(ctx context.Context) *OnuCmnMEDB {

	return &OnuCmnMEDB{
		MeDbLock:             sync.RWMutex{},
		MeDb:                 make(MeDbMap),
		UnknownMeAndAttribDb: make(UnknownMeAndAttribDbMap),
		MIBUploadStatus:      NotStarted,
	}
}

// NewOnuDeviceDB returns a new instance for a specific ONU_Device_Entry
func NewOnuDeviceDB(ctx context.Context, aDeviceID string) *OnuDeviceDB {
	logger.Debugw(ctx, "Init OnuDeviceDB for:", log.Fields{"device-id": aDeviceID})
	var OnuDeviceDB OnuDeviceDB
	OnuDeviceDB.ctx = ctx
	OnuDeviceDB.deviceID = aDeviceID
	OnuDeviceDB.CommonMeDb = nil
	OnuDeviceDB.OnuSpecificMeDb = make(MeDbMap)

	return &OnuDeviceDB
}

// PutMe puts an ME instance into internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) PutMe(ctx context.Context, meClassID me.ClassID, meEntityID uint16, meAttributes me.AttributeValueMap) {

	//filter out the OnuData
	if me.OnuDataClassID == meClassID {
		return
	}

	// Dereference the MeDb pointer
	if OnuDeviceDB.CommonMeDb == nil || OnuDeviceDB.CommonMeDb.MeDb == nil {
		logger.Errorw(ctx, "MeDb is nil", log.Fields{"device-id": OnuDeviceDB.deviceID})
		return
	}
	meDb := OnuDeviceDB.CommonMeDb.MeDb
	_, ok := meDb[meClassID]
	if !ok {
		logger.Debugw(ctx, "meClassID not found - add to db :", log.Fields{"device-id": OnuDeviceDB.deviceID})
		meDb[meClassID] = make(map[uint16]me.AttributeValueMap)
		meDb[meClassID][meEntityID] = make(me.AttributeValueMap)
		meDb[meClassID][meEntityID] = meAttributes
	} else {
		meAttribs, ok := meDb[meClassID][meEntityID]
		if !ok {
			meDb[meClassID][meEntityID] = make(me.AttributeValueMap)
			meDb[meClassID][meEntityID] = meAttributes
		} else {
			for k, v := range meAttributes {
				meAttribs[k] = v
			}
			meDb[meClassID][meEntityID] = meAttribs
		}
	}
}

// GetMe returns an ME instance from internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) GetMe(meClassID me.ClassID, meEntityID uint16) me.AttributeValueMap {
	OnuDeviceDB.CommonMeDb.MeDbLock.RLock()
	defer OnuDeviceDB.CommonMeDb.MeDbLock.RUnlock()

	// Check in the common MeDb
	if meAttributes, present := OnuDeviceDB.CommonMeDb.MeDb[meClassID][meEntityID]; present {
		return meAttributes
	}

	OnuDeviceDB.OnuSpecificMeDbLock.RLock()
	defer OnuDeviceDB.OnuSpecificMeDbLock.RUnlock()

	// Check in the ONU-specific MeDb
	if meAttributes, present := OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID]; present {
		return meAttributes
	}
	return nil
}

// GetUint32Attrib converts JSON numbers to uint32
func (OnuDeviceDB *OnuDeviceDB) GetUint32Attrib(meAttribute interface{}) (uint32, error) {

	switch reflect.TypeOf(meAttribute).Kind() {
	case reflect.Float64:
		//JSON numbers by default are unmarshaled into values of float64 type if type information is not present
		return uint32(meAttribute.(float64)), nil
	case reflect.Uint32:
		return meAttribute.(uint32), nil
	default:
		return uint32(0), fmt.Errorf(fmt.Sprintf("wrong-interface-type-%v-received-for-device-%s", reflect.TypeOf(meAttribute).Kind(), OnuDeviceDB.deviceID))
	}
}

// GetUint16Attrib converts JSON numbers to uint16
func (OnuDeviceDB *OnuDeviceDB) GetUint16Attrib(meAttribute interface{}) (uint16, error) {

	switch reflect.TypeOf(meAttribute).Kind() {
	case reflect.Float64:
		//JSON numbers by default are unmarshaled into values of float64 type if type information is not present
		return uint16(meAttribute.(float64)), nil
	case reflect.Uint16:
		return meAttribute.(uint16), nil
	default:
		return uint16(0), fmt.Errorf(fmt.Sprintf("wrong-interface-type-%v-received-for-device-%s", reflect.TypeOf(meAttribute).Kind(), OnuDeviceDB.deviceID))
	}
}

// GetSortedInstKeys returns a sorted list of all instances of an ME
func (OnuDeviceDB *OnuDeviceDB) GetSortedInstKeys(ctx context.Context, meClassID me.ClassID) []uint16 {

	var meInstKeys []uint16
	OnuDeviceDB.CommonMeDb.MeDbLock.RLock()
	defer OnuDeviceDB.CommonMeDb.MeDbLock.RUnlock()
	meDb := OnuDeviceDB.CommonMeDb.MeDb

	// Check if the class ID exists in the MeDb map
	if meInstMap, found := meDb[meClassID]; found {
		for k := range meInstMap {
			meInstKeys = append(meInstKeys, k)
		}
		logger.Debugw(ctx, "meInstKeys - input order :", log.Fields{"meInstKeys": meInstKeys}) //TODO: delete the line after test phase!
	}
	sort.Slice(meInstKeys, func(i, j int) bool { return meInstKeys[i] < meInstKeys[j] })
	logger.Debugw(ctx, "meInstKeys - output order :", log.Fields{"meInstKeys": meInstKeys}) //TODO: delete the line after test phase!

	// Return the sorted instance keys
	return meInstKeys
}

// GetNumberOfInst returns the number of instances of an ME
func (OnuDeviceDB *OnuDeviceDB) GetNumberOfInst(meClassID me.ClassID) int {
	var count int

	OnuDeviceDB.CommonMeDb.MeDbLock.RLock()
	defer OnuDeviceDB.CommonMeDb.MeDbLock.RUnlock()

	if meClassMap, found := OnuDeviceDB.CommonMeDb.MeDb[meClassID]; found {
		count = len(meClassMap)
	}

	OnuDeviceDB.OnuSpecificMeDbLock.RLock()
	defer OnuDeviceDB.OnuSpecificMeDbLock.RUnlock()

	if onuSpecificMap, found := OnuDeviceDB.OnuSpecificMeDb[meClassID]; found {
		count += len(onuSpecificMap)
	}

	return count
}

// LogMeDb logs content of internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) LogMeDb(ctx context.Context) {
	logger.Debugw(ctx, "Logging ME instances for device:", log.Fields{"device-id": OnuDeviceDB.deviceID})

	if OnuDeviceDB.CommonMeDb != nil && OnuDeviceDB.CommonMeDb.MeDb != nil {
		meDb := OnuDeviceDB.CommonMeDb.MeDb

		for meClassID, meInstMap := range meDb {
			for meEntityID, meAttribs := range meInstMap {
				logger.Debugw(ctx, "Common ME instance: ", log.Fields{"meClassID": meClassID, "meEntityID": meEntityID, "meAttribs": meAttribs,
					"device-id": OnuDeviceDB.deviceID})
			}
		}
	} else {
		logger.Warnw(ctx, "Common MeDb is nil", log.Fields{"device-id": OnuDeviceDB.deviceID})
	}

	// Log ONU-specific ME instances
	OnuDeviceDB.OnuSpecificMeDbLock.RLock()
	defer OnuDeviceDB.OnuSpecificMeDbLock.RUnlock()

	for meClassID, meInstMap := range OnuDeviceDB.OnuSpecificMeDb {
		for meEntityID, meAttribs := range meInstMap {
			logger.Debugw(ctx, "ONU Specific ME instance:", log.Fields{
				"meClassID":  meClassID,
				"meEntityID": meEntityID,
				"meAttribs":  meAttribs,
				"device-id":  OnuDeviceDB.deviceID,
			})
		}
	}

}

// PutUnknownMeOrAttrib puts an instance with unknown ME or attributes into internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) PutUnknownMeOrAttrib(ctx context.Context, aMeName UnknownMeOrAttribName, aMeClassID me.ClassID, aMeEntityID uint16,
	aMeAttributeMask uint16, aMePayload []byte) {

	meAttribMaskStr := fmt.Sprintf("0x%04x", aMeAttributeMask)
	attribs := unknownAttribs{meAttribMaskStr, hex.EncodeToString(aMePayload)}

	unknownMeDb := OnuDeviceDB.CommonMeDb.UnknownMeAndAttribDb

	_, ok := unknownMeDb[aMeName]
	if !ok {
		unknownMeDb[aMeName] = make(map[me.ClassID]map[uint16]unknownAttribs)
		unknownMeDb[aMeName][aMeClassID] = make(map[uint16]unknownAttribs)
		unknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
	} else {
		_, ok := unknownMeDb[aMeName][aMeClassID]
		if !ok {
			unknownMeDb[aMeName][aMeClassID] = make(map[uint16]unknownAttribs)
			unknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
		} else {
			_, ok := unknownMeDb[aMeName][aMeClassID][aMeEntityID]
			if !ok {
				unknownMeDb[aMeName][aMeClassID][aMeEntityID] = attribs
			}
		}
	}
}

// DeleteMe deletes an ME instance from internal ONU DB
func (OnuDeviceDB *OnuDeviceDB) DeleteMe(meClassID me.ClassID, meEntityID uint16) {
	OnuDeviceDB.CommonMeDb.MeDbLock.Lock()
	defer OnuDeviceDB.CommonMeDb.MeDbLock.Unlock()
	meDb := OnuDeviceDB.CommonMeDb.MeDb
	delete(meDb[meClassID], meEntityID)

	OnuDeviceDB.OnuSpecificMeDbLock.Lock()
	defer OnuDeviceDB.OnuSpecificMeDbLock.Unlock()
	delete(OnuDeviceDB.OnuSpecificMeDb[meClassID], meEntityID)
}

// PutOnuSpeficMe puts an ME instance into specifically to the ONU DB maintained per ONU.
func (OnuDeviceDB *OnuDeviceDB) PutOnuSpeficMe(ctx context.Context, meClassID me.ClassID, meEntityID uint16, meAttributes me.AttributeValueMap) {
	OnuDeviceDB.OnuSpecificMeDbLock.Lock()
	defer OnuDeviceDB.OnuSpecificMeDbLock.Unlock()
	//filter out the OnuData
	if me.OnuDataClassID == meClassID {
		return
	}
	_, ok := OnuDeviceDB.OnuSpecificMeDb[meClassID]
	if !ok {
		logger.Debugw(ctx, "meClassID not found - add to db :", log.Fields{"device-id": OnuDeviceDB.deviceID})
		OnuDeviceDB.OnuSpecificMeDb[meClassID] = make(map[uint16]me.AttributeValueMap)
		OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID] = make(me.AttributeValueMap)
		OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID] = meAttributes
	} else {
		meAttribs, ok := OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID]
		if !ok {
			OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID] = make(me.AttributeValueMap)
			OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID] = meAttributes
		} else {
			for k, v := range meAttributes {
				meAttribs[k] = v
			}
			OnuDeviceDB.OnuSpecificMeDb[meClassID][meEntityID] = meAttribs
		}
	}
}
