package common

import (
	"github.com/sirupsen/logrus"
	"sync"
	"time"
)

/*
 IntervalHandler is used to run a routine at regular intervals and provide all the necessary
 utilities to manage the execution.
*/

type IntervalHandler struct {
	// Interval period in between each execution (in seconds?)
	Interval int
	// function to execute after each interval
	function func()
	// Channel listening to execution events
	execute chan _ExecutionState
	// Channel listening for a termination event
	terminate chan struct{}
	// Current execution state of the handler
	state _ExecutionState
	wg    sync.WaitGroup
}

// Define execution state constants
type _ExecutionState uint8

const (
	STARTED _ExecutionState = iota
	STOPPED
	PAUSED
	RESUMED
)

// Execute state string equivalents
var _ExecutionStateEnum = []string{
	"STARTED",
	"STOPPED",
	"PAUSED",
	"RESUMED",
}

func (s _ExecutionState) String() string {
	return _ExecutionStateEnum[s]
}

/*
NewIntervalHandler instantiates a new interval based function execution handler
*/
func NewIntervalHandler(interval int, function func()) *IntervalHandler {
	handler := &IntervalHandler{
		Interval: interval,
		function: function,
	}

	handler.execute = make(chan _ExecutionState)
	handler.terminate = make(chan struct{})
	handler.state = STOPPED

	return handler
}

/*
_Execute is a routine running concurrently and listening to execution events
*/
func (h *IntervalHandler) _Execute() {
	defer h.wg.Done()
	for {
		select {
		case h.state = <-h.execute:
			Logger().WithFields(logrus.Fields{
				"handler": h,
			}).Debug("Processing execution state")
			switch h.state {
			case STARTED:
			case PAUSED:
			case RESUMED:
				h.state = STARTED
			case STOPPED:
				fallthrough
			default:
				h.terminate <- struct{}{}
			}

		case <-h.terminate:
			return

		default:
			if h.state == STARTED {
				h.function()
				time.Sleep(time.Duration(h.Interval) * time.Second)
			} else {
				// TODO: replace hardcoded delay with a configurable parameter
				time.Sleep(1 * time.Second)
			}
		}
	}
}

/*
Start initiates the interval based function execution
*/
func (h *IntervalHandler) Start() {
	Logger().WithFields(logrus.Fields{
		"handler": h,
	}).Info("Starting interval handler")

	if h.execute == nil {
		return
	}
	if h.state == STOPPED {
		go h._Execute()
		h.execute <- STARTED
	}
}

/*
Pause interrupts the interval based function execution
*/
func (h *IntervalHandler) Pause() {
	Logger().WithFields(logrus.Fields{
		"handler": h,
	}).Info("Pausing interval handler")

	if h.execute == nil || h.state == STOPPED {
		return
	}
	if h.state == STARTED {
		h.execute <- PAUSED
	}
}

/*
Resume continues the interval based function execution
*/
func (h *IntervalHandler) Resume() {
	Logger().WithFields(logrus.Fields{
		"handler": h,
	}).Info("Resuming interval handler")

	if h.execute == nil || h.state == STOPPED {
		return
	}
	if h.state == PAUSED {
		h.execute <- RESUMED
	}
}

/*
Stop terminates the interval based function execution
*/
func (h *IntervalHandler) Stop() {
	Logger().WithFields(logrus.Fields{
		"handler": h,
	}).Info("Stopping interval handler")

	if h.execute == nil || h.state == STOPPED {
		return
	}
	h.execute <- STOPPED
}
