package presenter;

import model.LineModel;
import presenter.algorithms.advanced.LeastMedianOfSquaresEstimator;
import presenter.algorithms.advanced.RepeatedMedianEstimator;
import presenter.algorithms.advanced.TheilSenEstimator;
import presenter.evaluation.EvaluateAlgorithms;
import presenter.evaluation.PictureProcessor;
import presenter.generator.DatasetGenerator;
import presenter.io.DataExporter;
import presenter.io.DataImporter;
import presenter.io.EvalResultLatexExport;
import view.MainFrame;

import javax.swing.table.DefaultTableModel;
import java.io.File;


/**
 * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
 *
 * @Author: Armin Wolf
 * @Email: a_wolf28@uni-muenster.de
 * @Date: 28.05.2017.
 */
public class Presenter extends AbstractPresenter{

    /* Threads */
    private Thread tsThread;
    private Thread rmThread;
    private Thread lmsThread;
    private Thread importThread;
    private Thread importPictureThread;
    private Thread exportThread;
    private Thread exportResultThread;
    private Thread generatorThread;
    private Thread evalThread;

    public Presenter(LineModel model, MainFrame view) {
        super(model, view);
    }


    public void visualizeDualLines() {
        getView().createDualityDialog();
    }

    /***************************************************************************************************************************
     *                                          Ausführung der Algorithmen
     ***************************************************************************************************************************/
    public void calculateLMS(String[] input) {
        if (input[0] != null && input[1] != null) {
            if (lmsThread == null || !lmsThread.isAlive()) {
                lmsThread = new Thread(() -> {
                    Double constant = Double.parseDouble(input[0]);
                    Double error = Double.parseDouble(input[1]);
                    LeastMedianOfSquaresEstimator lms = new LeastMedianOfSquaresEstimator(getModel().getLines(), getModel().getNodes(), this);
                    lms.setConstant(constant);
                    lms.setQuantileError(error);
                    lms.addObserver(this);
                    lms.run();
                    lms.getResult();
                });
                lmsThread.start();
                try {
                    lmsThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void calculateRM(String input) {
        if (input != null) {
            if (rmThread == null || !rmThread.isAlive()) {
                rmThread = new Thread(() -> {
                    RepeatedMedianEstimator rm = new RepeatedMedianEstimator(getModel().getLines(), this);
                    Double parameter = Double.parseDouble(input);
                    rm.setBeta(parameter);
                    rm.addObserver(this);
                    rm.run();
                    rm.getResult();
                });
                rmThread.start();
                try {
                    rmThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void calculateTS(String input) {
        if (input != null) {
            if (tsThread == null || !tsThread.isAlive()) {
                tsThread = new Thread(() -> {
                    TheilSenEstimator ts = new TheilSenEstimator(getModel().getLines(), getModel().getNodes(), this);
                    ts.addObserver(this);
                    ts.run();
                    ts.getResult();
                });
                tsThread.start();
                try {
                    tsThread.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /***************************************************************************************************************************
     *                                          Hilfsmethoden
     ***************************************************************************************************************************/

    public void startImport(File file) {
        if (importThread == null || !importThread.isAlive()) {
            importThread = new Thread(() -> {
                DataImporter importer = new DataImporter(file, this);
                importer.addObserver(this);
                importer.run();
            });
            importThread.start();
            try {
                importThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void startPictureDataImport(File file){
        if (importPictureThread == null || !importPictureThread.isAlive()) {
            importPictureThread = new Thread(() -> {
                PictureProcessor pictureProcessor = new PictureProcessor(this, file);
                pictureProcessor.addObserver(this);
                pictureProcessor.run();
            });
            importPictureThread.start();
            try {
                importPictureThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }



    }

    public void startExport(File file) {
        if (exportThread == null || !exportThread.isAlive()) {
            exportThread = new Thread(() -> {
                DataExporter exporter = new DataExporter(getModel(), file);
                exporter.addObserver(this);
                exporter.export();
            });
            exportThread.start();
            try {
                exportThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void startResultExport(DefaultTableModel model, File file) {
        if (exportResultThread == null || !exportResultThread.isAlive()) {
            exportResultThread = new Thread(() -> {
                EvalResultLatexExport exporter = new EvalResultLatexExport(model, file);
                exporter.writeFile();
            });
            exportResultThread.start();
            try {
                exportResultThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void generateDataset() {
        if (generatorThread == null || !generatorThread.isAlive()) {
            generatorThread = new Thread(() -> {
                DatasetGenerator generator = new DatasetGenerator();
                generator.addObserver(this);
                getModel().setLines(generator.generateCircle(100));
                calculateIntersections();
                getView().enableFunctionality();
            });
            generatorThread.start();
            try {
                generatorThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void startEvaluation(int typ, int n, int alg, String datasettyp) {

        if (evalThread == null || !evalThread.isAlive()) {
            evalThread = new Thread(() -> {
                try {
                    setEval(new EvaluateAlgorithms(typ, n, alg, datasettyp));
                    getEval().addObserver(this);
                    getEval().run();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            evalThread.start();
        }
    }
}
