package com.lemenzo.messenger.util;

import android.content.BroadcastReceiver;
import android.util.Log;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Runs BroadcastReceiver follow-up work off the receiver main thread while keeping
 * the PendingResult alive until the work is complete. The pool is intentionally
 * small and bounded because SMS/MMS callbacks are bursty and should never create
 * an unbounded number of threads or queued tasks.
 */
public final class ReceiverAsync {
    private static final String TAG = "LemenzoReceiverAsync";
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            1,
            2,
            30L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(64),
            new ThreadFactory() {
                private int nextId;
                @Override public synchronized Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "LemenzoReceiver-" + (++nextId));
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy());

    static {
        EXECUTOR.allowCoreThreadTimeOut(true);
    }

    private ReceiverAsync() {}

    public static void run(BroadcastReceiver receiver, Runnable work) {
        final BroadcastReceiver.PendingResult pendingResult = receiver.goAsync();
        EXECUTOR.execute(() -> {
            try {
                work.run();
            } catch (RuntimeException e) {
                Log.e(TAG, "Asynchronous receiver work failed", e);
            } finally {
                pendingResult.finish();
            }
        });
    }
}
