package scopeTest;

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.PointLight;
import javafx.scene.Scene;
import javafx.scene.SceneAntialiasing;
import javafx.scene.SubScene;
import javafx.scene.control.Label;
import javafx.scene.control.ListView;
import javafx.scene.control.RadioButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Sphere;
import javafx.stage.Stage;

public class ScopeTest extends Application {

    double size = 30;
    Sphere sphereRed = new Sphere(size);
    Sphere sphereGreen = new Sphere(size);
    Sphere sphereBlue = new Sphere(size);
    Sphere sphereYellow = new Sphere(size);

    Group redGreen = new Group(sphereRed, sphereGreen);
    Group blueYellow = new Group(sphereBlue, sphereYellow);
    Group root = new Group(redGreen, blueYellow);

    PointLight pointLight = new PointLight();

    @Override
    public void start(Stage stage) throws Exception {
        sphereRed.setId("Red");
        sphereGreen.setId("Green");
        sphereBlue.setId("Blue");
        sphereYellow.setId("Yellow");
        redGreen.setId("Red+Green");
        blueYellow.setId("Blue+Yellow");
        root.setId("All");

        sphereRed.setTranslateX(-size * 5);
        sphereGreen.setTranslateX(-size * 2);
        sphereBlue.setTranslateX(size * 2);
        sphereYellow.setTranslateX(size * 5);

        sphereRed.setMaterial(new PhongMaterial(Color.RED));
        sphereGreen.setMaterial(new PhongMaterial(Color.LIME));
        sphereBlue.setMaterial(new PhongMaterial(Color.BLUE));
        sphereYellow.setMaterial(new PhongMaterial(Color.YELLOW));

        root.setTranslateX(300);
        root.setTranslateY(200);

        pointLight.setTranslateZ(-500);
        root.getChildren().add(pointLight);

        SubScene subScene = new SubScene(root, 600, 400, true, SceneAntialiasing.BALANCED);
        subScene.setFill(Color.TEAL);
        VBox vBox = new VBox(subScene, createControls());
        Scene scene = new Scene(vBox);
        stage.setScene(scene);
        stage.show();
    }

    private Pane createControls() {
        var scopeNames = FXCollections.<String>observableArrayList();
        setUpLists(pointLight.getScope(), scopeNames);
        var scopeList = new ListView<>(scopeNames);
        scopeList.setPrefHeight(150);

        var excludeNames = FXCollections.<String>observableArrayList();
        setUpLists(pointLight.getExclusionScope(), excludeNames);
        var excludeList = new ListView<>(excludeNames);
        excludeList.setPrefHeight(150);
        
        var lists = new VBox(5, new Label("Scoped"), scopeList, new Label("Excluded"), excludeList);

        var toggles = new VBox(5,
                createToggles(sphereRed),
                createToggles(sphereGreen),
                createToggles(sphereBlue),
                createToggles(sphereYellow),
        
                createToggles(redGreen),
                createToggles(blueYellow),
                createToggles(root));

        return new HBox(60, toggles, lists);
    }

    private void setUpLists(ObservableList<Node> lightList, ObservableList<String> nameList) {
        lightList.addListener((ListChangeListener<? super Node>) c -> {
            while (c.next()) {
                c.getRemoved().forEach(n -> nameList.remove(n.getId()));
                c.getAddedSubList().forEach(n -> nameList.add(n.getId()));
            }
        });
    }

    private Pane createToggles(Node node) {
        var none = new RadioButton("none");
        none.setSelected(true);
        none.setOnAction(a -> {
            System.out.println("\n---- none " + node.getId());
            pointLight.getScope().remove(node);
            pointLight.getExclusionScope().remove(node);
        });

        var scoped = new RadioButton("scoped");
        scoped.setOnAction(a -> {
            System.out.println("\n---- scope " + node.getId());
            pointLight.getScope().add(node);
        });

        var excluded = new RadioButton("excluded");
        excluded.setOnAction(a -> {
            System.out.println("\n---- exclude " + node.getId());
            pointLight.getExclusionScope().add(node);
        });

        var tg = new ToggleGroup();
        tg.getToggles().addAll(none, scoped, excluded);
        var vBox = new VBox(2, none, scoped, excluded);
        return new HBox(5, new Label(node.getId()), vBox);
    }

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