package com.github.kubatatami.judonetworking.callbacks;

import com.github.kubatatami.judonetworking.AsyncResult;
import com.github.kubatatami.judonetworking.exceptions.JudoException;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Created by Kuba on 28/03/15.
 */
public class MergeCallback<T> {

    int requests;

    int finishRequests = 0;

    boolean started = false;

    boolean canceled = false;

    int progress;

    Set<AsyncResult> asyncResultSet = new HashSet<>();

    Callback<T> finalCallback;

    T result;

    public MergeCallback(int requests) {
        this.requests = requests;
    }

    public MergeCallback(int requests, Callback<T> finalCallback) {
        this.requests = requests;
        this.finalCallback = finalCallback;
    }

    public final void addStart(AsyncResult asyncResult) {
        if (canceled) {
            return;
        }
        if (!started) {
            started = true;
            onMergeStart();
        }
        asyncResultSet.add(asyncResult);
    }

    public final void addProgress(int progress) {
        if (canceled) {
            return;
        }
        this.progress+=progress;
        onMergeProgress(calculateProgress());
    }

    protected final int calculateProgress() {
        return (int) ((float) progress / (float) requests);
    }

    public final void addSuccess() {
        if (canceled) {
            return;
        }
        finishRequests++;
        if (finishRequests == requests) {
            onMergeSuccess();
            onMergeFinish();
        }

    }

    public final void addError(JudoException e) {
        if (canceled) {
            return;
        }
        onMergeError(e);
        onMergeFinish();
        cancelAll();
        canceled = true;
    }

    private void cancelAll() {
        for (AsyncResult asyncResult : asyncResultSet) {
            asyncResult.cancel();
        }
    }

    public void setResult(T result) {
        this.result = result;
    }

    protected void onMergeStart() {
        if (finalCallback != null) {
            finalCallback.onStart(null, new AsyncResult() {
                @Override
                public boolean isDone() {
                    for (AsyncResult asyncResult : asyncResultSet) {
                        if (!asyncResult.isDone()) {
                            return false;
                        }
                    }
                    return true;
                }

                @Override
                public boolean isCancelled() {
                    return canceled;
                }

                @Override
                public boolean isRunning() {
                    for (AsyncResult asyncResult : asyncResultSet) {
                        if (asyncResult.isRunning()) {
                            return true;
                        }
                    }
                    return false;
                }

                @Override
                public void cancel() {
                    cancelAll();
                }

                @Override
                public Map<String, List<String>> getHeaders() {
                    throw new UnsupportedOperationException("getHeaders of MergeCallback is not supported");
                }
            });
        }

    }

    protected void onMergeProgress(int progress) {
        if (finalCallback != null) {
            finalCallback.onProgress(progress);
        }
    }

    protected void onMergeSuccess() {
        if (finalCallback != null) {
            finalCallback.onSuccess(result);
        }
    }

    protected void onMergeError(JudoException e) {
        if (finalCallback != null) {
            finalCallback.onError(e);
        }
    }

    protected void onMergeFinish() {
        if (finalCallback != null) {
            finalCallback.onFinish();
        }
    }

}

@@ -484,28 +484,75 @@
 e;%0A%0A    
-int progress
+Map%3CBaseCallback%3C?%3E, Integer%3E progressMap = new HashMap%3C%3E()
 ;%0A%0A    S
@@ -1160,32 +1160,58 @@
 oid addProgress(
+BaseCallback%3C?%3E callback, 
 int progress) %7B%0A
@@ -1202,32 +1202,32 @@
 int progress) %7B%0A
-
         if (canc
@@ -1276,21 +1276,16 @@
     
-this.
 progress
 +=pr
@@ -1284,18 +1284,34 @@
 ress
-+=
+Map.put(callback, 
 progress
 ;%0A  
@@ -1306,16 +1306,17 @@
 progress
+)
 ;%0A      
@@ -1354,32 +1354,32 @@
 ress());%0A    %7D%0A%0A
-
     protected fi
@@ -1400,32 +1400,148 @@
 ateProgress() %7B%0A
+        int progress = 0;%0A        for (int value : progressMap.values()) %7B%0A            progress += value;%0A        %7D%0A
         return (

improve merge callback