package swift.client.proto;

import java.util.ArrayList;
import java.util.List;

import swift.clocks.CausalityClock;
import swift.clocks.Timestamp;
import swift.clocks.TimestampMapping;
import swift.crdt.operations.CRDTObjectUpdatesGroup;
import sys.net.api.rpc.RpcHandle;
import sys.net.api.rpc.RpcHandler;

/**
 * Client request to commit set of updates to the store.
 * <p>
 * All updates use the same client timestamp. Updates are organized into atomic
 * groups of updates per each object.
 * 
 * @author mzawirski
 */
// TODO: We can consider more space-efficient representation of this message
// that require a bit of extra processing at the server (e.g. baseTimestamp and
// dependency CausalityClock is shared by all updates).
public class CommitUpdatesRequest extends ClientRequest {
    protected List<CRDTObjectUpdatesGroup<?>> objectUpdateGroups;
    // Optimization HACK! dependencyClock and timestampMapping are unified to
    // limit data structure size and message size.
    // We should have a cleaner way to do it, perhaps with Kryo serializer?
    // Shall we really share these instances?
    protected TimestampMapping timestampMapping;
    protected CausalityClock dependencyClock;

    /**
     * Fake constructor for Kryo serialization. Do NOT use.
     */
    CommitUpdatesRequest() {
    }

    public CommitUpdatesRequest(String clientId, final Timestamp baseTimestamp,
            List<CRDTObjectUpdatesGroup<?>> objectUpdateGroups) {
        super(clientId);
        this.objectUpdateGroups = new ArrayList<CRDTObjectUpdatesGroup<?>>(objectUpdateGroups.size());
        // Part of optimization hack.
        for (final CRDTObjectUpdatesGroup<?> ops : objectUpdateGroups) {
            if (this.dependencyClock == null) {
                this.dependencyClock = ops.getDependency();
                this.timestampMapping = ops.getTimestampMapping();
            }
            ops.init(this.timestampMapping, this.dependencyClock);
            this.objectUpdateGroups.add(ops);
        }
    }

    /**
     * @return valid base timestamp for all updates in the request, previously
     *         obtained using {@link GenerateTimestampRequest}; all individual
     *         updates use TripleTimestamps with this base Timestamp
     */
    public Timestamp getBaseTimestamp() {
        return timestampMapping.getClientTimestamp();
    }

    /**
     * @return list of groups of object operations; there is at most one group
     *         per object and they all share the same base timestamp
     *         {@link #getBaseTimestamp()}
     */
    public List<CRDTObjectUpdatesGroup<?>> getObjectUpdateGroups() {
        return objectUpdateGroups;
    }

    @Override
    public void deliverTo(RpcHandle conn, RpcHandler handler) {
        ((SwiftServer) handler).onReceive(conn, this);
    }
}

@@ -145,46 +145,8 @@
 mp;%0A
-import swift.clocks.TimestampMapping;%0A
 impo
@@ -483,643 +483,171 @@
  */%0A
-// TODO: We can consider more space-efficient representation of this message%0A// that require a bit of extra processing at the server (e.g. baseTimestamp and%0A// dependency CausalityClock is shared by all updates).%0Apublic class CommitUpdatesRequest extends ClientRequest %7B%0A    protected List%3CCRDTObjectUpdatesGroup%3C?%3E%3E objectUpdateGroups;%0A    // Optimization HACK! dependencyClock and timestampMapping are unified to%0A    // limit data structure size and message size.%0A    // We should have a cleaner way to do it, perhaps with Kryo serializer?%0A    // Shall we really share these instances?%0A    protected TimestampMapping timestampMapping
+public class CommitUpdatesRequest extends ClientRequest %7B%0A    protected List%3CCRDTObjectUpdatesGroup%3C?%3E%3E objectUpdateGroups;%0A    protected Timestamp clientTimestamp
 ;%0A  
@@ -855,51 +855,8 @@
 tId,
- final Timestamp baseTimestamp,%0A           
  Lis
@@ -1028,15 +1028,8 @@
 oups
-.size()
 );%0A 
@@ -1039,422 +1039,83 @@
     
-// Part of optimization hack.%0A        for (final CRDTObjectUpdatesGroup%3C?%3E ops : objectUpdateGroups) %7B%0A            if (this.dependencyClock == null) %7B%0A                this.dependencyClock = ops.getDependency();%0A                this.timestampMapping = ops.getTimestampMapping();%0A            %7D%0A            ops.init(this.timestampMapping, this.dependencyClock);%0A            this.objectUpdateGroups.add(ops);%0A        %7D
+this.clientTimestamp = this.objectUpdateGroups.get(0).getClientTimestamp();
 %0A   
@@ -1422,29 +1422,9 @@
 urn 
-timestampMapping.getC
+c
 lien
@@ -1425,34 +1425,32 @@
  clientTimestamp
-()
 ;%0A    %7D%0A%0A    /**
@@ -1558,22 +1558,31 @@
 ject
- and they
+; note that
  all 
+groups 
 shar
@@ -1597,25 +1597,22 @@
 me base 
-timestamp
+client
 %0A     * 
@@ -1618,16 +1618,28 @@
         
+ timestamp (
  %7B@link 
@@ -1658,16 +1658,82 @@
 stamp()%7D
+), timestamp mappings and%0A     *         dependency clock.%0A     * 
 %0A     */

update implementation and docs