/*
 * Script.java
 *
 * Created on May 23, 2006, 12:26 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package cz.pcland.scripting;
import cz.pcland.ga.GAConfiguration;
import cz.pcland.ga.crossover.CrossoverOpearator;
import cz.pcland.ga.fitness.Evaluator;
import cz.pcland.ga.selection.RandomSelection;
import cz.pcland.ga.selection.RankSelection;
import cz.pcland.ga.selection.RouletteSelection2;
import cz.pcland.ga.selection.SelectionOperator;
import cz.pcland.ga.selection.TournamentSelection;
import cz.pcland.knapsack.*;
import cz.pcland.sat.*;
import cz.pcland.tsp.*;
import java.util.*;
import javax.swing.*;
import cz.pcland.functions.*;
import cz.pcland.io.*;
import cz.pcland.gavisualization.*;
import cz.pcland.ga.*;
import cz.pcland.functions.syntax.*;

/**
 *
 * @author petr
 */
public class Script {
    public static boolean isTest = false;
    public static String result = "";
    public static String data;
    public static String name;
    public static boolean prepared = false;
    public static Lexan lexan;
    public static BaseProblemPanel problem;
    public static MainApplet3 ma;
    // public static boolean isEndData = false;
    public static String problemData = "";
    public static String selectionParam = "";
    
    public static int fitnessIndex;
    public static int crossoverIndex;
    public static int selectionIndex;
    
    
    /** Creates a new instance of Script */
    public Script(String str) {
    }
    
    
    public static void loadData(String str, MainApplet3 _ma) throws ParseErrorException {
        isTest = true;
        result = "";
        prepared = false;
        data = str;
        ma = _ma;
        lexan = new Lexan(data);
        
    }
    
    
    public static boolean prepared() throws ParseErrorException {
        if(data == null || lexan.isEnd()) {
            System.out.println("no data or end of script");
            isTest = false;
            return false;
        }
        
        if(!prepared) {
            prepared = loadNext();
        }
        
        if(!prepared) isTest = false;
        
        System.out.println("prepared=" + prepared);
        return prepared;
    }
    
    public static void match(char ch) throws ParseErrorException {
        if(lexan.lookAtChar() == ch) {
            lexan.getNextChar();
            System.out.println("matching " + ch);
        }else {
            throw new ParseErrorException("cant match " + ch);
        }
    }
    
    public static boolean loadNext() throws ParseErrorException {
        
        if(lexan.isEnd()) {
            System.out.println("lexan said end");
            return false;
        }
        
        String cmd = lexan.readCommand();
        
        if(cmd.equals("run")) {
            System.out.println("run found");
            match('{');
            name = lexan.readQuotes();
            match(',');
            
            problem = getProblem(lexan.readString());
            
            if(problem != null) {
                ma.problemPanel = problem;
                ma.loadProblem();
                
                match('{');
                String tmp = lexan.readTillParenthesis();
                tmp = tmp.trim();
                
                if(!tmp.equalsIgnoreCase("[last]")) {
                    problemData = tmp;
                }
                
                System.out.println("problemdata: " + problemData);
                loadInstance();
                match('}');
                
                ma.inputPopSize.setText(String.valueOf(lexan.readInt()));
                match(',');
                
                ma.inputProbCrossover.setText(String.valueOf(lexan.readDouble()));
                match(',');
                
                ma.inputProbMutation.setText(String.valueOf(lexan.readDouble()));
                match(',');
                
                ma.inputElite.setText(String.valueOf(lexan.readInt()));
                match(',');
                
                String selStr = lexan.readQuotes();
                
                if(lexan.lookAtChar() == '(') {
                    match('(');
                    selectionParam = lexan.readQuotes();
                    match(')');
                }else {
                    selectionParam = "";
                }
                
                ma.selectionObject = getSelection(selStr);
                
                match(',');
                if(ma.selectionObject == null) return false;
                ma.comboReproduction.setSelectedIndex(selectionIndex);
                
                ma.fitnessObject = getFitness(lexan.readQuotes());
                if(ma.fitnessObject == null) return false;
                ma.comboFitness.setSelectedIndex(fitnessIndex);
                match(',');
                
                
                
                ma.crossoverObject = getCrossover(lexan.readQuotes());
                match(',');
                if(ma.crossoverObject == null) return false;
                ma.comboCrossover.setSelectedIndex(crossoverIndex);
                
                
                ma.checkViewDistribution.setSelected(lexan.getBoolean());
                match(',');
                
                ma.chcksetMinFitnessToZero.setSelected(lexan.getBoolean());
                match(',');
                
                ma.inputGASteps.setText(String.valueOf(lexan.readInt()));
                
                match('}');
                System.out.println("Data loaded, OK");
                return true;
            }else {
                System.out.println("cant find problem");
                throw new ParseErrorException("Cant read Problem name");
            }
            
        }
        
        if(cmd == "view") {
            return false;
        }
        
        return false;
    }
    
    public static void loadInstance() {
        if(problem instanceof TSPPanel) {
            TSPInstance instance = new TSPInstance();
            ((Loadable)instance).loadFromString(problemData);
            ((TSPPanel)problem).setInstance(instance);
        }
        
        if(problem instanceof KnapSackPanel) {
            KnapSack kp = new KnapSack(0);
            ((Loadable)kp).loadFromString(problemData);
            ((KnapSackPanel)problem).setKnapSack(kp);
        }
        
        if(problem instanceof SATPanel) {
            System.out.println("Data are SAT data");
            System.out.println(problemData);
            SATInstance instance = new SATInstance();
            ((Loadable)instance).loadFromString(problemData);
            ((SATPanel)problem).SATInstances.add(instance);
            ((SATPanel)problem).updateSATList();
            
        }
    }
    
    public static Evaluator getFitness(String str) {
        for(int i=0;i < problem.getEvaluators().length; i++) {
            if(problem.getEvaluators()[i].toString().equalsIgnoreCase(str)) {
                fitnessIndex = i;
                return problem.getEvaluators()[i];
            }
        }
        return null;
    }
    
    public static CrossoverOpearator getCrossover(String str) {
        for(int i=0;i < problem.getCrossoverOperators().length; i++) {
            if(problem.getCrossoverOperators()[i].toString().equalsIgnoreCase(str)) {
                crossoverIndex = i;
                return problem.getCrossoverOperators()[i];
            }
        }
        return null;
    }
    
    public static BaseProblemPanel getProblem(String str) {
        if(str.equalsIgnoreCase("tsp")) return new TSPPanel(ma);
        if(str.equalsIgnoreCase("ks")) return new KnapSackPanel(ma);
        if(str.equalsIgnoreCase("f")) return new FunctionPanel(ma);
        if(str.equalsIgnoreCase("sat")) return new SATPanel(ma);
        return null;
    }
    
    public static SelectionOperator getSelection(String str) {
        SelectionOperator so = null;
        for(int i=0;i<MainApplet3.selectionMethods.length;i++) {
            if(MainApplet3.selectionMethods[i].toString().equalsIgnoreCase(str)) {
                selectionIndex = i;
                so = MainApplet3.selectionMethods[i];
                break;
            }
        }
        
        if(so != null && so instanceof TournamentSelection) {
            int size = Integer.parseInt(selectionParam);
            ((TournamentSelection)so).setTournamentSize(size);
        }
        
        return so;
    }
    
    
    public static void appendResult(Vector gi, String time) {
        double max = ((GenerationInfo)gi.get(0)).getBestRank();
        int gen = -1;
        for(int i=0;i<gi.size();i++) {
            if ( ((GenerationInfo)gi.get(i)).getBestRank() < max ) {
                gen = ((GenerationInfo)gi.get(i)).getGenNum();
                break;
            }
        }
        
        
        result += "Test name: " + name +  " (" +  ((GenerationInfo)gi.get(0)).getGenNum() + " generations)"  +"\n";
        result += "Best Rank: " + ((GenerationInfo)gi.get(0)).getBestRank() + ", found in " + gen + " step"   + "\n";
        result += "Best Fitness: " + ((GenerationInfo)gi.get(0)).getBestFitness() + "\n";
        result += "AVG Fitness: " + ((GenerationInfo)gi.get(0)).getAvgFitness() + "\n";
        result += "AVG Rank: " + ((GenerationInfo)gi.get(0)).getAvgRank() + "\n";
        result += "Lowest Fitness: " + ((GenerationInfo)gi.get(0)).getLowestFitness() + "\n";
        result += "Lowest Rank: " + ((GenerationInfo)gi.get(0)).getLowestRank() + "\n";
        result += "In Time: " + time + "\n\n";;
        
    }
    
    public static void runNext(){
        
        if(prepared){            
            if(ma != null && problem != null){
                prepared = false;
                ma.configAndRun(true);
                isTest = true;
                System.out.println("running");
            }
        }
    }
    
}
