package de.sebse.fuplanner.tools;

import java.util.HashMap;
import java.util.LinkedList;

import de.sebse.fuplanner.tools.network.NetworkCallback;
import de.sebse.fuplanner.tools.network.NetworkErrorCallback;

public class AsyncQueue {
    private final HashMap<String, LinkedList<AsyncQueueCallback>> mQueues = new HashMap<>();
    private final HashMap<String, Boolean> mIsRunning = new HashMap<>();

    public void add(String hash, AsyncQueueCallback callback) {
        if (isRunning(hash))
            getQueue(hash).addLast(callback);
        else {
            setRunning(hash, true);
            callback.run();
        }
    }

    public void next(String hash) {
        AsyncQueueCallback callback = getQueue(hash).pollFirst();
        if (callback == null)
            setRunning(hash, false);
        else
            callback.run();
    }

    public interface AsyncQueueCallback {
        void run();
    }

    public NetworkErrorCallback check(String hash, NetworkErrorCallback value) {
        return error -> {
            value.onError(error);
            next(hash);
        };
    }

    public <T> NetworkCallback<T> check(String hash, NetworkCallback<T> value) {
        return success -> {
            value.onResponse(success);
            next(hash);
        };
    }

    private boolean isRunning(String hash) {
        return mIsRunning.containsKey(hash) && mIsRunning.get(hash);
    }

    private void setRunning(String hash, boolean value) {
        mIsRunning.put(hash, value);
    }

    private LinkedList<AsyncQueueCallback> getQueue(String hash) {
        if (mQueues.get(hash) == null)
            mQueues.put(hash, new LinkedList<>());
        return mQueues.get(hash);
    }
}

/*public class AsyncQueue<T, U> {
    private ArrayList<T> successes = new ArrayList<>();
    private ArrayList<U> errors = new ArrayList<>();
    private boolean isRequesting = false;

    public void add(T successFunc, U errorFunc) {
        this.successes.add(successFunc);
        this.errors.add(errorFunc);
    }

    public void add(T successFunc, U errorFunc, AsyncQueueCallback request) {
        this.add(successFunc, errorFunc);
        request(request);
    }

    public void forEachSuccess(AsyncQueueCallbackValue<T> forEach) {
        isRequesting = false;
        for (T success: this.successes) {
            forEach.run(success);
        }
        this.clear();
    }

    public void forEachError(AsyncQueueCallbackValue<U> forEach) {
        isRequesting = false;
        for (U error: this.errors) {
            forEach.run(error);
        }
        this.clear();
    }

    public void clear() {
        this.successes.clear();
        this.errors.clear();
    }

    public void request(AsyncQueueCallback request) {
        if (!this.isRequesting) {
            this.isRequesting = true;
            request.run();
        }
    }

    public interface AsyncQueueCallbackValue<T> {
        public void run(T value);
    }

    public interface AsyncQueueCallback {
        public void run();
    }
}*/
