// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/InteractorInvokerImp.java
// public class InteractorInvokerImp implements InteractorInvoker {
// 
//   private ExecutorService executor;
//   private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
// 
//   public InteractorInvokerImp(ExecutorService executor,
//       Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
//     this.executor = executor;
//     this.uncaughtExceptionHandler = uncaughtExceptionHandler;
//   }
// 
//   @Override public <T> Future<T> execute(InteractorExecution<T> execution) {
//     if (execution.getInteractorResult() != null) {
//       return (Future<T>) executor.submit(
//           new InteractorExecutionFutureTask<>(execution, uncaughtExceptionHandler));
//     } else {
//       return executor.submit(new PriorityInteractorDecorator<>(execution));
//     }
//   }
// }
// 
// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/InteractorPriorityBlockingQueue.java
// public class InteractorPriorityBlockingQueue extends PriorityBlockingQueue<Runnable> {
// 
//   public InteractorPriorityBlockingQueue(int initialCapacity) {
//     super(initialCapacity, new Comparator<Runnable>() {
//       @Override public int compare(Runnable runnable1, Runnable runnable2) {
//         boolean firstIsPriority = runnable1 instanceof PriorityRunnableFutureDecorated;
//         boolean secondIsPriority = runnable2 instanceof PriorityRunnableFutureDecorated;
// 
//         if (!firstIsPriority && !secondIsPriority) {
//           return 0;
//         } else if (!firstIsPriority) {
//           return -1;
//         } else if (!secondIsPriority) {
//           return 1;
//         }
// 
//         int priority1 = ((PriorityRunnableFutureDecorated) runnable1).getPriority();
//         int priority2 = ((PriorityRunnableFutureDecorated) runnable2).getPriority();
// 
//         return Integer.valueOf(priority1).compareTo(priority2);
//       }
//     });
//   }
// }
// 
// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/LogExceptionHandler.java
// public class LogExceptionHandler implements Thread.UncaughtExceptionHandler {
// 
//   private static final String TAG = "LogExceptionHandler";
// 
//   @Override public void uncaughtException(Thread thread, Throwable ex) {
//     Log.e(TAG, "Unhandled Interactor Exception", ex);
//   }
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/invoker/InteractorInvoker.java
// public interface InteractorInvoker {
//   <T> Future<T> execute(InteractorExecution<T> interactor);
// }


import dagger.Module;
import dagger.Provides;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import me.panavtec.cleancontacts.BuildConfig;
import me.panavtec.cleancontacts.domain.invoker.InteractorInvokerImp;
import me.panavtec.cleancontacts.domain.invoker.InteractorOutputThreadFactory;
import me.panavtec.cleancontacts.domain.invoker.InteractorPriorityBlockingQueue;
import me.panavtec.cleancontacts.domain.invoker.LogExceptionHandler;
import me.panavtec.cleancontacts.domain.invoker.PriorizableThreadPoolExecutor;
import me.panavtec.cleancontacts.presentation.invoker.InteractorInvoker;
package me.panavtec.cleancontacts.di;


@Module(
    includes = {
        InteractorsModule.class
    },
    complete = false,
    library = true) public class DomainModule {

  @Provides @Singleton InteractorInvoker provideInteractorInvoker(ExecutorService executor,
      LogExceptionHandler logExceptionHandler) {
    return new InteractorInvokerImp(executor, logExceptionHandler);
  }

// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/InteractorInvokerImp.java
// public class InteractorInvokerImp implements InteractorInvoker {
// 
//   private ExecutorService executor;
//   private Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
// 
//   public InteractorInvokerImp(ExecutorService executor,
//       Thread.UncaughtExceptionHandler uncaughtExceptionHandler) {
//     this.executor = executor;
//     this.uncaughtExceptionHandler = uncaughtExceptionHandler;
//   }
// 
//   @Override public <T> Future<T> execute(InteractorExecution<T> execution) {
//     if (execution.getInteractorResult() != null) {
//       return (Future<T>) executor.submit(
//           new InteractorExecutionFutureTask<>(execution, uncaughtExceptionHandler));
//     } else {
//       return executor.submit(new PriorityInteractorDecorator<>(execution));
//     }
//   }
// }
// 
// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/InteractorPriorityBlockingQueue.java
// public class InteractorPriorityBlockingQueue extends PriorityBlockingQueue<Runnable> {
// 
//   public InteractorPriorityBlockingQueue(int initialCapacity) {
//     super(initialCapacity, new Comparator<Runnable>() {
//       @Override public int compare(Runnable runnable1, Runnable runnable2) {
//         boolean firstIsPriority = runnable1 instanceof PriorityRunnableFutureDecorated;
//         boolean secondIsPriority = runnable2 instanceof PriorityRunnableFutureDecorated;
// 
//         if (!firstIsPriority && !secondIsPriority) {
//           return 0;
//         } else if (!firstIsPriority) {
//           return -1;
//         } else if (!secondIsPriority) {
//           return 1;
//         }
// 
//         int priority1 = ((PriorityRunnableFutureDecorated) runnable1).getPriority();
//         int priority2 = ((PriorityRunnableFutureDecorated) runnable2).getPriority();
// 
//         return Integer.valueOf(priority1).compareTo(priority2);
//       }
//     });
//   }
// }
// 
// Path: app/src/main/java/me/panavtec/cleancontacts/domain/invoker/LogExceptionHandler.java
// public class LogExceptionHandler implements Thread.UncaughtExceptionHandler {
// 
//   private static final String TAG = "LogExceptionHandler";
// 
//   @Override public void uncaughtException(Thread thread, Throwable ex) {
//     Log.e(TAG, "Unhandled Interactor Exception", ex);
//   }
// }
// 
// Path: presentation/src/main/java/me/panavtec/cleancontacts/presentation/invoker/InteractorInvoker.java
// public interface InteractorInvoker {
//   <T> Future<T> execute(InteractorExecution<T> interactor);
// }


// Path: app/src/main/java/me/panavtec/cleancontacts/di/DomainModule.java
import dagger.Module;
import dagger.Provides;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import javax.inject.Singleton;
import me.panavtec.cleancontacts.BuildConfig;
import me.panavtec.cleancontacts.domain.invoker.InteractorInvokerImp;
import me.panavtec.cleancontacts.domain.invoker.InteractorOutputThreadFactory;
import me.panavtec.cleancontacts.domain.invoker.InteractorPriorityBlockingQueue;
import me.panavtec.cleancontacts.domain.invoker.LogExceptionHandler;
import me.panavtec.cleancontacts.domain.invoker.PriorizableThreadPoolExecutor;
import me.panavtec.cleancontacts.presentation.invoker.InteractorInvoker;

package me.panavtec.cleancontacts.di;


@Module(
    includes = {
        InteractorsModule.class
    },
    complete = false,
    library = true) public class DomainModule {

  @Provides @Singleton InteractorInvoker provideInteractorInvoker(ExecutorService executor,
      LogExceptionHandler logExceptionHandler) {
    return new InteractorInvokerImp(executor, logExceptionHandler);
  }

  @Provides @Singleton LogExceptionHandler provideLogExceptionHandler() {