package ru.micord.ervu.kafka.service.impl;

import java.util.Optional;
import java.util.concurrent.ExecutionException;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.springframework.kafka.requestreply.ReplyingKafkaTemplate;
import org.springframework.kafka.requestreply.RequestReplyFuture;
import ru.micord.ervu.kafka.service.ReplyingKafkaService;

/**
 * @author gulnaz
 */
public abstract class BaseReplyingKafkaService<T, V> implements ReplyingKafkaService<T, V> {

  @Override
  public V sendMessageAndGetReply(String requestTopic, String replyTopic, T requestMessage) {
    RequestReplyFuture<String, T, V> replyFuture = getTemplate().sendAndReceive(
        getProducerRecord(requestTopic, replyTopic, requestMessage));

    try {
      return Optional.ofNullable(replyFuture.get())
          .map(ConsumerRecord::value)
          .orElseThrow(() -> new RuntimeException("Kafka return result is null"));
    }
    catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException("Failed to get kafka response", e);
    }
  }
  protected abstract ReplyingKafkaTemplate<String, T, V> getTemplate();

  protected abstract ProducerRecord<String, T> getProducerRecord(String requestTopic,
      String replyTopic, T requestMessage);
}
