package transactions

import (
	"errors"
	"sync"
)

type Mempool struct {
	txs []*Transaction
	mu  sync.RWMutex
}

func NewMempool() *Mempool {
	return &Mempool{}
}

func (m *Mempool) Add(tx *Transaction) error {
	m.mu.Lock()
	defer m.mu.Unlock()
	if m.Has(tx.Hash()) {
		return errors.New("transação já existente na mempool")
	}
	m.txs = append(m.txs, tx)
	return nil
}

func (m *Mempool) Remove(hash string) {
	m.mu.Lock()
	defer m.mu.Unlock()
	for i, tx := range m.txs {
		if tx.Hash() == hash {
			m.txs = append(m.txs[:i], m.txs[i+1:]...)
			return
		}
	}
}

func (m *Mempool) All() []*Transaction {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return append([]*Transaction(nil), m.txs...)
}

func (m *Mempool) GetByHash(hash string) *Transaction {
	m.mu.RLock()
	defer m.mu.RUnlock()
	for _, tx := range m.txs {
		if tx.Hash() == hash {
			return tx
		}
	}
	return nil
}

func (m *Mempool) Pending() []*Transaction {
	return m.All()
}

func (m *Mempool) Clear() {
	m.mu.Lock()
	defer m.mu.Unlock()
	m.txs = []*Transaction{}
}

func (m *Mempool) Has(hash string) bool {
	m.mu.RLock()
	defer m.mu.RUnlock()
	for _, tx := range m.txs {
		if tx.Hash() == hash {
			return true
		}
	}
	return false
}