package wcanalysis.charting;

import com.google.common.base.Preconditions;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.knowm.xchart.XChartPanel;
import org.knowm.xchart.XYChart;
import org.knowm.xchart.XYChartBuilder;
import org.knowm.xchart.XYSeries;
import org.knowm.xchart.style.Styler;

import javax.swing.*;
import javax.swing.border.EtchedBorder;

import wcanalysis.fitting.FunctionFitter;

/**
 * @author Kasper Luckow
 */
public class WorstCaseChart {
  public static JFrame createChartPanel(Collection<DataSeries> series) {
    return createFrame(buildBasicChart(series), series);
  }

  public static JFrame createChartPanel(Collection<DataSeries> series, double inputReq,
                                         double resReq) {
    final XYChart chart = buildBasicChart(series);


    // Add lines to the chart for resource and input requirements

    //We can take any series to get max X---supposedly
    DataSeries fst = series.iterator().next();
    double[] xs = fst.getX();
    double maxX = xs[xs.length-1];

    double maxY = -1;
    for(DataSeries o : series) {
      double[] ys = fst.getY();
      if(ys[ys.length - 1] > maxY) {
        maxY = ys[ys.length - 1];
      }
    }

    //add input req line:
    chart.addSeries("Input Requirement", new double[] {inputReq, inputReq}, new double[] {0, maxY});

    //add resource req line:
    chart.addSeries("Resource Requirement",
        new double[] {0, maxX}, new double[] {0, resReq});
    return createFrame(chart, series);
  }

  private static XYChart buildBasicChart(Collection<DataSeries> series) {
    Preconditions.checkNotNull(series);
    Preconditions.checkArgument(!series.isEmpty());

    final XYChart chart = new XYChartBuilder()
        .width(800)
        .height(600)
        .title("Worst Case Prediction Model")
        .xAxisTitle("Input Size")
        .yAxisTitle("Cost")
        .build();

    // Customize Chart
    chart.getStyler().setLegendPosition(Styler.LegendPosition.InsideNW);
    chart.getStyler().setDefaultSeriesRenderStyle(XYSeries.XYSeriesRenderStyle.Line);

    // Add Series
    for(DataSeries s : series) {
      chart.addSeries(s.getSeriesName(), s.getX(), s.getY());
    }
    return chart;
  }

  private static JFrame createFrame(XYChart chart, Collection<DataSeries> series) {

    JPanel panel = new XChartPanel<>(chart);

    final Map<JCheckBox, DataSeries> box2series = new HashMap<>();

    // Item listener enabling toggling of plots
    ItemListener listener = e -> {
      if(e.getItem() instanceof JCheckBox) {
        JCheckBox checkbox = (JCheckBox)e.getItem();
        if(!checkbox.isSelected()) {
          String series1 = box2series.get(checkbox).getSeriesName();
          chart.removeSeries(series1);
        } else {
          DataSeries series1 = box2series.get(checkbox);
          chart.addSeries(series1.getSeriesName(), series1.getX(), series1.getY());
        }
        panel.revalidate();
        panel.repaint();
      }
    };

    // Create and set up the window.
    JFrame frame = new JFrame("Worst Case Prediction Model");
    frame.setLayout(new BorderLayout());
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JPanel checkPanel = new JPanel(new GridLayout(0, 1));
    List<DataSeries> sortedSeries = new ArrayList<>();
    DataSeries rawSeries = null;
    for(DataSeries ds : series) {
      if(ds.getSeriesName().equalsIgnoreCase("raw")) {
        rawSeries = ds;
      } else {
        sortedSeries.add(ds);
      }
    }

    assert rawSeries != null;

    sortedSeries.sort((o1, o2) -> o1.getSeriesName().compareTo(o2.getSeriesName()));

    JPanel rawPanel = new JPanel(new GridLayout(0, 1));
    rawPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(Color
            .BLUE, Color.BLACK),
        rawSeries.getSeriesName()));
    JCheckBox rawCheckbox = new JCheckBox("Toggle");
    rawCheckbox.setSelected(true);
    rawPanel.add(rawCheckbox);
    rawCheckbox.addItemListener(listener);

    box2series.put(rawCheckbox, rawSeries);
    checkPanel.add(rawPanel);

    for(DataSeries ser : sortedSeries) {
      JPanel boxPanel = new JPanel(new GridLayout(0, 1));
      boxPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),
          ser.getSeriesName()));
      JCheckBox checkbox = new JCheckBox("Toggle");
      checkbox.setSelected(true);
      checkbox.addItemListener(listener);
      boxPanel.add(checkbox);
      boxPanel.add(new JLabel("Function: " + ser.getFunction()));
      boxPanel.add(new JLabel("r^2: " + ser.getR2()));
      checkPanel.add(boxPanel);
      box2series.put(checkbox, ser);
    }

    frame.add(checkPanel, BorderLayout.LINE_START);
    frame.add(panel, BorderLayout.CENTER);

    return frame;
  }
}

@@ -847,91 +847,8 @@
 g.*;
-%0Aimport javax.swing.border.EtchedBorder;%0A%0Aimport wcanalysis.fitting.FunctionFitter;
 %0A%0A/*
@@ -1897,17 +1897,22 @@
 uble%5B%5D %7B
-0
+resReq
 , resReq
@@ -2759,16 +2759,26 @@
     
-JPanel p
+XChartPanel chartP
 anel
@@ -3373,25 +3373,30 @@
   %7D%0A        
-p
+chartP
 anel.revalid
@@ -3410,17 +3410,22 @@
         
-p
+chartP
 anel.rep
@@ -4116,39 +4116,37 @@
  JPanel(new 
-Grid
+Border
 Layout(
-0, 1
 ));%0A    rawP
@@ -4343,32 +4343,37 @@
 CheckBox(%22Toggle
+ Plot
 %22);%0A    rawCheck
@@ -4819,16 +4819,21 @@
 (%22Toggle
+ Plot
 %22);%0A    
@@ -5131,29 +5131,189 @@
 %0A    %7D%0A%0A    
-frame
+JPanel controls = new JPanel(new GridLayout(0, 1));%0A    controls.add(new JTextField(%22test%22));%0A%0A    JPanel mainPanel = new JPanel(new GridLayout(0,2));%0A%0A    mainPanel
 .add(checkPa
@@ -5351,19 +5351,28 @@
     
-frame.add(p
+mainPanel.add(chartP
 anel
@@ -5395,16 +5395,68 @@
 ENTER);%0A
+    frame.add(mainPanel);%0A    frame.add(controls);%0A%0A
 %0A    ret

Add some more changes to the xchart based charting functionality