/*
 * @(#) GA.java 2003/03/22
 * 
 */

import java.util.Properties;
import java.io.*;



/**
 * Genetic algorithm's main loop. Reads algorithm parameters, initializes
 * population, initializes operators, executes loop. Static methods and members
 * in this first  version.
 * 
 * @author Sushil J. Louis
 */
public class GA implements java.io.Serializable {

    /**
     * Location of properties file for GA configuration.
     */
    static String configFileLocation;

    /**
     * Random seed, read from the command line
     */ 
    static long seed;

    /**
     * Main constructs population, initializes population. Then
     * loops for a fixed number of iterations.
     * 
     * @param args command line args. We expect two arguments 1. the name
     * of the properties file that contains GA parameters. 2. a random seed.
     */
    public static void main(String[] args) {
	
	int maxGen;

	decodeCommandLine(args);
	Properties gaProps = loadParameters(configFileLocation);
	maxGen = Integer.parseInt(gaProps.getProperty("Maxgen", "100"));
	GARandom ra = new GARandom(seed);

	Population pop = null;
	App        a   = null;
	try {
	//    a = new App(gaProps);
	    pop = new Population(gaProps, a.getChromLength(), maxGen);
	}catch(Exception e){
	    System.err.println("Cannot construct Population");
	    e.printStackTrace();
	}

	Selector s = new Selector(gaProps, ra);
	Recombiner r = new Recombiner(gaProps, ra);

	Generator generation = new Generator(s, r, a);
	//	Generator generation = new Generator(s, r, a, ra);

	Statistician stat = new Statistician(gaProps);
	Reporter report = new Reporter(gaProps);

	try {
	    pop.initialize(a, stat, report);
	} catch (ApplicationException e){
	    System.err.println("Cannot initialize Population");
	    e.printStackTrace();
	    System.exit(1);
	}


	//	pop.initReport(report, a, stat);
	
	for(int i = 1; i < maxGen; i++){
	    try {
		generation.execute(pop, i);
	    } catch (ApplicationException e){
		System.err.println("Cannot evolve generation " + i);
		e.printStackTrace();
		System.exit(1);
	    }
	    stat.statistics(pop);
	    report.report(pop, a, i);
	}
    }

    /**
     * Loads a property object from given location and returns this 
     * property object;
     *
     * @param location the filename of the property file. Next release, will
     * also handle URLs.
     *
     * @return the properties object
     */

    private static Properties loadParameters(String location){
	Properties prop = new Properties();
	try {
	    FileInputStream fin = new FileInputStream(location);
	    prop.load(fin);
	    fin.close();
	} catch (IOException e){
	    System.err.println("Cannot open file " + location);
	    e.printStackTrace();
	}
	return prop;

    }

    private static void decodeCommandLine(String[] args){

	if(args.length < 2) {
	    configFileLocation = new String("infile");
	    seed = (long) 11111;
	} else if(args.length == 2){
	    configFileLocation = new String(args[0]);
	    seed = Long.parseLong(args[1]);
	} else {
	    System.err.println("Usage: java edu.unr.cs.strike.cigar.GA <filelocation> <random seed>");
	    System.exit(1);
	}

    }

}
