package shared

import (
	"sync"
)

type UniqueFifo struct {
	keys   []string
	values []interface{}
	Mu     sync.Mutex
	size   int
}

func NewUniqueFifo(size int) *UniqueFifo {
	q := UniqueFifo{}
	q.keys = make([]string, 0)
	q.values = make([]interface{}, 0)
	q.size = size
	return &q
}

func (q *UniqueFifo) Add(k string, v interface{}) bool {
	ret := false
	if len(q.keys) == 0 {
		q.keys = append(q.keys, k)
		q.values = append(q.values, v)
		ret = false
	} else {
		i, _ := q.Contains(k)
		if i != -1 {
			q.Remove(i)
			ret = true
		} else {
			ret = false
		}
		q.keys = append(q.keys, "")
		q.values = append(q.values, "")
		copy(q.keys[1:], q.keys)
		copy(q.values[1:], q.values)
		q.keys[0] = k
		q.values[0] = v
		if len(q.keys) <= q.size {
			q.keys = q.keys[:len(q.keys)]
			q.values = q.values[:len(q.values)]
		} else {
			q.keys = q.keys[:q.size]
			q.values = q.values[:q.size]
		}
	}

	return ret
}

func (q *UniqueFifo) Remove(r int) {
	f := q.keys[:r]
	e := q.keys[r+1:]
	q.keys = f
	q.keys = append(q.keys, e...)

	n := q.values[:r]
	o := q.values[r+1:]
	q.values = n
	q.values = append(q.values, o...)
}

func (q *UniqueFifo) Contains(k string) (int, interface{}) {
	for i, key := range q.keys {
		if key == k {
			return i, q.values[i]
		}
	}
	return -1, nil
}