package com.timgroup.eventstore.readerutils;

import com.timgroup.eventstore.api.EventReader;
import com.timgroup.eventstore.api.EventRecord;
import com.timgroup.eventstore.api.Position;
import com.timgroup.eventstore.api.ResolvedEvent;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

import static java.util.Objects.requireNonNull;

@ParametersAreNonnullByDefault
public class TransformingEventReader implements EventReader {

    private final EventReader underlying;
    private final Function<ResolvedEvent, ResolvedEvent> transformer;

    protected TransformingEventReader(EventReader underlying, Function<ResolvedEvent, ResolvedEvent> transformer) {
        this.underlying = requireNonNull(underlying);
        this.transformer = requireNonNull(transformer);
    }

    public static TransformingEventReader transformEventRecords(EventReader underlying, Function<EventRecord, EventRecord> transformer) {
        return transformResolvedEvents(underlying, toResolvedEventTransformer(transformer));
    }

    public static TransformingEventReader transformResolvedEvents(EventReader underlying, Function<ResolvedEvent, ResolvedEvent> transformer) {
        return new TransformingEventReader(underlying, transformer);
    }


    public static Function<ResolvedEvent, ResolvedEvent> toResolvedEventTransformer(Function<EventRecord, EventRecord> transformer) {
        return re -> new ResolvedEvent(re.position(), transformer.apply(re.eventRecord()));
    }

    @CheckReturnValue
    @Nonnull
    @Override
    public final Stream<ResolvedEvent> readAllForwards(Position positionExclusive) {
        return underlying.readAllForwards(positionExclusive).map(transformer);
    }

    @Nonnull
    @Override
    public final Position emptyStorePosition() {
        return underlying.emptyStorePosition();
    }

    @CheckReturnValue
    @Nonnull
    @Override
    public final Stream<ResolvedEvent> readAllBackwards() {
        return underlying.readAllBackwards().map(transformer);
    }

    @CheckReturnValue
    @Nonnull
    @Override
    public final Stream<ResolvedEvent> readAllBackwards(Position positionExclusive) {
        return underlying.readAllBackwards(positionExclusive).map(transformer);
    }

    @Nonnull
    @Override
    public Optional<ResolvedEvent> readLastEvent() {
        return underlying.readLastEvent().map(transformer);
    }

    @Override
    public String toString() {
        return "TransformingEventReader{" +
                "underlying=" + underlying +
                ", transformer=" + transformer +
                '}';
    }
}

@@ -414,24 +414,29 @@
 unction.
-Function
+UnaryOperator
 ;%0Aimport
@@ -669,32 +669,22 @@
 nal 
-Function%3CResolvedEvent, 
+UnaryOperator%3C
 Reso
@@ -774,32 +774,22 @@
 ng, 
-Function%3CResolvedEvent, 
+UnaryOperator%3C
 Reso
@@ -1019,38 +1019,30 @@
 rlying, 
-Function%3CEventRecord, 
+UnaryOperator%3C
 EventRec
@@ -1255,32 +1255,22 @@
 ng, 
-Function%3CResolvedEvent, 
+UnaryOperator%3C
 Reso
@@ -1394,32 +1394,22 @@
 tic 
-Function%3CResolvedEvent, 
+UnaryOperator%3C
 Reso
@@ -1450,30 +1450,22 @@
 mer(
-Function%3CEventRecord, 
+UnaryOperator%3C
 Even
@@ -1480,32 +1480,69 @@
  transformer) %7B%0A
+        requireNonNull(transformer);%0A
         return r

use UnaryOperator harder