// Copyright (c) 2020 Tailscale Inc & 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 portlist

import (
	"time"
)

type Poller struct {
	C      chan List     // new data when it arrives; closed when done
	quitCh chan struct{} // close this to force exit
	Err    error         // last returned error code, if any
	prev   List          // most recent data
}

func NewPoller() (*Poller, error) {
	p := &Poller{
		C:      make(chan List),
		quitCh: make(chan struct{}),
	}
	// Do one initial poll synchronously, so the caller can react
	// to any obvious errors.
	p.prev, p.Err = GetList(nil)
	return p, p.Err
}

func (p *Poller) Close() {
	close(p.quitCh)
	<-p.C
}

// Poll periodically. Run this in a goroutine if you want.
func (p *Poller) Run() error {
	defer close(p.C)
	tick := time.NewTicker(POLL_SECONDS * time.Second)
	defer tick.Stop()

	// Send out the pre-generated initial value
	p.C <- p.prev

	for {
		select {
		case <-tick.C:
			pl, err := GetList(p.prev)
			if err != nil {
				p.Err = err
				return p.Err
			}
			if !pl.SameInodes(p.prev) {
				p.prev = pl
				p.C <- pl
			}
		case <-p.quitCh:
			return nil
		}
	}
}