package ac.essex.gp.ooechs.novelty2;

import ac.essex.ooechs.imaging.commons.PixelLoader;
import ac.essex.gp.Evolve;
import ac.essex.gp.nodes.imaging.features.dissociateddipoles.DissociatedDipole;
import ac.essex.gp.training.TrainingImage;
import ac.essex.gp.individuals.Individual;
import ac.essex.gp.interfaces.console.ConsoleListener;

import java.io.File;

/**
 * Creates a novelty detector.
 *
 * @author Olly Oechsle, University of Essex, Date: 21-Apr-2008
 * @version 1.0
 */
public class NoveltyDetectorFinder {

/*    public static final String TRUE_TRAINING_DIRECTORY = "/home/ooechs/Desktop/birds/faces/mandarin/training";
    public static final String TRUE_DIRECTORY = "/home/ooechs/Desktop/birds/faces/mandarin";
    public static final String FALSE_DIRECTORY = "/home/ooechs/ecj-training/faces/essex/false1/";
    public static final String UNUSUAL_DIRECTORY = "/home/ooechs/Desktop/birds/faces/toucan";

    public static final int imageWidth = 40;
    public static final int imageHeight = 40;
    public static final int blocksX =4;
    public static final int blocksY = 4;

    */

    public static final String TRUE_TRAINING_DIRECTORY = "/home/ooechs/Desktop/Stuff/pipes/Foreground";
    public static final String TRUE_DIRECTORY = "/home/ooechs/Desktop/Stuff/pipes/Foreground";
    public static final String FALSE_DIRECTORY = "/home/ooechs/Desktop/Stuff/pipes/Background";
    public static final String UNUSUAL_DIRECTORY = "/home/ooechs/Desktop/Stuff/pipes/Unusual";

    public static final int imageWidth = 50;
    public static final int imageHeight = 5;
    public static final int blocksX = 10;
    public static final int blocksY = 1;

    static int numClassifiers;

    public static void main(String[] args) throws Exception {

        ac.essex.gp.ooechs.novelty2.NoveltyDetector n = new NoveltyDetector();

        long start = System.currentTimeMillis();

        FeatureFindingProblemDipole2 problem = new FeatureFindingProblemDipole2();

        problem.load(TRUE_TRAINING_DIRECTORY, FeatureFindingProblem.TRUE);
        problem.load(FALSE_DIRECTORY, FeatureFindingProblem.FALSE);

        int blockX = imageWidth / blocksX;
        int blockY = imageHeight / blocksY;

        PixelLoader.feature1Size = blockX / 2;
        PixelLoader.feature2Size = blockX;

        int numBlocks = blocksX * blocksY;

        int counter = 1;
        numClassifiers = 0;

        for (int by = 0; by < blocksY; by++) {
            for (int bx = 0; bx < blocksX; bx++) {

                int x = (bx * blockX) + (blockX / 2);
                int y = (by * blockY) + (blockY / 2);

                problem.setX(x);
                problem.setY(y);

                DissociatedDipole.left = Math.min(5, x);
                DissociatedDipole.right = Math.min(5, imageWidth-x);
                DissociatedDipole.top = Math.min(5,y);
                DissociatedDipole.bottom = Math.min(5, imageHeight-y);

                System.out.println("Left: " + DissociatedDipole.left);
                System.out.println("Right: " + DissociatedDipole.right);
                System.out.println("Top: " + DissociatedDipole.top);
                System.out.println("Bottom: " + DissociatedDipole.bottom);

                System.out.println("Evolving solution " + counter + " at (" + x + "," + y + ")");


                Evolve e = new Evolve(problem, new ConsoleListener(ConsoleListener.SILENT));

                e.run();

                Individual ind = e.getBestIndividual();
                
                if (ind.getMistakes() < 60) {
                    n.addClassifier(ind, 1, x, y, DissociatedDipole.left, DissociatedDipole.right, DissociatedDipole.top, DissociatedDipole.bottom);
                    System.out.println("Added classifier, hits=" + ind.getHits() + ", mistakes=" + ind.getMistakes());
                    numClassifiers++;
                    test(n);
                } else {
                    System.out.println("Rejected classifier, hits=" + ind.getHits() + ", mistakes=" + ind.getMistakes());
                }

                long time = System.currentTimeMillis() - start;

                System.out.println(time + "ms elapsed.");

                counter++;

            }
        }

        n.save(new File("/home/ooechs/Desktop/pipelinedetector.solution"));

    }

    public static void test(NoveltyDetector d) {

        System.out.println("Testing detector with " + d.classifiers.size() + " classifiers");

        int[] trueOutput = getOutput(d, TRUE_DIRECTORY);
        double totalTrue = total;

        int[] falseOutput = getOutput(d, FALSE_DIRECTORY);
        double totalFalse = total;

        int[] unusualOutput = getOutput(d, UNUSUAL_DIRECTORY);
        double totalUnusual = total;

        System.out.println("Output, True, False, Unusual");
        for (int i = 0; i < d.classifiers.size() + 1; i++) {
            System.out.println(i + ", " + (100*trueOutput[i]/totalTrue) + ", " + 100*falseOutput[i]/totalFalse + ", " + 100*unusualOutput[i]/totalUnusual);
        }

    }

    static int total;

    public static int[] getOutput(NoveltyDetector d, String directoryPath) {

        int[] output = new int[numClassifiers + 1];

        total = 0;

        File directory = new File(directoryPath);
        if (directory.exists() && directory.isDirectory()) {

            File[] files = directory.listFiles();

            for (int i = 0; i < files.length; i++) {
                File imageFile = files[i];

                if (imageFile.isDirectory()) continue;

                try {
                    PixelLoader image = new PixelLoader(imageFile);

                    int result = (int) d.execute(new TrainingImage(image.getBufferedImage()));

                    output[result]++;

                    total++;

                } catch (Exception err) {
                    // don't worry too much
                }
            }

        }

        return output;

    }


}
