package uk.ac.ic.wlgitbridge.snapshot.push;

import com.google.common.base.Preconditions;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InvalidPostbackKeyException;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.UnexpectedPostbackException;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Winston on 17/11/14.
 */
public class PostbackManager {

    private final SecureRandom random;
    final Map<String, PostbackPromise> postbackContentsTable;

    PostbackManager(SecureRandom random) {
        this.random = random;
        postbackContentsTable = Collections.synchronizedMap(
                new HashMap<String, PostbackPromise>()
        );
    }

    public PostbackManager() {
        this(new SecureRandom());
    }

    public int waitForVersionIdOrThrow(String projectName)
            throws SnapshotPostException {
        try {
            PostbackPromise postbackPromise =
                    postbackContentsTable.get(projectName);
            Preconditions.checkNotNull(postbackPromise);
            return postbackPromise.waitForPostback();
        } finally {
            postbackContentsTable.remove(projectName);
        }
    }

    public void postVersionIDForProject(String projectName,
                                        int versionID,
                                        String postbackKey)
            throws UnexpectedPostbackException {
        getPostbackForProject(
                projectName
        ).receivedVersionID(versionID, postbackKey);
    }

    public void postExceptionForProject(String projectName,
                                        SnapshotPostException exception,
                                        String postbackKey)
            throws UnexpectedPostbackException {
        getPostbackForProject(
                projectName
        ).receivedException(exception, postbackKey);
    }

    private PostbackPromise getPostbackForProject(String projectName)
            throws UnexpectedPostbackException {
        PostbackPromise contents = postbackContentsTable.get(projectName);
        if (contents == null) {
            throw new UnexpectedPostbackException();
        }
        return contents;
    }

    public String makeKeyForProject(String projectName) {
        String key = System.currentTimeMillis() + randomString();
        PostbackPromise contents = new PostbackPromise(key);
        postbackContentsTable.put(projectName, contents);
        return key;
    }

    public void checkPostbackKey(String projectName, String postbackKey)
            throws InvalidPostbackKeyException {
        postbackContentsTable.get(projectName).checkPostbackKey(postbackKey);
    }

    private String randomString() {
        return new BigInteger(130, random).toString(32);
    }

}

@@ -2761,32 +2761,66 @@
 eption %7B%0A       
+ PostbackPromise postbackPromise =
  postbackContent
@@ -2842,16 +2842,192 @@
 ectName)
+;%0A        if (postbackPromise == null) %7B%0A            throw new InvalidPostbackKeyException(); // project not found; can't check key%0A        %7D else %7B%0A            postbackPromise
 .checkPo
@@ -3042,32 +3042,42 @@
 y(postbackKey);%0A
+        %7D%0A
     %7D%0A%0A    priva

Check for missing project before checking key