package services

import (
	"sync"
	"time"

	"github.com/fiskerinc/cloud-services/pkg/kafka"
	"github.com/fiskerinc/cloud-services/pkg/logger"
	"github.com/pkg/errors"
	"gopkg.in/retry.v1"
)

const ServiceName = "jetfire"

var (
	consumer kafka.BaseConsumerInterface = nil

	consumerLock sync.Mutex

	kafkaRetry = retry.LimitTime(
		120*time.Second,
		retry.Exponential{
			Initial: 100 * time.Millisecond,
		})
)

// GetKafkaConsumer returns singleton instance of kafka consumer
func GetKafkaConsumer() (kafka.BaseConsumerInterface, error) {
	consumerLock.Lock()
	defer consumerLock.Unlock()

	if consumer != nil {
		return consumer, nil
	}

	var err error
	for a := retry.Start(kafkaRetry, nil); a.Next(); {
		newConsumer, err := kafka.NewBaseConsumer(ServiceName, -1, -1, true)
		if err == nil {
			consumer = newConsumer
			return consumer, nil
		}
		logger.Error().Err(err).Send()
	}
	err = errors.WithStack(err)
	return nil, err
}

// stops the kafka consumer, instantiates new one. gc should clean up old one
func ResetKafkaConsumer() (kafka.BaseConsumerInterface, error) {
	consumerLock.Lock()
	defer consumerLock.Unlock()

	logger.Info().Msgf("Resetting Kafka Consumer...")

	if consumer != nil {
		consumer.Stop()
		consumer = nil
	}

	var err error
	for a := retry.Start(kafkaRetry, nil); a.Next(); {
		newConsumer, err := kafka.NewBaseConsumer(ServiceName, -1, -1, true)
		if err == nil {
			consumer = newConsumer
			return consumer, nil
		}
		logger.Error().Err(err).Send()
	}
	err = errors.WithStack(err)
	return nil, err
}
