/*
 * Copyright 2017, TeamDev Ltd. 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 io.spine.annotation.Internal;
import io.spine.server.storage.ReadRequest;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A read request for {@link AggregateStorage}.
 *
 * <p>A result of this request is a record with the specified id.
 *
 * <p>To organize efficient reading of an aggregate history, {@link AggregateStorage} should
 * read {@linkplain AggregateEventRecord aggregate event records} by batches.
 *
 * <p>The request specifies a size of the batches as a
 * {@linkplain #getSnapshotTrigger snapshot trigger} value.
 *
 * <p>Two requests for the aggregate with the same {@link #id} are considered equal.
 * {@link #snapshotTrigger} is not taken into account, because it should affect only
 * process of reading, but resulting records should be the same.
 *
 * @param <I> the type of the record ID
 * @author Dmytro Grankin
 */
@Internal
public final class AggregateReadRequest<I> implements ReadRequest<I> {

    private final I id;
    private final int snapshotTrigger;

    public AggregateReadRequest(I id, int snapshotTrigger) {
        checkArgument(snapshotTrigger > 0);
        this.id = checkNotNull(id);
        this.snapshotTrigger = snapshotTrigger;
    }

    @Override
    public I getId() {
        return id;
    }

    /**
     * Obtains the {@linkplain AggregateRepository#snapshotTrigger snapshot trigger}.
     *
     * <p>Use this value for the {@linkplain AggregateStorage#historyBackward(AggregateReadRequest)
     * history} reading optimization.
     *
     * <p>To load an aggregate, required only the last {@link Snapshot} and events occurred after
     * creation of this snapshot. So instead of reading all {@linkplain AggregateEventRecord
     * aggregate event records}, it is reasonable to read them by batches, size of which is equal
     * to the snapshot trigger value.
     *
     * <p>NOTE: A snapshot trigger can be changed for {@link AggregateRepository}
     * after the instantiation, so the amount of events between snapshots can be different
     * in an aggregate history and may look like this: {@code e1, s1, e2, e3, e4, s2, e5, e6, s3}.
     *
     * @return the snapshot trigger value
     */
    public int getSnapshotTrigger() {
        return snapshotTrigger;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) { return true; }
        if (o == null || getClass() != o.getClass()) { return false; }

        AggregateReadRequest<?> that = (AggregateReadRequest<?>) o;

        return id.equals(that.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }
}

@@ -1275,22 +1275,68 @@
 A re
-ad request for
+quest to read events for a particular %7B@code Aggregate%7D from
  %7B@l
@@ -1375,24 +1375,35 @@
 A result of 
+processing 
 this request
@@ -1412,221 +1412,404 @@
 s a 
-record with the specified id.%0A *%0A * %3Cp%3ETo organize efficient reading of an aggregate history, %7B@link AggregateStorage%7D should%0A * read %7B@linkplain AggregateEventRecord aggregate event records%7D by batches.%0A *%0A * %3Cp%3E
+%7B@linkplain AggregateStateRecord record%7D,%0A * which satisfies the request criteria.%0A *%0A * %3Cp%3ETo restore an aggregate, the last %7B@link Snapshot%7D and events occurred after%0A * creation of this snapshot are required. So instead of reading all%0A * %7B@linkplain AggregateEventRecord aggregate event records%7D, it is reasonable to read%0A * them by batches, while the last %7B@link Snapshot%7D will not be found. 
 The 
@@ -1825,16 +1825,19 @@
 pecifies
+%0A *
  a size 
@@ -1855,19 +1855,16 @@
 hes as a
-%0A *
  %7B@linkp
@@ -2870,404 +2870,102 @@
 tion
-.%0A     *%0A     * %3Cp%3ETo load an aggregate, required only the last %7B@link Snapshot%7D and events occurred after%0A     * creation of this snapshot. So instead of reading all %7B@linkplain AggregateEventRecord%0A     * aggregate event records%7D, it is reasonable to read them by batches, size of which is equal%0A     * to the snapshot trigger value.%0A     *%0A     * %3Cp%3ENOTE: A snapshot trigger can be changed for
+ as a batch size.%0A     *%0A     * %3Cp%3EThe value reflects the current snapshot trigger set for the
  %7B@l
@@ -2988,24 +2988,25 @@
 ository%7D
+,
 %0A     * 
 after th
@@ -3001,189 +3001,40 @@
   * 
-after the instantiation, so the amount of events between snapshots can be different%0A     * in an aggregate history and may look like this: %7B@code e1, s1, e2, e3, e4, s2, e5, e6, s3%7D
+in which this request is created
 .%0A  

Improve Javadocs for `AggregateReadRequest`