// Copyright Istio Authors
//
// 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 workloadinstances

import (
	"sync"
)

import (
	"github.com/apache/dubbo-go-pixiu/pilot/pkg/model"
)

// Index reprensents an index over workload instances from workload entries.
//
// Indexes are thread-safe.
type Index interface {
	// Insert adds/updates given workload instance to the index.
	//
	// Returns previous value in the index, or nil otherwise.
	Insert(*model.WorkloadInstance) *model.WorkloadInstance
	// Delete removes given workload instance from the index.
	//
	// Returns value removed from the index, or nil otherwise.
	Delete(*model.WorkloadInstance) *model.WorkloadInstance
	// GetByIP returns a list of all workload instances associated with a
	// given IP address. The list is ordered by namespace/name.
	//
	// There are several use cases where multiple workload instances might
	// have the same IP address:
	// 1) there are multiple Istio Proxies running on a single host, e.g.
	//    in 'router' mode or even in 'sidecar' mode.
	// 2) workload instances have the same IP but different networks
	GetByIP(string) []*model.WorkloadInstance
	// Empty returns whether the index is empty.
	Empty() bool
	// ForEach iterates over all workload instances in the index.
	ForEach(func(*model.WorkloadInstance))
}

// indexKey returns index key for a given workload instance.
func indexKey(wi *model.WorkloadInstance) string {
	return wi.Namespace + "/" + wi.Name
}

// NewIndex returns a new Index instance.
func NewIndex() Index {
	return &index{
		keyFunc:       indexKey,
		keyToInstance: make(map[string]*model.WorkloadInstance),
		ipToKeys:      make(MultiValueMap),
	}
}

// index implements Index.
type index struct {
	mu sync.RWMutex
	// key function
	keyFunc func(*model.WorkloadInstance) string
	// map of namespace/name -> workload instance
	keyToInstance map[string]*model.WorkloadInstance
	// map of ip -> set of namespace/name
	ipToKeys MultiValueMap
}

// Insert implements Index.
func (i *index) Insert(wi *model.WorkloadInstance) *model.WorkloadInstance {
	i.mu.Lock()
	defer i.mu.Unlock()

	key := i.keyFunc(wi)
	// Check to see if the workload entry changed. If it did, clear the old entry
	previous := i.keyToInstance[key]
	if previous != nil && previous.Endpoint.Address != wi.Endpoint.Address {
		i.ipToKeys.Delete(previous.Endpoint.Address, key)
	}
	i.keyToInstance[key] = wi
	i.ipToKeys.Insert(wi.Endpoint.Address, key)
	return previous
}

// Delete implements Index.
func (i *index) Delete(wi *model.WorkloadInstance) *model.WorkloadInstance {
	i.mu.Lock()
	defer i.mu.Unlock()

	key := i.keyFunc(wi)
	previous := i.keyToInstance[key]
	if previous != nil {
		i.ipToKeys.Delete(previous.Endpoint.Address, key)
	}
	i.ipToKeys.Delete(wi.Endpoint.Address, key)
	delete(i.keyToInstance, key)
	return previous
}

// GetByIP implements Index.
func (i *index) GetByIP(ip string) []*model.WorkloadInstance {
	i.mu.RLock()
	defer i.mu.RUnlock()

	keys := i.ipToKeys[ip]
	if len(keys) == 0 {
		return nil
	}
	instances := make([]*model.WorkloadInstance, 0, len(keys))
	for _, key := range keys.SortedList() {
		if instance, exists := i.keyToInstance[key]; exists {
			instances = append(instances, instance)
		}
	}
	return instances
}

// Empty implements Index.
func (i *index) Empty() bool {
	i.mu.RLock()
	defer i.mu.RUnlock()

	return len(i.keyToInstance) == 0
}

// ForEach iterates over all workload instances in the index.
func (i *index) ForEach(fn func(*model.WorkloadInstance)) {
	i.mu.RLock()
	defer i.mu.RUnlock()

	for _, instance := range i.keyToInstance {
		fn(instance)
	}
}
