package eu.mivrenik.particles.controller;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import eu.mivrenik.particles.io.ExperimentLoader;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.chart.BarChart;
import javafx.scene.chart.LineChart;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.control.Spinner;

/**
 * Demonstration scene controller.
 */
public class DemonstrationController implements Initializable {
    private static final Logger LOG = Logger.getLogger(DemonstrationController.class.getName());

    private NumberFormat timeElapsedFormat = new DecimalFormat("#.##");

    private ExperimentLoader loader;

    @FXML
    private Canvas canvas;
    @FXML
    private Slider timeSlider;
    @FXML
    private Label timeElapsedLabel;
    @FXML
    private Button playbackButton;
    @FXML
    private Spinner<Integer> fpsInput;
    @FXML
    private BarChart<Float, Float> barChart;
    @FXML
    private LineChart<Float, Float> lineChart;

    public DemonstrationController(final String filePath) throws IOException {
        File sourceFile = new File(filePath);
        loader = new ExperimentLoader(sourceFile);
    }

    @Override
    public void initialize(final URL location, final ResourceBundle resources) {
        timeSlider.setMax((double) loader.getStateCount());

        // Time slider value changed listener
        timeSlider.valueProperty().addListener(
                (ov, o, n) -> onTimeSliderValueChanged(o, n));
        // FPS input value changed listener
        fpsInput.valueProperty().addListener(
                (ov, o, n) -> onFpsValueChanged(o, n));
    }

    /**
     * Playback button click callback.
     */
    public void onPlaybackClicked() {
        // TODO Method stub.
        LOG.info("Playback clicked");
    }

    /**
     * Time slider valued changed callback. Registered in
     * {@link #initialize(URL, ResourceBundle)} method.
     *
     * @param oldValue
     *            Value changed from.
     * @param newValue
     *            Value changed to.
     */
    public void onTimeSliderValueChanged(final Number oldValue, final Number newValue) {
        timeElapsedLabel.setText("Time elapsed: " + timeElapsedFormat.format((int) newValue) + "s");
    }

    /**
     * FPS input value changed callback. Registered in
     * {@link #initialize(URL, ResourceBundle)} method.
     *
     * @param oldValue
     *            Value changed from.
     * @param newValue
     *            Value changed to.
     */
    public void onFpsValueChanged(final int oldValue, final int newValue) {
        // TODO Method stub.
        LOG.info("FPS value changed from " + oldValue + " to " + newValue);
    }
}

@@ -282,24 +282,76 @@
 mentLoader;%0A
+import eu.mivrenik.particles.model.ExperimentState;%0A
 import javaf
@@ -363,16 +363,16 @@
 l.FXML;%0A
-
 import j
@@ -1632,16 +1632,61 @@
 eCount()
+ - 1);%0A        timeSlider.setMinorTickCount(1
 );%0A%0A    
@@ -1983,32 +1983,557 @@
 (o, n));%0A    %7D%0A%0A
+    private void setState(final int newValue, boolean setSlider) throws Exception %7B%0A        ExperimentState state = loader.getState(newValue);%0A%0A        double timeElapsed = state.getTime() / 1_000_000.0;%0A        timeElapsedLabel.setText(%22Time elapsed: %22 + timeElapsedFormat.format(timeElapsed) + %22s%22);%0A%0A        redraw(state);%0A%0A        if (setSlider) %7B%0A            timeSlider.setValue((double) newValue);%0A        %7D%0A    %7D%0A%0A    private void redraw(final ExperimentState state) %7B%0A        // TODO: implement canvas redraw%0A    %7D%0A%0A%0A
     /**%0A     * P
@@ -3018,32 +3018,33 @@
 Number newValue)
+ 
  %7B%0A        timeE
@@ -3043,99 +3043,144 @@
    t
-imeElapsedLabel.setText(%22Time elapsed: %22 + timeElapsedFormat.format((int) newValue) + %22s%22);
+ry %7B%0A            setState(newValue.intValue(), false);%0A        %7D catch (Exception e) %7B%0A            LOG.severe(e.getMessage());%0A        %7D
 %0A   

Implement state change via slider