/*
 * Copyright 2019, TeamDev. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package io.spine.server.aggregate;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import io.spine.core.Event;
import io.spine.core.EventContext;
import io.spine.core.Version;
import io.spine.core.Versions;

import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;

import static com.google.common.collect.ImmutableList.toImmutableList;

/**
 * Updates the version of aggregate events before they are played over the aggregate.
 */
final class VersionSequence {

    private final Version start;

    VersionSequence(Version start) {
        this.start = start;
    }

    /**
     * Prepares the given events to be applied to this aggregate.
     *
     * @param originalEvents
     *         the events to be applied
     * @return events ready to be applied to this aggregate
     * @see Aggregate#apply(List)
     */
    ImmutableList<Event> update(Collection<Event> originalEvents) {

        Stream<Version> versions = Stream.iterate(start, Versions::increment)
                                         .skip(1) // Skip current version
                                         .limit(originalEvents.size());
        Stream<Event> events = originalEvents.stream();
        ImmutableList<Event> eventsToApply = Streams.zip(events, versions,
                                                         VersionSequence::substituteVersion)
                                                    .collect(toImmutableList());
        return eventsToApply;
    }

    /**
     * Replaces the event version with the given {@code newVersion}.
     *
     * @param event
     *         original event
     * @param newVersion
     *         the version to set
     * @return the copy of the original event but with the new version
     */
    private static Event substituteVersion(Event event, Version newVersion) {
        EventContext newContext = event.context()
                                       .toVBuilder()
                                       .setVersion(newVersion)
                                       .build();
        Event result = event.toVBuilder()
                            .setContext(newContext)
                            .build();
        return result;
    }
}

@@ -1965,17 +1965,16 @@
 ents) %7B%0A
-%0A
         
@@ -1999,16 +1999,32 @@
 rsions =
+%0A               
  Stream.
@@ -2081,35 +2081,16 @@
         
-                
-   
 .skip(1)
@@ -2114,35 +2114,16 @@
 version%0A
-                   
         
@@ -2267,16 +2267,32 @@
 oApply =
+%0A               
  Streams
@@ -2346,37 +2346,8 @@
     
-                          
-   
 Vers
@@ -2382,37 +2382,8 @@
 on)%0A
-                             
     
@@ -2854,24 +2854,8 @@
 xt =
- event.context()
 %0A   
@@ -2859,34 +2859,48 @@
                 
-  
+event.context()%0A
                 
@@ -2939,34 +2939,16 @@
         
-                
-  
 .setVers
@@ -2963,34 +2963,16 @@
 ersion)%0A
-                  
         
@@ -3016,16 +3016,32 @@
 result =
+%0A               
  event.t
@@ -3044,39 +3044,32 @@
 nt.toVBuilder()%0A
-       
                 
@@ -3097,23 +3097,16 @@
 ontext)%0A
-       
         

Improve code layout