package de.factoryfx.javafx.widget.tree;

import com.google.common.collect.TreeTraverser;
import de.factoryfx.data.Data;
import de.factoryfx.javafx.editor.data.DataEditor;
import de.factoryfx.javafx.widget.CloseAwareWidget;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.SelectionMode;
import javafx.scene.control.SplitPane;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.control.cell.TextFieldTreeCell;

public class DataTreeWidget implements CloseAwareWidget {
    private final Data root;
    private final DataEditor dataEditor;

    public DataTreeWidget(DataEditor dataEditor, Data root) {
        this.dataEditor=dataEditor;
        this.root = root;
    }

    @Override
    public void closeNotifier() {
//        listener.changed(null, null, null);
    }

    @Override
    public Node createContent() {
        SplitPane splitPane = new SplitPane();
        splitPane.getItems().addAll(dataEditor.createContent(),createTree());
        splitPane.setDividerPosition(0,0.75);
        return splitPane;
    }

    private Node createTree(){
        TreeView<Data> tree = new TreeView<>();
        tree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
        tree.setCellFactory(param -> new TextFieldTreeCell<Data>() {
            @Override
            public void updateItem(Data item, boolean empty) {
                super.updateItem(item, empty);
                if (item != null) {
                    this.setText(item.getDisplayText());
                } else {
                    this.setText("");
                }
                //CellUtils.updateItem(this, getConverter(), hbox, getTreeItemGraphic(), textField);
            }

        });
        tree.setRoot(constructTree(root));

        tree.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
            if (newValue!=null){
                dataEditor.edit(newValue.getValue());
            }
        });

        ChangeListener<Data> dataChangeListener = (observable, oldValue, newValue) -> {
            Platform.runLater(() -> {//javafx bug workaround http://stackoverflow.com/questions/26343495/indexoutofboundsexception-while-updating-a-listview-in-javafx
                TreeItem<Data> treeItemRoot = constructTree(root);
                tree.setRoot(treeItemRoot);

                for (TreeItem<Data> item : treeViewTraverser.breadthFirstTraversal(treeItemRoot)) {
                    item.setExpanded(true);
                }
                tree.getSelectionModel().clearSelection();
                for (TreeItem<Data> item : treeViewTraverser.breadthFirstTraversal(treeItemRoot)) {
                    if (item.getValue() == newValue) {
                        tree.getSelectionModel().select(item);
                    }
                }
            });

        };
        dataEditor.editData().addListener(dataChangeListener);
        dataChangeListener.changed(dataEditor.editData(),dataEditor.editData().get(),dataEditor.editData().get());

        ScrollPane scrollPane = new ScrollPane(tree);
        scrollPane.setFitToHeight(true);
        scrollPane.setFitToWidth(true);
        return scrollPane;
    }

    TreeTraverser<TreeItem<Data>> treeViewTraverser = new TreeTraverser<TreeItem<Data>>() {
        @Override
        public Iterable<TreeItem<Data>> children(TreeItem<Data> data) {
            return data.getChildren();
        }
    };

    private TreeItem<Data> constructTree(Data data){
        TreeItem<Data> dataTreeItem = new TreeItem<>(data);
        data.visitChildFactoriesFlat(child -> {
            dataTreeItem.getChildren().add(constructTree(child));
        });
        return dataTreeItem;
    }


}

@@ -326,24 +326,105 @@
 cene.Node;%0D%0A
+import javafx.scene.control.ContextMenu;%0D%0Aimport javafx.scene.control.MenuItem;%0D%0A
 import javaf
@@ -2625,173 +2625,8 @@
 %0D%0A%0D%0A
-                for (TreeItem%3CData%3E item : treeViewTraverser.breadthFirstTraversal(treeItemRoot)) %7B%0D%0A                    item.setExpanded(true);%0D%0A                %7D%0D%0A
     
@@ -3287,32 +3287,449 @@
 ToWidth(true);%0D%0A
+%0D%0A        ContextMenu contextMenu = new ContextMenu();%0D%0A        MenuItem menuItem = new MenuItem(%22expand all%22);%0D%0A        menuItem.setOnAction(event -%3E %7B%0D%0A            for (TreeItem%3CData%3E item : treeViewTraverser.breadthFirstTraversal(tree.getRoot())) %7B%0D%0A                item.setExpanded(true);%0D%0A            %7D%0D%0A        %7D);%0D%0A        contextMenu.getItems().addAll(menuItem);%0D%0A        tree.setContextMenu(contextMenu);%0D%0A%0D%0A
         return s

remove auto expand