package ac.essex.gp.util;

import ac.essex.gp.Evolve;
import ac.essex.gp.interfaces.GraphicalInterface;
import ac.essex.gp.interfaces.GPInterface;
import ac.essex.gp.problems.Problem;
import ac.essex.gp.params.GPParams;

import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.ActionListener;

/**
 * Sets up parameters for GP
 *
 * @author Olly Oechsle, University of Essex, Date: 24-Apr-2007
 * @version 1.0
 */
public class GPStartDialog extends JDialog implements ActionListener {

    protected JTextField populationSize, generations;
    protected JTextField tournamentSize, breedSize;
    protected JTextField crossoverRate, mutationRate, ERCMutationRate, ERCJitterRate;
    protected JCheckBox autoRangeTyping;
    protected JCheckBox optimisation;
    protected JTextField treeSize, eliteCount;
    protected JButton ok, cancel, reset;


    private Problem p;
    private GPInterface gpinterface;
    private GPParams params;

    public GPStartDialog(Problem p, GPInterface gpinterface) {

        // the evolve object calls the problem's init params function which we need to initialise the form
        // we won't run the evolve at this time though
        Evolve e = new Evolve(p, new GPParams(), gpinterface);
        this.params = e.getParams();
        this.gpinterface = gpinterface;
        this.p = p;

        Container c = getContentPane();

        Border loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);

        JPanel basicParameters = new JPanel(new GridLayout(4, 2));
        basicParameters.setBorder(BorderFactory.createTitledBorder(loweredetched, "Basic Parameters"));

        populationSize = new JTextField(String.valueOf(params.getPopulationSize()));
        basicParameters.add(new JLabel("Population Size"));
        basicParameters.add(populationSize);

        generations = new JTextField(String.valueOf(params.getGenerations()));
        basicParameters.add(new JLabel("Generations"));
        basicParameters.add(generations);

        tournamentSize = new JTextField(String.valueOf(params.getTournamentSizePercentage()));
        basicParameters.add(new JLabel("Tournament Size"));
        basicParameters.add(tournamentSize);

        breedSize = new JTextField(String.valueOf(params.getBreedSizePercentage()));
        basicParameters.add(new JLabel("Breed Size"));
        basicParameters.add(breedSize);

        JPanel geneticOperators = new JPanel(new GridLayout(4, 2));
        geneticOperators.setBorder(BorderFactory.createTitledBorder(loweredetched, "Genetic Operators"));

        crossoverRate = new JTextField(String.valueOf(params.getCrossoverProbability()));
        geneticOperators.add(new JLabel("Crossover Rate"));
        geneticOperators.add(crossoverRate);

        mutationRate = new JTextField(String.valueOf(params.getPointMutationProbability()));
        geneticOperators.add(new JLabel("Point Mutation Rate"));
        geneticOperators.add(mutationRate);

        ERCMutationRate = new JTextField(String.valueOf(params.getERCmutateProbability()));
        geneticOperators.add(new JLabel("ERC Mutation Rate"));
        geneticOperators.add(ERCMutationRate);

        ERCJitterRate = new JTextField(String.valueOf(params.getERCjitterProbability()));
        geneticOperators.add(new JLabel("ERC Jitter Rate"));
        geneticOperators.add(ERCJitterRate);

        JPanel options = new JPanel(new GridLayout(4, 2));
        options.setBorder(BorderFactory.createTitledBorder(loweredetched, "Options"));

        optimisation = new JCheckBox("On", params.isOptimisationEnabled());
        options.add(new JLabel("Tree Optimisation"));
        options.add(optimisation);

        autoRangeTyping = new JCheckBox("On", params.isAutomaticRangeTypingEnabled());
        options.add(new JLabel("Auto Range Typing"));
        options.add(autoRangeTyping);

        treeSize = new JTextField(String.valueOf(params.getMaxTreeSize()));
        options.add(new JLabel("Max Tree Size"));
        options.add(treeSize);

        eliteCount = new JTextField(String.valueOf(params.getEliteCount()));
        options.add(new JLabel("Elite Count"));
        options.add(eliteCount);


        JPanel form = new JPanel(new GridLayout(3, 1));
        form.add(basicParameters);
        form.add(geneticOperators);
        form.add(options);

        c.add(form, BorderLayout.CENTER);

        JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));

        ok = new JButton("Start");
        ok.addActionListener(this);
        cancel = new JButton("Cancel");
        cancel.addActionListener(this);
        reset = new JButton("Reset");
        reset.addActionListener(this);

        buttons.add(reset);
        buttons.add(cancel);
        buttons.add(ok);

        c.add(buttons, BorderLayout.SOUTH);

        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });

        setTitle("GP Parameters");
        setSize(380, 480);
        setLocation(200, 200);
        setVisible(true);

    }

    public void actionPerformed(ActionEvent e) {

        if (e.getSource() == ok) onOK();
        if (e.getSource() == cancel) onCancel();
        if (e.getSource() == reset) onReset();

    }

    public void onOK() {

        try {

            Evolve e = new Evolve(p, params, gpinterface);

            params.setPopulationSize(Integer.parseInt(populationSize.getText()));
            params.setGenerations(Integer.parseInt(generations.getText()));
            params.setTournamentSizePercentage(Double.parseDouble(tournamentSize.getText()));
            params.setBreedSizePercentage(Double.parseDouble(breedSize.getText()));

            params.setCrossoverProbability(Double.parseDouble(crossoverRate.getText()));
            params.setPointMutationProbability(Double.parseDouble(mutationRate.getText()));
            params.setERCmutateProbability(Double.parseDouble(ERCMutationRate.getText()));
            params.setERCjitterProbability(Double.parseDouble(ERCJitterRate.getText()));

            params.setOptimisationEnabled(optimisation.isSelected());
            params.setAutomaticRangeTypingEnabled(autoRangeTyping.isSelected());
            params.setMaxTreeSize(Integer.parseInt(treeSize.getText()));
            params.setEliteCount(Integer.parseInt(eliteCount.getText()));

            e.start();

        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, e.getMessage());
        }

    }

    public void onCancel() {
        dispose();
    }

    public void onReset() {

        populationSize.setText(String.valueOf(params.getPopulationSize()));
        generations.setText(String.valueOf(params.getGenerations()));
        tournamentSize.setText(String.valueOf(params.getTournamentSizePercentage()));
        breedSize.setText(String.valueOf(params.getBreedSizePercentage()));

        crossoverRate.setText(String.valueOf(params.getCrossoverProbability()));
        mutationRate.setText(String.valueOf(params.getPointMutationProbability()));
        ERCMutationRate.setText(String.valueOf(params.getERCmutateProbability()));
        ERCJitterRate.setText(String.valueOf(params.getERCjitterProbability()));

        optimisation = new JCheckBox("On", params.isOptimisationEnabled());
        autoRangeTyping = new JCheckBox("On", params.isAutomaticRangeTypingEnabled());
        treeSize.setText(String.valueOf(params.getERCmutateProbability()));
        eliteCount.setText(String.valueOf(params.getERCjitterProbability()));

    }

}

