import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Orientation;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class ScrollPaneControlsSample extends Application {

    public static void main(String[] args) {
        launch(args);
    }

    private static void buttonPressed(int index) {
        System.out.printf("Button Pressed: %d%n", index);
    }

    @Override
    public void start(Stage primaryStage) {

        primaryStage.setTitle("Scroll Pane Example!");

        int N = 3;

        List<Node> nodes = new ArrayList<>();
        int currentIndex = 0;

        for (int i = 0; i < N; i++) {

            addNode(currentIndex++, nodes, (index) -> {
                Button button = new Button();
                button.setText("Button: " + index);
                button.setOnAction((e) -> buttonPressed(index));
                return button;
            });

            addNode(currentIndex++, nodes, (index) -> {
                ToggleButton toggleButton = new ToggleButton();
                toggleButton.setText("ToggleButton: " + index);
                toggleButton.setOnAction((e) -> System.out.printf("ToggleButton pressed: %d%n", index));
                return toggleButton;
            });

            addNode(currentIndex++, nodes, (index) -> {
                CheckBox checkBox = new CheckBox("Checkbox: " + index);
                checkBox.selectedProperty().addListener((ov, o, n) -> {
                    System.out.printf("CheckBox is clicked: %d%n", index);
                });
                return checkBox;
            });

            addNode(currentIndex++, nodes, (index) -> {
                TextField textField = new TextField("TextField: " + index);
                textField.setOnAction((e) -> {
                    System.out.printf("TextField is clicked: %d%n", index);
                });
                return textField;
            });

            addNode(currentIndex++, nodes, (index) -> {
                ComboBox comboBox = new ComboBox();

                comboBox.getItems().add("ComboBox " + index + ", 1");
                comboBox.getItems().add("ComboBox " + index + ", 2");
                comboBox.getItems().add("ComboBox " + index + ", 3");
                comboBox.setValue(comboBox.getItems().get(0));

                comboBox.setOnAction((e) -> {
                    int selectedIndex = comboBox.getSelectionModel().getSelectedIndex();
                    System.out.printf("Combo Box is selected: %d-%d%n", index, selectedIndex + 1);
                });

                return comboBox;
            });

            addNode(currentIndex++, nodes, (index) -> {
                ChoiceBox choiceBox = new ChoiceBox();
                choiceBox.getItems().add("ChoiceBox " + index + ", 1");
                choiceBox.getItems().add("ChoiceBox " + index + ", 2");
                choiceBox.getItems().add("ChoiceBox " + index + ", 3");
                choiceBox.setValue(choiceBox.getItems().get(0));

                choiceBox.setOnAction((e) -> {
                    int selectedIndex = choiceBox.getSelectionModel().getSelectedIndex();
                    System.out.printf("Choice Box is selected: %d-%d%n", index, selectedIndex + 1);
                });

                return choiceBox;
            });

            addNode(currentIndex++, nodes, (index) -> {
                ColorPicker colorPicker = new ColorPicker();
                colorPicker.setOnAction(e -> {
                    System.out.printf("ColorPicker color: %s%n", colorPicker.getValue());
                });

                return colorPicker;
            });

            addNode(currentIndex++, nodes, (index) -> {
                DatePicker datePicker = new DatePicker();
                datePicker.setOnAction(e -> {
                    System.out.printf("DatePicker color: %s%n", datePicker.getValue());
                });

                return datePicker;
            });

            final ToggleGroup radioGroup = new ToggleGroup();

            addNode(currentIndex++, nodes, (index) -> {
                RadioButton radioButton = new RadioButton("Up    : " + index);
                radioButton.setOnAction(e -> {
                    System.out.printf("RadioButton Up is clicked: %d%n", index);
                });
                radioButton.setToggleGroup(radioGroup);

                return radioButton;
            });

            addNode(currentIndex++, nodes, (index) -> {
                RadioButton radioButton = new RadioButton("Down: " + index);
                radioButton.setOnAction(e -> {
                    System.out.printf("RadioButton Down is clicked: %d%n", index);
                });
                radioButton.setToggleGroup(radioGroup);

                return radioButton;
            });

            addNode(currentIndex++, nodes, (index) -> {
                Slider slider = new Slider(10, 100, 50);
                slider.setOrientation(Orientation.VERTICAL);
                slider.valueProperty().addListener(new ChangeListener<Number>() {
                    public void changed(ObservableValue<? extends Number> ov,
                                        Number oldVal, Number newVal) {
                        System.out.printf("Slider Vertical: %d, [%2.2f->%2.2f]%n", index, oldVal.floatValue(), newVal.floatValue());
                    }
                });

                return slider;
            });

            addNode(currentIndex++, nodes, (index) -> {
                Slider slider = new Slider(10, 100, 50);
                slider.setOrientation(Orientation.HORIZONTAL);
                slider.valueProperty().addListener(new ChangeListener<Number>() {
                    public void changed(ObservableValue<? extends Number> ov,
                                        Number oldVal, Number newVal) {
                        System.out.printf("Slider Horizontal: %d, [%2.2f->%2.2f]%n", index, oldVal.floatValue(), newVal.floatValue());
                    }
                });

                return slider;
            });
        }

        VBox buttonsPane = new VBox(5, nodes.toArray(new Node[0]));
        ScrollPane scrollPane = new ScrollPane(buttonsPane);

        StackPane root = new StackPane();
        root.getChildren().add(scrollPane);
        root.setStyle("-fx-padding: 10;" +
                "-fx-border-style: solid inside;" +
                "-fx-border-width: 2;" +
                "-fx-border-insets: 5;" +
                "-fx-border-radius: 5;" +
                "-fx-font-size: 38px;" +
                "-fx-border-color: blue;");

        primaryStage.setScene(new Scene(root, 800, 600));
        primaryStage.show();
    }

    private interface NodeFactory {
        Node create(int index);
    }

    private static void addNode(int index, List<Node> nodes, NodeFactory factory) {
        nodes.add(factory.create(index));
    }
}
