package org.testng.internal;

import org.testng.collections.Lists;
import org.testng.collections.Maps;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * This class allows a caller to pass a list of Callable workers that will be run in threads
 * taken from the thread pool.  Each list of callables is indexed with a key, and when they
 * have all completed, the listener passed in @code{submitTask} will be invoked with all
 * the futures.  Additional workers can be submitted to this pool while it is in existence
 * and the caller can either block while waiting for the results (@code{submitTasksAndWait})
 * or submit them asynchronously (@code{submitTasks}) and supply listeners to notify when
 * the callers are done.
 *  
 * @author cbeust
 *
 * @param <KeyType> The type of the key to index each list of Callables
 * @param <FutureType> The type of the result returned by the futures
 */
public class PoolService<KeyType, FutureType> {
  private static PoolService m_instance;

  private ExecutorService m_service;
  private HashMap<KeyType, List<Future<FutureType>>> m_futureMap;
  private Thread m_listenerThread;
  private Map<KeyType, PoolListener<KeyType, FutureType>> m_listeners;

  /**
   * One pool is created per XmlSuite object.
   * 
   * @param threadPoolSize the size of the thread pool
   */
  private PoolService(int threadPoolSize) {
    m_instance = this;
    m_service = Executors.newFixedThreadPool(threadPoolSize);
    m_futureMap = new HashMap<KeyType, List<Future<FutureType>>>();
    m_listeners = Maps.newHashMap();

    m_listenerThread = new Thread() {
      public void run() {
        System.out.println("Listener thread starting, futures:" + m_futureMap.size());
        while (m_futureMap.size() > 0) {
          List<KeyType> doneFutures = Lists.newArrayList();
          for (KeyType key : m_futureMap.keySet()) {
            List<Future<FutureType>> futures = m_futureMap.get(key);
            if (isFinished(futures)) {
              PoolListener<KeyType, FutureType> listener = m_listeners.get(key);
              if (listener != null) {
                listener.onFinish(key, futures);
              }
              m_listeners.remove(key);
              doneFutures.add(key);
            }
          }
          for (KeyType key : doneFutures) {
            m_futureMap.remove(key);
          }
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
        System.out.println("Listener thread ending");
      }
    };
  }

  public static void initialize(int threadCount) {
    m_instance = new PoolService(threadCount);
  }

  public static PoolService getInstance() {
    if (m_instance == null) {
      throw new RuntimeException("The Service Pool was not created, should never happen");
    }

    return m_instance;
  }

  /**
   * This listener will be invoked as soon as all the Callables in a given list have completed.
   */
  public static interface PoolListener<KeyType, FutureType> {
    public void onFinish(KeyType key, List<Future<FutureType>> results);
  }

  /**
   * Submit the tasks to the thread pool.
   */
  public List<FutureType> submitTasksAndWait(KeyType key, List<Callable<FutureType>> tasks) {
    submitTasks(key, tasks, null);
    List<Future<FutureType>> futures = m_futureMap.get(key);
    while (!isFinished(futures)) {
      try {
        Thread.sleep(1000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    List<FutureType> result = Lists.newArrayList();
    for (Future<FutureType> future : futures) {
      try {
        result.add(future.get());
      } catch (InterruptedException e) {
        e.printStackTrace();
      } catch (ExecutionException e) {
        e.printStackTrace();
      }
    }
    return result;
  }

  public void submitTasks(KeyType key, List<Callable<FutureType>> tasks,
      PoolListener<KeyType, FutureType> listener) {

    for (Callable<FutureType> task : tasks) {
      Future<FutureType> future = m_service.submit(task);
      List<Future<FutureType>> list = m_futureMap.get(key);
      if (list == null) {
        list = Lists.newArrayList();
        m_futureMap.put(key, list);
      }
      list.add(future);
    }

    if (listener != null) {
      m_listeners.put(key, listener);

      if (!m_listenerThread.isAlive()) {
        m_listenerThread.start();
      }
    }
  }

  private boolean isFinished(List<Future<FutureType>> futures) {
    for (Future<FutureType> f : futures) {
      if (!f.isDone())
        return false;
    }
    return true;
  }

  /**
   * Shut down the service.
   */
  public void shutdown() {
    Utils.log(getClass().getName(), 3, "Shutting down poolservice " + this + " terminated:"
        + m_service.isTerminated());
    //      if (m_service.isTerminated()) {
    m_service.shutdown();
    //      }
  }

}
