package org.ccci.gto.android.common.db.async;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

import org.ccci.gto.android.common.db.AbstractDao;
import org.ccci.gto.android.common.db.Expression;
import org.ccci.gto.android.common.db.Query;
import org.ccci.gto.android.common.util.AsyncTaskCompat;

import java.util.List;

public abstract class AbstractAsyncDao extends AbstractDao {
    protected AbstractAsyncDao(@NonNull final SQLiteOpenHelper helper) {
        super(helper);
    }

    @NonNull
    public final <T> ListenableFuture<List<T>> getAsync(@NonNull final Query<T> query) {
        final SettableFuture<List<T>> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(get(query));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final ListenableFuture<Cursor> getCursorAsync(@NonNull final Query<?> query) {
        final SettableFuture<Cursor> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(getCursor(query));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final <T> ListenableFuture<T> findAsync(@NonNull final Class<T> clazz, @NonNull final Object... key) {
        final SettableFuture<T> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(find(clazz, key));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final ListenableFuture<Long> insertAsync(@NonNull final Object obj) {
        return insertAsync(obj, SQLiteDatabase.CONFLICT_NONE);
    }

    @NonNull
    public final ListenableFuture<Long> insertAsync(@NonNull final Object obj, final int conflictAlgorithm) {
        final SettableFuture<Long> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(insert(obj, conflictAlgorithm));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final ListenableFuture<Integer> updateAsync(@NonNull final Object obj) {
        return updateAsync(obj, getFullProjection(obj.getClass()));
    }

    @NonNull
    public final ListenableFuture<Integer> updateAsync(@NonNull final Object obj, @NonNull final String... projection) {
        final SettableFuture<Integer> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(update(obj, projection));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final <T> ListenableFuture<Integer> updateAsync(@NonNull final T sample, @Nullable final Expression where,
                                                           @NonNull final String... projection) {
        final SettableFuture<Integer> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    future.set(update(sample, where, projection));
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }

    @NonNull
    public final ListenableFuture<?> updateOrInsertAsync(@NonNull final Object obj) {
        return updateOrInsertAsync(obj, getFullProjection(obj.getClass()));
    }

    @NonNull
    public final ListenableFuture<?> updateOrInsertAsync(@NonNull final Object obj,
                                                         @NonNull final String... projection) {
        final SettableFuture<Long> future = SettableFuture.create();
        AsyncTaskCompat.THREAD_POOL_EXECUTOR.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    updateOrInsert(obj, projection);
                    future.set(null);
                } catch (final Throwable t) {
                    future.setException(t);
                }
            }
        });
        return future;
    }
}

@@ -254,16 +254,74 @@
 ullable;
+%0Aimport android.support.v4.content.ParallelExecutorCompat;
 %0A%0Aimport
@@ -580,65 +580,8 @@
 ery;
-%0Aimport org.ccci.gto.android.common.util.AsyncTaskCompat;
 %0A%0Aim
@@ -952,44 +952,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -1488,44 +1488,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -2049,44 +2049,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -2773,44 +2773,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -3533,44 +3533,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -4209,44 +4209,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe
@@ -5038,44 +5038,52 @@
     
-AsyncTaskCompat.THREAD_POOL_EXECUTOR
+ParallelExecutorCompat.getParallelExecutor()
 .exe

switch to using ParallelExecutorCompat.getParallelExecutor()