/**
 * Manager.java
 * Multithreaded example:
 * Give a job to each worker. As soon as a worker finishes his job, assign a new 
 *  job to the free worker.
 * @author Xuan Ngo
 */
import java.util.ArrayList;

public class Manager
{
  public static void main(String[] args)
  {
    // Variables
    int iNumOfWorkers = 3;// Number of workers.
    int iNumOfJobs = 11;  // Number of jobs.
    long lWaitTime = 1000;// Time lapse before asking who workers are free.
    
    // Create jobs list.
    ArrayList<String> aJobsList = new ArrayList<String>();
    for(int j=0; j<iNumOfJobs; j++)
      aJobsList.add((j+1)+"");
    
    // Create workers
    Worker aWorkers[] = new Worker[iNumOfWorkers];
    for(int i=0; i<iNumOfWorkers; i++)
    {
      aWorkers[i] = new Worker();
    }
    
    
    System.out.println("Start giving jobs to workers("+aJobsList.size()+" jobs)");    
    
    // Work until there is no job left.
    while(aJobsList.size()>0)
    {
      // Get a list of which workers are free.
      ArrayList<Integer> aFreeWorkersIndex = getFreeWorkers(aWorkers);
      
      // Show free workers.
      displayFreeWorkers(aFreeWorkersIndex);
      
      // Give each worker a job.
      for(int j=0; j<aFreeWorkersIndex.size(); j++)
      {
        int iWorkerId = aFreeWorkersIndex.get(j).intValue();
        aWorkers[iWorkerId] = new Worker();
        
        // Custom method used to pass data to the worker.
        aWorkers[iWorkerId].set("Worker"+iWorkerId, aJobsList);
        
        aWorkers[iWorkerId].start();
      }
      
      // Wait X time before asking who are free to take a job.
      try
      {
        Thread.sleep(lWaitTime);
      }
      catch(Exception ex)
      {
        System.out.println(ex);
      }
    }
   
    System.out.println("End giving jobs to workers.");
    
  }
  
  /**
   * Get the id of workers that are free.
   * @param aWorkers
   * @return IDs of workers that are free.
   */
  public static ArrayList<Integer> getFreeWorkers(Worker aWorkers[])
  {
    ArrayList<Integer> aFreeWorkersIndex = new ArrayList<Integer>();
    
    // Go through each worker and see who are free to take new job.
    for(int i=0; i<aWorkers.length; i++)
    {
      if(!aWorkers[i].isAlive())
      {
        aFreeWorkersIndex.add(new Integer(i));
      }
    }
    return aFreeWorkersIndex;
  }
  
  public static void displayFreeWorkers(ArrayList<Integer> aWorkers)
  {
    // No free workers. Get out.
    if(aWorkers.size()==0)
    {
      System.out.println("No free workers.");
      return;
    }
    
    // Display free workers.
    System.out.print("Free workers IDs: ");
    for(int i=0; i<aWorkers.size()-1; i++)
      System.out.print(aWorkers.get(i)+", ");
    System.out.print(aWorkers.get(aWorkers.size()-1)); // Display last worker's ID.
    System.out.println();
  }
}

