/*
 * 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 (
	"sync"

	"github.com/opencord/voltha-lib-go/v3/pkg/log"
)

// TODO: implement weak references or something equivalent
// TODO: missing proper logging

// Branch structure is used to classify a collection of transaction based revisions
type Branch struct {
	mutex      sync.RWMutex
	Node       *node
	Txid       string
	Origin     Revision
	Revisions  map[string]Revision
	LatestLock sync.RWMutex
	Latest     Revision
}

// NewBranch creates a new instance of the Branch structure
func NewBranch(node *node, txid string, origin Revision, autoPrune bool) *Branch {
	b := &Branch{}
	b.Node = node
	b.Txid = txid
	b.Origin = origin
	b.Revisions = make(map[string]Revision)
	b.Latest = origin

	return b
}

// Utility function to extract all children names for a given revision (mostly for debugging purposes)
func (b *Branch) retrieveChildrenNames(revision Revision) []string {
	var childrenNames []string

	for _, child := range revision.GetChildren("devices") {
		childrenNames = append(childrenNames, child.GetName())
	}

	return childrenNames
}

// Utility function to compare children names and report the missing ones (mostly for debugging purposes)
func (b *Branch) findMissingChildrenNames(previousNames, latestNames []string) []string {
	var missingNames []string

	for _, previousName := range previousNames {
		found := false

		if len(latestNames) == 0 {
			break
		}

		for _, latestName := range latestNames {
			if previousName == latestName {
				found = true
				break
			}
		}
		if !found {
			missingNames = append(missingNames, previousName)
		}
	}

	return missingNames
}

// SetLatest assigns the latest revision for this branch
func (b *Branch) SetLatest(latest Revision) {
	b.mutex.Lock()
	defer b.mutex.Unlock()

	if b.Latest != nil {
		logger.Debugw("updating-latest-revision", log.Fields{"current": b.Latest.GetHash(), "new": latest.GetHash()})

		// Go through list of children names in current revision and new revision
		// and then compare the resulting outputs to ensure that we have not lost any entries.

		if level, _ := log.GetPackageLogLevel(); level == log.DebugLevel {
			var previousNames, latestNames, missingNames []string

			if previousNames = b.retrieveChildrenNames(b.Latest); len(previousNames) > 0 {
				logger.Debugw("children-of-previous-revision", log.Fields{"hash": b.Latest.GetHash(), "names": previousNames})
			}

			if latestNames = b.retrieveChildrenNames(b.Latest); len(latestNames) > 0 {
				logger.Debugw("children-of-latest-revision", log.Fields{"hash": latest.GetHash(), "names": latestNames})
			}

			if missingNames = b.findMissingChildrenNames(previousNames, latestNames); len(missingNames) > 0 {
				logger.Debugw("children-missing-in-latest-revision", log.Fields{"hash": latest.GetHash(), "names": missingNames})
			}
		}

	} else {
		logger.Debugw("setting-latest-revision", log.Fields{"new": latest.GetHash()})
	}

	b.Latest = latest
}

// GetLatest retrieves the latest revision of the branch
func (b *Branch) GetLatest() Revision {
	b.mutex.RLock()
	defer b.mutex.RUnlock()

	return b.Latest
}

// GetOrigin retrieves the original revision of the branch
func (b *Branch) GetOrigin() Revision {
	b.mutex.RLock()
	defer b.mutex.RUnlock()

	return b.Origin
}

// AddRevision inserts a new revision to the branch
func (b *Branch) AddRevision(revision Revision) {
	if revision != nil && b.GetRevision(revision.GetHash()) == nil {
		b.SetRevision(revision.GetHash(), revision)
	}
}

// GetRevision pulls a revision entry at the specified hash
func (b *Branch) GetRevision(hash string) Revision {
	b.mutex.RLock()
	defer b.mutex.RUnlock()

	if revision, ok := b.Revisions[hash]; ok {
		return revision
	}

	return nil
}

// SetRevision updates a revision entry at the specified hash
func (b *Branch) SetRevision(hash string, revision Revision) {
	b.mutex.Lock()
	defer b.mutex.Unlock()

	b.Revisions[hash] = revision
}

// DeleteRevision removes a revision with the specified hash
func (b *Branch) DeleteRevision(hash string) {
	b.mutex.Lock()
	defer b.mutex.Unlock()

	delete(b.Revisions, hash)
}
