package view.panels;

import model.Line;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.util.ShapeUtilities;

import javax.swing.*;
import java.awt.*;
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: 29.05.2017.
 */
public class PlotPanel extends JPanel {

    private JFreeChart chart;
    private ChartPanel panel;
    private XYSeriesCollection datapoints;
    private XYSeries series;
    private Double min;
    private Double max;
    private XYPlot xyPlot;
    private int seriesCount;

    private XYLineAndShapeRenderer renderer;
    private Shape diamond;

    public PlotPanel() {
        super();
        this.setLayout(new BorderLayout());
        seriesCount = 1;
    }

    public void createPlot(LinkedList<Line> points) {
        if (!points.isEmpty()) {
            try {
                Thread thread = new Thread(() -> convertData(points));
                thread.start();
                thread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //createScatterPlot
        chart = ChartFactory.createXYLineChart("",
                "X", "Y", datapoints, PlotOrientation.VERTICAL, true, true, false);
        diamond = ShapeUtilities.createDiamond(2f);
        chart.setBorderVisible(false);
        chart.setAntiAlias(true);
        chart.getPlot().setBackgroundPaint(Color.WHITE);
        chart.setBorderVisible(false);


        xyPlot = (XYPlot) chart.getPlot();
        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);


        renderer = (XYLineAndShapeRenderer) xyPlot.getRenderer();
        renderer.setSeriesLinesVisible(0, false);
        renderer.setSeriesShapesVisible(0, true);
        renderer.setSeriesLinesVisible(1, true);
        renderer.setSeriesLinesVisible(1, true);
        renderer.setSeriesPaint(0, Color.blue);
        renderer.setSeriesShape(0, diamond);
        renderer.setBaseSeriesVisible(true);


        xyPlot.setDomainCrosshairVisible(true);
        xyPlot.setRangeCrosshairVisible(true);

        panel = new ChartPanel(chart);
        panel.setMouseZoomable(false);
        this.add(panel, BorderLayout.CENTER);
    }

    public void clear() {
        if (datapoints != null)
            datapoints.removeAllSeries();
    }

    public void addLineToPlot(double m, double b, Paint color, String name) {

        XYSeries linesA = new XYSeries(name);
        linesA.add(min.doubleValue(), min * m + b);
        linesA.add(max.doubleValue(), max * m + b);

        datapoints.addSeries(linesA);

        renderer.setSeriesPaint(seriesCount, color);
        renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f));
        renderer.setBaseSeriesVisible(true);
        renderer.setSeriesLinesVisible(seriesCount, true);
        seriesCount++;

    }


    public void addLineToPlot(double m, double b, String name) {


        XYSeries linesA = new XYSeries(name);
        linesA.add(min.doubleValue(), min * m + b);
        linesA.add(max.doubleValue(), max * m + b);

        datapoints.addSeries(linesA);
        seriesCount = xyPlot.getSeriesCount();
        renderer.setSeriesPaint(seriesCount, Color.red);
        renderer.setSeriesStroke(seriesCount, new BasicStroke(2.0f));
        renderer.setBaseSeriesVisible(true);
        renderer.setSeriesLinesVisible(seriesCount, true);
    }

    private void convertData(LinkedList<Line> points) {
        datapoints = new XYSeriesCollection();
        ArrayList<Double> coordinates = new ArrayList<>();
        series = new XYSeries("points");
        for (Line p : points) {
            series.add(p.getM().doubleValue(), p.getB().doubleValue() * (-1));
            coordinates.add(p.getM());

        }
        this.max = series.getMaxX();
        this.min = series.getMinX();
        datapoints.addSeries(series);
    }


}

