package monitor

import (
	"local/rssmon3/config"
	"log"
	"time"

	"github.com/golang-collections/go-datastructures/queue"
)

type Item struct {
	Key string
}

const nsLast = "nsLast"
const nsInterval = "nsInterval"

var never = time.Date(2999, time.January, 1, 1, 1, 1, 1, time.UTC)
var forever = time.Duration(time.Hour * 99999)

func NewItem(key string, interval time.Duration) (*Item, error) {
	i := &Item{
		Key: key,
	}

	if err := i.setInterval(interval); err != nil {
		return nil, err
	}
	if err := i.setLast(time.Now().Add(-2 * interval)); err != nil {
		return nil, err
	}

	return &Item{
		Key: key,
	}, nil
}

func (i *Item) Compare(other queue.Item) int {
	j := other.(*Item)
	iNext := i.Last().Add(i.Interval())
	jNext := j.Last().Add(j.Interval())
	if iNext.Before(jNext) {
		return -1
	} else if jNext.Before(iNext) {
		return 1
	} else {
		return 0
	}
}

func (i *Item) Interval() time.Duration {
	t, err := i.getInterval()
	if err != nil {
		log.Println("[Interval]", err)
		return forever
	}
	return t
}

func (i *Item) getInterval() (time.Duration, error) {
	t := time.Duration(0)
	b, err := config.Values().DB.Get(i.Key, nsInterval)
	if err != nil {
		return forever, err
	}
	err = config.Decode(b, &t)
	return t, err
}

func (i *Item) setInterval(t time.Duration) error {
	b, err := config.Encode(t)
	if err != nil {
		return err
	}
	if err := config.Values().DB.Set(i.Key, b, nsInterval); err != nil {
		return err
	}
	return nil
}

func (i *Item) Last() time.Time {
	t, err := i.getLast()
	if err != nil {
		log.Println("[Last]", err)
	}
	return t
}

func (i *Item) Mark() {
	if err := i.setLast(time.Now()); err != nil {
		log.Println("[Mark]", err)
	}
}

func (i *Item) setLast(t time.Time) error {
	b, err := config.Encode(t)
	if err != nil {
		return err
	}
	return config.Values().DB.Set(i.Key, b, nsLast)
}

func (i *Item) getLast() (time.Time, error) {
	t := never
	b, err := config.Values().DB.Get(i.Key, nsLast)
	if err != nil {
		return never, err
	}
	err = config.Decode(b, &t)
	return t, err
}

func (i *Item) Encode() ([]byte, error) {
	return config.Encode(i)
}

func (i *Item) Decode(b []byte) error {
	return config.Decode(b, i)
}
