package lib

import (
	"fmt"
	"sync"
)

type Queue[T any] struct {
	data []T
	lock sync.RWMutex
}

func NewQueue[T any]() *Queue[T] {
	return &Queue[T]{data: make([]T, 0)}
}

func (this *Queue[T]) Add(obj T) {
	this.lock.Lock()
	defer this.lock.Unlock()
	this.data = append(this.data, obj)
}

func (this *Queue[T]) List() []T {
	this.lock.RLock()
	defer this.lock.RUnlock()
	list := make([]T, 0, len(this.data))
	for _, v := range this.data {
		list = append(list, v)
	}
	return list
}

func (this *Queue[T]) Get(index int) (T, bool) {
	this.lock.RLock()
	defer this.lock.RUnlock()

	var ret T
	if index < 0 || index >= len(this.data) {
		return ret, false
	}

	return this.data[index], true
}

func (this *Queue[T]) Pop() (T, error) {
	this.lock.Lock()
	defer this.lock.Unlock()
	var ret T
	if len(this.data) == 0 {
		return ret, fmt.Errorf("not found")
	}

	pop := this.data[0]
	this.data = this.data[1:]
	return pop, nil
}
