package vismon.plot;

import vismon.data.Indicator;
import vismon.data.Scenario;
import vismon.util.Constants;
import vismon.util.Util;

import javax.swing.*;
import java.awt.*;

public class BoxPlot extends JPanel {

    private Indicator indicator;
    private Scenario scenario;
    private double scenarioMin;
    private double scenarioMax;

    private int x;
    private int y;
    private int w;
    private int h;
    private int lrBorder = 5;
    private int tbBorder = 10;

    public BoxPlot(Indicator indicator) {
        this.indicator = indicator;

        x = lrBorder;
        y = tbBorder;
    }

    public void setScenario(Scenario scenario) {
        this.scenario = scenario;

        scenarioMin = Double.MAX_VALUE;
        scenarioMax = Double.MIN_VALUE;

        for (double v : scenario.getValues(indicator)) {
            if (v < scenarioMin)
                scenarioMin = v;
            if (v > scenarioMax)
                scenarioMax = v;
        }
    }

    @Override
    public void paint(Graphics graphics) {
        w = this.getWidth() - 2 * lrBorder;
        h = this.getHeight() - 2 * tbBorder;

        drawBoxPlot(graphics);
    }

    public void drawBoxPlot(Graphics g) {
        double min = indicator.getMin();
        double max = indicator.getMax();

        double average = scenario.getAverageValue(indicator);
        double median = scenario.getMedianValue(indicator);
        double[] quartiles = scenario.getErrorBar(indicator, 50);

        int minLocal = x + (int) (w * ((scenarioMin-min)/(max-min)));
        int maxLocal = x + (int) (w * ((scenarioMax-min)/(max-min)));
        int averageLocal = x + (int) (w * ((average-min)/(max-min)));
        int medianLocal = x + (int) (w * ((median-min)/(max-min)));
        int quartile1Local = x + (int) (w * ((quartiles[0]-min)/(max-min)));
        int quartile2Local = x + (int) (w * ((quartiles[1]-min)/(max-min)));

        g.setColor(Constants.MAIN_COLOR);
        g.drawRect(quartile1Local, y, (quartile2Local - quartile1Local), h);  // box
        g.drawLine(minLocal, y, minLocal, y + h);                             // min
        g.drawLine(maxLocal, y, maxLocal, y + h);                             // max
        g.drawLine(medianLocal, y, medianLocal, y+h);                         // median
        g.fillOval(averageLocal-2, (y+(int) (h*0.5)) - 2, 4, 4);              // average
        g.drawLine(minLocal, y + (int) (0.5*h), maxLocal, y + (int) (0.5 * h)); // horizontal line
    }

    public String getToolTipText() {
        double average = scenario.getAverageValue(indicator);
        double median = scenario.getMedianValue(indicator);

        return Util.format(scenarioMin, 2) + " [ " +
                       "average = " + Util.format(average, 2) +
                       " ; " +
                       "median = " + Util.format(median, 2) +
                       " ] " + Util.format(scenarioMax, 2);
    }
}
