// Copyright 2016 Google Inc. All Rights Reserved.
package com.android.contacts.util.concurrent;

import android.os.AsyncTask;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;

import com.google.common.util.concurrent.ForwardingFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.SettableFuture;

import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RunnableScheduledFuture;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Provides some common executors for use with {@link Futures}
 */
public class ContactsExecutors {

    private ContactsExecutors() {}

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;

    // AsyncTask.THREAD_POOL_EXECUTOR is a ThreadPoolExecutor so we should end up always using that
    // but we have a fallback in case the platform implementation changes in some future release.
    private static final ListeningExecutorService DEFAULT_THREAD_POOL_EXECUTOR =
            (AsyncTask.THREAD_POOL_EXECUTOR instanceof ExecutorService) ?
                    MoreExecutors.listeningDecorator(
                            (ExecutorService) AsyncTask.THREAD_POOL_EXECUTOR) :
                    MoreExecutors.listeningDecorator(
                            Executors.newFixedThreadPool(CORE_POOL_SIZE));

    // We initialize this lazily since in some cases we may never even read from the SIM card
    private static ListeningExecutorService sSimExecutor;

    /**
     * Returns the default thread pool that can be used for background work.
     */
    public static ListeningExecutorService getDefaultThreadPoolExecutor() {
        return DEFAULT_THREAD_POOL_EXECUTOR;
    }

    /**
     * Creates an executor that runs commands on the application UI thread
     */
    public static ScheduledExecutorService newUiThreadExecutor() {
        return newHandlerExecutor(new Handler(Looper.getMainLooper()));
    }

    /**
     * Create an executor that posts commands to the provided handler
     */
    public static ScheduledExecutorService newHandlerExecutor(final Handler handler) {
        return new HandlerExecutorService(handler);
    }

    /**
     * Returns an ExecutorService that can be used to read from the SIM card.
     *
     * <p>See b/32831092</p>
     * <p>A different executor than {@link ContactsExecutors#getDefaultThreadPoolExecutor()} is
     * provided for this case because reads of the SIM card can block for long periods of time
     * and if they do we might exhaust our thread pool. Additionally it appears that reading from
     * the SIM provider from multiple threads concurrently can cause problems.
     * </p>
     */
    public synchronized static ListeningExecutorService getSimReadExecutor() {
        if (sSimExecutor == null) {
            final ThreadPoolExecutor executor = new ThreadPoolExecutor(
                    1, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
            executor.allowCoreThreadTimeOut(true);
            sSimExecutor = MoreExecutors.listeningDecorator(executor);
        }
        return sSimExecutor;
    }

    /**
     * Wrapper around a handler that implements a subset of the ScheduledExecutorService
     *
     * <p>This class is useful for testability because Handler can't be mocked since it's
     * methods are final. It might be better to just use Executors.newSingleThreadScheduledExecutor
     * in the cases where we need to run some time based tasks.
     * </p>
     */
    private static class HandlerExecutorService extends AbstractExecutorService
            implements ScheduledExecutorService {
        private final Handler mHandler;

        private HandlerExecutorService(Handler handler) {
            mHandler = handler;
        }

        @NonNull
        @Override
        public ScheduledFuture<?> schedule(final Runnable command, long delay, TimeUnit unit) {
            final HandlerFuture<Void> future = HandlerFuture
                    .fromRunnable(mHandler, delay, unit, command);
            mHandler.postDelayed(future, unit.toMillis(delay));
            return future;
        }

        @NonNull
        @Override
        public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
            final HandlerFuture<V> future = new HandlerFuture<>(mHandler, delay, unit, callable);
            mHandler.postDelayed(future, unit.toMillis(delay));
            return future;
        }

        @NonNull
        @Override
        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay,
                long period, TimeUnit unit) {
            throw new UnsupportedOperationException();
        }

        @NonNull
        @Override
        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay,
                long delay, TimeUnit unit) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void shutdown() {
        }

        @Override
        public List<Runnable> shutdownNow() {
            return null;
        }

        @Override
        public boolean isShutdown() {
            return false;
        }

        @Override
        public boolean isTerminated() {
            return false;
        }

        @Override
        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
            throw new UnsupportedOperationException();
        }

        @Override
        public void execute(Runnable command) {
            mHandler.post(command);
        }
    }

    private static class HandlerFuture<T> extends ForwardingFuture<T> implements
            RunnableScheduledFuture<T> {

        private final Handler mHandler;
        private final TimeUnit mUnit;
        private final long mDelay;
        private final Callable<T> mTask;
        private final SettableFuture<T> mDelegate = SettableFuture.create();

        private HandlerFuture(Handler handler, long delay, TimeUnit timeUnit, Callable<T> task) {
            mHandler = handler;
            mUnit = timeUnit;
            mDelay = delay;
            mTask = task;
        }

        @Override
        public boolean isPeriodic() {
            return false;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            return unit.convert(mDelay, mUnit);
        }

        @Override
        public int compareTo(Delayed o) {
            return Long.compare(mDelay, o.getDelay(mUnit));
        }

        @Override
        protected Future<T> delegate() {
            return mDelegate;
        }

        @Override
        public boolean cancel(boolean b) {
            mHandler.removeCallbacks(this);
            return super.cancel(b);
        }

        @Override
        public void run() {
            try {
                mDelegate.set(mTask.call());
            } catch (Exception e) {
                mDelegate.setException(e);
            }
        }

        public static HandlerFuture<Void> fromRunnable(Handler handler, long delay, TimeUnit unit,
                final Runnable command) {
            return new HandlerFuture<>(handler, delay, unit, new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    command.run();
                    return null;
                }
            });
        }
    }
}
