import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Iterator;
import java.io.File;
import java.io.IOException;

/**
 * The controller class creates a set of worker
 * threads to calculate * the sum of a set of
 * integers contained in files in the sepecified 
 * directory.
 */
public class Controller {
    private String directoryPath;
    private int sum;
    private ArrayList workers;
    private LinkedList files;

    /**
     * Start a set of worker threads to some the integers
     * found in the directoryPath directory.
     */
    public Controller( String directoryPath, int noWorkers ) {
        this.directoryPath = directoryPath;
        this.sum = 0;
        this.workers = new ArrayList();
        this.files = new LinkedList();

        File dir = new File( directoryPath );
        File[] list = dir.listFiles();
        if ( list == null ) {
            return;
        }
        /*
         * files must be created before any workers
         * are started.
         */
        for( int i = 0 ; i < list.length; i++ ) {
            files.add( list[i].getName() );
        }

        /* create the workers */
        for( int i = 0 ; i < noWorkers ; i++ ) {
            workers.add( new Worker( this ) );
        }
        /* start them up */
        Iterator it = workers.iterator();
        while ( it.hasNext() ) {
            Worker w = (Worker)it.next();
            w.start();
        }
    }

    /**
     * Retrieve the next file to processes.
     * Must be synchronized since more than one worker
     * can attempt to get a file.
     */
    public synchronized File getFile() {
        if ( files.size() == 0 ) return null;
        String f = (String)files.removeFirst();
        return new File( directoryPath, f );
    }

    /**
     * Invoked by a worker to update the total sum.
     * Must be synchronized since more than one worker
     * can attempt to upate the sum.
     */
    public synchronized void updateSum( int s ) {
        sum += s;
    }

    public void waitForWorkers() {
        Iterator it = workers.iterator();
        while ( it.hasNext() ) {
            Worker w = (Worker)it.next();
            try {
                w.join();
            }
            catch( InterruptedException ex ) {
            }
        }
    }

    public synchronized int getSum() {
        return sum;
    }

    public static void main( String[] args ) {
        if ( args.length != 2 ) {
            System.err.println(
                "uasge: java Controller dir no_workers");
            return;
        }
        long t0 = System.currentTimeMillis();
        int noWorkers = 0;
        try {
            noWorkers = Integer.parseInt( args[1] );
        }
        catch( NumberFormatException ex ) {
            System.err.println("no_workers is not a number");
            return;
        }

        Controller controller =
            new Controller( args[0], noWorkers );

        controller.waitForWorkers();
        long t1 = System.currentTimeMillis();
        System.out.println("sum = " + controller.getSum() );
        System.out.println("time = " + (t1-t0) );
    }
}
