/*
 * Copyright 2018-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.
 */
package model

import (
	"bytes"
	"crypto/md5"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/opencord/voltha-go/common/log"
	"reflect"
	"runtime/debug"
	"sort"
	"sync"
)

// TODO: Cache logic will have to be revisited to cleanup unused entries in memory (disabled for now)
//
//type revCacheSingleton struct {
//	sync.RWMutex
//	//Cache map[string]interface{}
//	Cache sync.Map
//}
//
//var revCacheInstance *revCacheSingleton
//var revCacheOnce sync.Once
//
//func GetRevCache() *revCacheSingleton {
//	revCacheOnce.Do(func() {
//		//revCacheInstance = &revCacheSingleton{Cache: make(map[string]interface{})}
//		revCacheInstance = &revCacheSingleton{Cache: sync.Map{}}
//	})
//	return revCacheInstance
//}

type NonPersistedRevision struct {
	mutex        sync.RWMutex
	Root         *root
	Config       *DataRevision
	childrenLock sync.RWMutex
	Children     map[string][]Revision
	Hash         string
	Branch       *Branch
	WeakRef      string
	Name         string
	discarded    bool
}

func NewNonPersistedRevision(root *root, branch *Branch, data interface{}, children map[string][]Revision) Revision {
	r := &NonPersistedRevision{}
	r.Root = root
	r.Branch = branch
	r.Config = NewDataRevision(root, data)
	r.Children = children
	r.Hash = r.hashContent()
	r.discarded = false
	return r
}

func (npr *NonPersistedRevision) IsDiscarded() bool {
	return npr.discarded
}

func (npr *NonPersistedRevision) SetConfig(config *DataRevision) {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	npr.Config = config
}

func (npr *NonPersistedRevision) GetConfig() *DataRevision {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	return npr.Config
}

func (npr *NonPersistedRevision) SetAllChildren(children map[string][]Revision) {
	npr.childrenLock.Lock()
	defer npr.childrenLock.Unlock()
	npr.Children = make(map[string][]Revision)

	for key, value := range children {
		npr.Children[key] = make([]Revision, len(value))
		copy(npr.Children[key], value)
	}
}

func (npr *NonPersistedRevision) SetChildren(name string, children []Revision) {
	npr.childrenLock.Lock()
	defer npr.childrenLock.Unlock()

	npr.Children[name] = make([]Revision, len(children))
	copy(npr.Children[name], children)
}

func (npr *NonPersistedRevision) GetAllChildren() map[string][]Revision {
	npr.childrenLock.Lock()
	defer npr.childrenLock.Unlock()

	return npr.Children
}

func (npr *NonPersistedRevision) GetChildren(name string) []Revision {
	npr.childrenLock.Lock()
	defer npr.childrenLock.Unlock()

	if _, exists := npr.Children[name]; exists {
		return npr.Children[name]
	}
	return nil
}

func (npr *NonPersistedRevision) SetHash(hash string) {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	npr.Hash = hash
}

func (npr *NonPersistedRevision) GetHash() string {
	//npr.mutex.Lock()
	//defer npr.mutex.Unlock()
	return npr.Hash
}

func (npr *NonPersistedRevision) ClearHash() {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	npr.Hash = ""
}

func (npr *NonPersistedRevision) GetName() string {
	//npr.mutex.Lock()
	//defer npr.mutex.Unlock()
	return npr.Name
}

func (npr *NonPersistedRevision) SetName(name string) {
	//npr.mutex.Lock()
	//defer npr.mutex.Unlock()
	npr.Name = name
}
func (npr *NonPersistedRevision) SetBranch(branch *Branch) {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	npr.Branch = branch
}

func (npr *NonPersistedRevision) GetBranch() *Branch {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	return npr.Branch
}

func (npr *NonPersistedRevision) GetData() interface{} {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	if npr.Config == nil {
		return nil
	}
	return npr.Config.Data
}

func (npr *NonPersistedRevision) GetNode() *node {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()
	return npr.Branch.Node
}

func (npr *NonPersistedRevision) Finalize(skipOnExist bool) {
	npr.Hash = npr.hashContent()
}

// hashContent generates a hash string based on the contents of the revision.
// The string should be unique to avoid conflicts with other revisions
func (npr *NonPersistedRevision) hashContent() string {
	var buffer bytes.Buffer
	var childrenKeys []string

	if npr.Config != nil {
		buffer.WriteString(npr.Config.Hash)
	}

	if npr.Name != "" {
		buffer.WriteString(npr.Name)
	}

	for key := range npr.Children {
		childrenKeys = append(childrenKeys, key)
	}

	sort.Strings(childrenKeys)

	if len(npr.Children) > 0 {
		// Loop through sorted Children keys
		for _, key := range childrenKeys {
			for _, child := range npr.Children[key] {
				if child != nil && child.GetHash() != "" {
					buffer.WriteString(child.GetHash())
				}
			}
		}
	}

	return fmt.Sprintf("%x", md5.Sum(buffer.Bytes()))[:12]
}

// Get will retrieve the data for the current revision
func (npr *NonPersistedRevision) Get(depth int) interface{} {
	// 1. Clone the data to avoid any concurrent access issues
	// 2. The current rev might still be pointing to an old config
	//    thus, force the revision to get its latest value
	latestRev := npr.GetBranch().GetLatest()
	originalData := proto.Clone(latestRev.GetData().(proto.Message))
	data := originalData

	if depth != 0 {
		// FIXME: Traversing the struct through reflection sometimes corrupts the data.
		// Unlike the original python implementation, golang structs are not lazy loaded.
		// Keeping this non-critical logic for now, but Get operations should be forced to
		// depth=0 to avoid going through the following loop.
		for fieldName, field := range ChildrenFields(latestRev.GetData()) {
			childDataName, childDataHolder := GetAttributeValue(data, fieldName, 0)
			if field.IsContainer {
				for _, rev := range latestRev.GetChildren(fieldName) {
					childData := rev.Get(depth - 1)
					foundEntry := false
					for i := 0; i < childDataHolder.Len(); i++ {
						cdh_if := childDataHolder.Index(i).Interface()
						if cdh_if.(proto.Message).String() == childData.(proto.Message).String() {
							foundEntry = true
							break
						}
					}
					if !foundEntry {
						// avoid duplicates by adding it only if the child was not found in the holder
						childDataHolder = reflect.Append(childDataHolder, reflect.ValueOf(childData))
					}
				}
			} else {
				if revs := npr.GetBranch().GetLatest().GetChildren(fieldName); revs != nil && len(revs) > 0 {
					rev := revs[0]
					if rev != nil {
						childData := rev.Get(depth - 1)
						if reflect.TypeOf(childData) == reflect.TypeOf(childDataHolder.Interface()) {
							childDataHolder = reflect.ValueOf(childData)
						}
					}
				}
			}
			// Merge child data with cloned object
			reflect.ValueOf(data).Elem().FieldByName(childDataName).Set(childDataHolder)
		}
	}

	result := data

	if result != nil {
		// We need to send back a copy of the retrieved object
		result = proto.Clone(data.(proto.Message))
	}

	return result
}

// UpdateData will refresh the data content of the revision
func (npr *NonPersistedRevision) UpdateData(data interface{}, branch *Branch) Revision {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()

	// Do not update the revision if data is the same
	if npr.Config.Data != nil && npr.Config.hashData(npr.Root, data) == npr.Config.Hash {
		log.Debugw("stored-data-matches-latest", log.Fields{"stored": npr.Config.Data, "provided": data})
		return npr
	}

	// Construct a new revision based on the current one
	newRev := NonPersistedRevision{}
	newRev.Config = NewDataRevision(npr.Root, data)
	newRev.Hash = npr.Hash
	newRev.Root = npr.Root
	newRev.Name = npr.Name
	newRev.Branch = branch

	newRev.Children = make(map[string][]Revision)
	for entryName, childrenEntry := range branch.GetLatest().GetAllChildren() {
		newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
	}

	newRev.Finalize(false)

	return &newRev
}

// UpdateChildren will refresh the list of children with the provided ones
// It will carefully go through the list and ensure that no child is lost
func (npr *NonPersistedRevision) UpdateChildren(name string, children []Revision, branch *Branch) Revision {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()

	// Construct a new revision based on the current one
	updatedRev := &NonPersistedRevision{}
	updatedRev.Config = NewDataRevision(npr.Root, npr.Config.Data)
	updatedRev.Hash = npr.Hash
	updatedRev.Branch = branch
	updatedRev.Name = npr.Name

	updatedRev.Children = make(map[string][]Revision)
	for entryName, childrenEntry := range branch.GetLatest().GetAllChildren() {
		updatedRev.Children[entryName] = append(updatedRev.Children[entryName], childrenEntry...)
	}

	var updatedChildren []Revision

	// Verify if the map contains already contains an entry matching the name value
	// If so, we need to retain the contents of that entry and merge them with the provided children revision list
	if existingChildren := branch.GetLatest().GetChildren(name); existingChildren != nil {
		// Construct a map of unique child names with the respective index value
		// for the children in the existing revision as well as the new ones
		existingNames := make(map[string]int)
		newNames := make(map[string]int)

		for i, newChild := range children {
			newNames[newChild.GetName()] = i
		}

		for i, existingChild := range existingChildren {
			existingNames[existingChild.GetName()] = i

			// If an existing entry is not in the new list, add it to the updated list, so it is not forgotten
			if _, exists := newNames[existingChild.GetName()]; !exists {
				updatedChildren = append(updatedChildren, existingChild)
			}
		}

		log.Debugw("existing-children-names", log.Fields{"hash": npr.GetHash(), "names": existingNames})

		// Merge existing and new children
		for _, newChild := range children {
			nameIndex, nameExists := existingNames[newChild.GetName()]

			// Does the existing list contain a child with that name?
			if nameExists {
				// Check if the data has changed or not
				if existingChildren[nameIndex].GetData().(proto.Message).String() != newChild.GetData().(proto.Message).String() {
					// replace entry
					newChild.GetNode().Root = existingChildren[nameIndex].GetNode().Root
					updatedChildren = append(updatedChildren, newChild)
				} else {
					// keep existing entry
					updatedChildren = append(updatedChildren, existingChildren[nameIndex])
				}
			} else {
				// new entry ... just add it
				updatedChildren = append(updatedChildren, newChild)
			}
		}

		// Save children in new revision
		updatedRev.SetChildren(name, updatedChildren)

		updatedNames := make(map[string]int)
		for i, updatedChild := range updatedChildren {
			updatedNames[updatedChild.GetName()] = i
		}

		log.Debugw("updated-children-names", log.Fields{"hash": npr.GetHash(), "names": updatedNames})

	} else {
		// There are no children available, just save the provided ones
		updatedRev.SetChildren(name, children)
	}

	updatedRev.Finalize(false)

	return updatedRev
}

// UpdateAllChildren will replace the current list of children with the provided ones
func (npr *NonPersistedRevision) UpdateAllChildren(children map[string][]Revision, branch *Branch) Revision {
	npr.mutex.Lock()
	defer npr.mutex.Unlock()

	newRev := npr
	newRev.Config = npr.Config
	newRev.Hash = npr.Hash
	newRev.Branch = branch
	newRev.Name = npr.Name

	newRev.Children = make(map[string][]Revision)
	for entryName, childrenEntry := range children {
		newRev.Children[entryName] = append(newRev.Children[entryName], childrenEntry...)
	}
	newRev.Finalize(false)

	return newRev
}

// Drop is used to indicate when a revision is no longer required
func (npr *NonPersistedRevision) Drop(txid string, includeConfig bool) {
	log.Debugw("dropping-revision", log.Fields{"hash": npr.GetHash(), "stack": string(debug.Stack())})
	npr.discarded = true
}

// ChildDrop will remove a child entry matching the provided parameters from the current revision
func (npr *NonPersistedRevision) ChildDrop(childType string, childHash string) {
	if childType != "" {
		children := make([]Revision, len(npr.GetChildren(childType)))
		copy(children, npr.GetChildren(childType))
		for i, child := range children {
			if child.GetHash() == childHash {
				children = append(children[:i], children[i+1:]...)
				npr.SetChildren(childType, children)
				break
			}
		}
	}
}

func (npr *NonPersistedRevision) LoadFromPersistence(path string, txid string) []Revision {
	// stub... required by interface
	return nil
}

func (npr *NonPersistedRevision) SetupWatch(key string) {
	// stub ... required by interface
}

func (pr *NonPersistedRevision) StorageDrop(txid string, includeConfig bool) {
	// stub ... required by interface
}
