/*
 * Copyright 2014 Timothy Brooks
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package net.uncontended.precipice.pattern;

import net.uncontended.precipice.Controller;
import net.uncontended.precipice.Status;
import net.uncontended.precipice.concurrent.PrecipiceFuture;
import net.uncontended.precipice.concurrent.PrecipicePromise;
import net.uncontended.precipice.threadpool.ThreadPoolService;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class ThreadPoolShotgun<C> {

    private final ShotgunStrategy strategy;
    private final Controller<Status> controller;
    private final NewShotgun<Status, ThreadPoolService> newShotgun;
    private final Map<ThreadPoolService, C> serviceToContext;

    public ThreadPoolShotgun(Map<ThreadPoolService, C> serviceToContext, int submissionCount, Controller<Status> controller) {
        this(serviceToContext, submissionCount, controller, new ShotgunStrategy(serviceToContext.size(), submissionCount));
    }

    @SuppressWarnings("unchecked")
    public ThreadPoolShotgun(Map<ThreadPoolService, C> serviceToContext, int submissionCount, Controller<Status> controller,
                             ShotgunStrategy strategy) {
        if (serviceToContext.size() == 0) {
            throw new IllegalArgumentException("Cannot create ThreadPoolShotgun with 0 Executors.");
        } else if (submissionCount > serviceToContext.size()) {
            throw new IllegalArgumentException("Submission count cannot be greater than the number of services " +
                    "provided.");
        }

        this.serviceToContext = serviceToContext;
        this.controller = controller;
        List<ThreadPoolService> services = new ArrayList<>(serviceToContext.size());
        for (Map.Entry<ThreadPoolService, C> entry : serviceToContext.entrySet()) {
            services.add(entry.getKey());
        }

        this.newShotgun = new NewShotgun<>(controller, services, strategy);
        this.strategy = strategy;
    }

    public <T> PrecipiceFuture<Status, T> submit(final PatternAction<T, C> action, long millisTimeout) {
        PatternResult<ThreadPoolService, PrecipicePromise<Status, T>> patternEntries = newShotgun.promisePair();

//        for (PatternResult<ThreadPoolService, PrecipicePromise<Status, T>> entry : patternEntries) {
//            if (entry != null) {
//                ThreadPoolService service = entry.controllable;
//                final C context = serviceToContext.get(service);
//
//                Callable<T> callable = new CallableWithContext<>(action, context);
//                ExecutorService executor = service.getExecutor();
//                TimeoutService timeoutService = service.getTimeoutService();
//
//                long adjustedTimeout = TimeoutService.adjustTimeout(millisTimeout);
//                long startNanos = System.nanoTime();
//                ThreadPoolTask<T> task = new ThreadPoolTask<>(callable, entry.completable, adjustedTimeout, startNanos);
//                executor.execute(task);
//                timeoutService.scheduleTimeout(task);
//            }
//        }

//        return patternEntries[0].completable.future();
        return null;
    }

    public void shutdown() {
        for (ThreadPoolService service : serviceToContext.keySet()) {
            service.shutdown();
        }

    }
}

@@ -634,16 +634,63 @@
 ttern;%0A%0A
+import net.uncontended.precipice.Controllable;%0A
 import n
@@ -957,163 +957,351 @@
 ce;%0A
-%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0Aimport java.util.Map;%0A%0Apublic class ThreadPoolShotgun%3CC%3E %7B%0A%0A    private final ShotgunStrategy strategy;
+import net.uncontended.precipice.threadpool.ThreadPoolTask;%0Aimport net.uncontended.precipice.timeout.TimeoutService;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.List;%0Aimport java.util.Map;%0Aimport java.util.concurrent.Callable;%0Aimport java.util.concurrent.ExecutorService;%0A%0Apublic class ThreadPoolShotgun%3CC%3E implements Controllable%3CStatus%3E %7B%0A
 %0A   
@@ -2715,36 +2715,81 @@
     
+%7D%0A%0A
     
-this.strategy = strategy
+public Controller%3CStatus%3E controller() %7B%0A        return controller
 ;%0A  
@@ -2968,30 +2968,22 @@
 us, T%3E%3E 
-patternEntries
+result
  = newSh
@@ -3004,18 +3004,16 @@
 air();%0A%0A
-//
         
@@ -3017,28 +3017,27 @@
    for (
-PatternResul
+ChildContex
 t%3CThread
@@ -3090,67 +3090,32 @@
 y : 
-patternEntries) %7B%0A//            if (entry != null) %7B%0A//    
+result.submissions()) %7B%0A
     
@@ -3170,22 +3170,16 @@
 llable;%0A
-//    
         
@@ -3231,25 +3231,17 @@
 rvice);%0A
-//%0A//    
+%0A
         
@@ -3307,30 +3307,24 @@
 , context);%0A
-//    
             
@@ -3369,30 +3369,24 @@
 Executor();%0A
-//    
             
@@ -3450,17 +3450,9 @@
 ();%0A
-//%0A//    
+%0A
     
@@ -3527,22 +3527,16 @@
 meout);%0A
-//    
         
@@ -3576,18 +3576,16 @@
 Time();%0A
-//
         
@@ -3580,36 +3580,32 @@
 ();%0A            
-    
 ThreadPoolTask%3CT
@@ -3693,22 +3693,16 @@
 Nanos);%0A
-//    
         
@@ -3721,36 +3721,32 @@
 .execute(task);%0A
-//  
               ti
@@ -3741,18 +3741,16 @@
         
-  
 timeoutS
@@ -3783,26 +3783,9 @@
 k);%0A
-//            %7D%0A//
+%0A
     
@@ -3791,18 +3791,16 @@
      %7D%0A%0A
-//
         
@@ -3810,27 +3810,26 @@
 urn 
-patternEntries%5B0%5D.c
+result.getPatternC
 ompl
@@ -3834,16 +3834,18 @@
 pletable
+()
 .future(
@@ -3851,29 +3851,8 @@
 ();%0A
-        return null;%0A
     

Work towards a common threadpool pattern