package presenter.algorithms.naiv;

import model.Line;
import presenter.algorithms.Algorithm;
import presenter.algorithms.util.FastElementSelector;

import java.util.ArrayList;
import java.util.LinkedList;

/**
 * Implementierung verschiedener Algorithmen zur Berechnung von Ausgleichsgeraden.
 *
 * @Author: Armin Wolf
 * @Email: a_wolf28@uni-muenster.de
 * @Date: 15.09.2017.
 */
public class NaivTheilSenEstimator implements Algorithm {


    private LinkedList<Line> lines;
    private Double slope;
    private Double yInterception;

    public NaivTheilSenEstimator(LinkedList<Line> lines) {
        this.lines = lines;
        this.slope = 0d;
        this.yInterception = 0d;
    }


    @Override
    public void run() {
        ArrayList<Double> slopesList = new ArrayList<>();
        int cnt = 0;
        for (int i = 0; i < lines.size(); i++) {
            double x = lines.get(i).getM();
            double y = lines.get(i).getB();

            for (int j = i + 1; j < lines.size(); j++) {
                if (x != lines.get(j).getM()) { // x must be different, otherwise slope becomes infinite
                    Double slope = (lines.get(j).getB() - y) / (lines.get(j).getM() - x);
                    slopesList.add(slope);
                    ++cnt;
                }
            }
        }


        ArrayList<Double> list1 = new ArrayList<>();
        ArrayList<Double> list2 = new ArrayList<>();
        for (int i=0;i<lines.size();i++){
            list1.add(lines.get(i).getM());
            list2.add(lines.get(i).getB());
        }
        Double median1 = FastElementSelector.randomizedSelect(list1, list1.size()/2);
        Double median2 = FastElementSelector.randomizedSelect(list2, list2.size()/2);
        slope = FastElementSelector.randomizedSelect(slopesList, slopesList.size()/2);
        yInterception = median2 - slope * median1;
        System.out.printf("Naiv TS: %6.2f * x + %6.3f\n",slope, yInterception);
    }

    @Override
    public void getResult() {

    }


    public Double getM() {
        return slope * -1;
    }

    public Double getB() {
        return yInterception * -1;
    }
}
