// Copyright 2016 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package vine contains a discovery plugin that is using Vine protocol.
//
// This plugin is for testing Vanadium applications under unpredictable and
// unfriendly network conditions.
//
// Usage:
//
//	import (
//		"v.io/x/ref/lib/discovery"
//		"v.io/x/ref/lib/discovery/factory"
//		"v.io/x/ref/lib/discovery/plugins/vine"
//	)
//
//	p, err := vine.New(...)
//	...
//	df, err := discovery.NewFactory(ctx, p)
//	...
//	// The factory should be injected before v23.NewDiscovery() is called.
//	factory.InjectFactory(df)
//
//	d, err := v23.NewDiscovery(ctx)
//	...
package vine

import (
	"sync"
	"time"

	"v.io/v23/context"
	"v.io/v23/discovery"

	idiscovery "v.io/x/ref/lib/discovery"
	"v.io/x/ref/lib/timekeeper"
)

const (
	defaultTTL = 90 * time.Second

	minTTLSlack = 2 * time.Second
	maxTTLSlack = 10 * time.Second
)

type plugin struct {
	peers func(*context.T) []string
	store *store

	clock timekeeper.TimeKeeper

	ttl          time.Duration
	ttlWithSlack time.Duration
}

func (p *plugin) Advertise(ctx *context.T, adinfo *idiscovery.AdInfo, done func()) error {
	go func() {
		defer done()

		// We need a context that is detached from the deadlines and cancellation of ctx
		// since we have to unpublish the advertisement from peers after ctx is canceled.
		rctx, _ := context.WithRootCancel(ctx)
		defer p.unpublish(rctx, adinfo.Ad.Id)

		for {
			p.publish(ctx, *adinfo)

			select {
			case <-p.clock.After(p.ttl):
			case <-ctx.Done():
				return
			}
		}
	}()
	return nil
}

func (p *plugin) Scan(ctx *context.T, interfaceName string, ch chan<- *idiscovery.AdInfo, done func()) error {
	updated := p.store.listenToUpdates(ctx)

	go func() {
		defer done()

		seen := make(map[discovery.AdId]idiscovery.AdInfo)
		for {
			current := p.store.lookup(interfaceName)

			changed := make([]idiscovery.AdInfo, 0, len(current))
			for id, adinfo := range current {
				if old, ok := seen[id]; !ok || old.Hash != adinfo.Hash {
					changed = append(changed, adinfo)
				}
			}
			for id, adinfo := range seen {
				if _, ok := current[id]; !ok {
					adinfo.Lost = true
					changed = append(changed, adinfo)
				}
			}
			// Push new changes.
			for i := range changed {
				select {
				case ch <- &changed[i]:
				case <-ctx.Done():
					return
				}
			}
			seen = current

			// Wait the next update.
			select {
			case <-updated:
			case <-ctx.Done():
				return
			}
		}
	}()
	return nil
}

func (p *plugin) Close() {
	p.store.stop()
}

func (p *plugin) publish(ctx *context.T, adinfo idiscovery.AdInfo) {
	// Clear DirAddrs since we publish a full advertisement information.
	adinfo.DirAddrs = nil

	var wg sync.WaitGroup
	for _, peer := range p.peers(ctx) {
		wg.Add(1)
		go func(peer string) {
			defer wg.Done()
			if err := StoreClient(peer).Add(ctx, adinfo, p.ttlWithSlack); err != nil {
				ctx.Error(err)
			}
		}(peer)
	}
	wg.Wait()
}

func (p *plugin) unpublish(ctx *context.T, id discovery.AdId) {
	var wg sync.WaitGroup
	for _, peer := range p.peers(ctx) {
		wg.Add(1)
		go func(peer string) {
			defer wg.Done()
			if err := StoreClient(peer).Delete(ctx, id); err != nil {
				ctx.Error(err)
			}
		}(peer)
	}
	wg.Wait()
}

// New returns a new vine plugin instance with default ttl (90s).
func New(ctx *context.T, name string, peers func(*context.T) []string) (idiscovery.Plugin, error) {
	return NewWithTTL(ctx, name, peers, defaultTTL)
}

// New returns a new vine plugin instance. If ttl is zero, the default values will be used.
func NewWithTTL(ctx *context.T, name string, peers func(*context.T) []string, ttl time.Duration) (idiscovery.Plugin, error) {
	return newWithClock(ctx, name, peers, ttl, timekeeper.RealTime())
}

func newWithClock(ctx *context.T, name string, peers func(*context.T) []string, ttl time.Duration, clock timekeeper.TimeKeeper) (idiscovery.Plugin, error) {
	store, err := newStore(ctx, name, clock)
	if err != nil {
		return nil, err
	}

	if ttl == 0 {
		ttl = defaultTTL
	}
	ttlSlack := time.Duration(ttl.Nanoseconds() / 10)
	if ttlSlack < minTTLSlack {
		ttlSlack = minTTLSlack
	} else if ttlSlack > maxTTLSlack {
		ttlSlack = maxTTLSlack
	}
	p := &plugin{
		peers:        peers,
		store:        store,
		clock:        clock,
		ttl:          ttl,
		ttlWithSlack: ttl + ttlSlack,
	}
	return p, nil
}
