package control;

import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
import javafx.scene.control.TreeView;
import javafx.scene.control.TreeItem;
import javafx.scene.input.MouseEvent;
import javafx.event.ActionEvent;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import java.util.List;
import java.util.ArrayList;
import javafx.stage.*;  
import java.util.ConcurrentModificationException;
import javafx.application.Platform;

import graph.*;

/**
 * Die Klasse Hilfefenster stellt ein Hilfefenster für die Simulation eines
 * Algorithmus bereit.
 *
 * @author Thomas Schaller
 * @version v6.7 (9.12.2020)
 */

public class Hilfefenster extends Stage implements Hilfe{

    @FXML
    private TreeView<String> tvAblauf;

    private List<TreeItem<String>> stufen;
    private List<List<String>> zustaende;
    private TreeItem<String> last;
    private GraphPlotter gp;
    private List<String> aktuell;
    private boolean reviewAllowed;

    public void initialize() {
        loescheAlles();
        zustaende = new ArrayList<List<String>>();
        aktuell = null;
        reviewAllowed = false;
        tvAblauf.getSelectionModel().selectedIndexProperty().addListener((obs,oldValue, newValue)->showState());
    }

    public void setGraphPlotter(GraphPlotter gp) {
        this.gp = gp;
    }

    public void loescheAlles() {
        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    stufen = new ArrayList<TreeItem<String>>();
                    zustaende = new ArrayList<List<String>>();
                    TreeItem<String> root =  new TreeItem<String>("Algorithmus");
                    root.setExpanded(true);
                    last = root;
                    tvAblauf.setRoot(root);
                    tvAblauf.setShowRoot(false);
                    stufen.add(root);                    
                }
            });

    }

    public void append(String text) {
        List<String> status = gp.getGraph().getStatus();
        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    last = new TreeItem<String>(text);
                    stufen.get(stufen.size()-1).getChildren().add(last);
                    zustaende.add(status);
                }
            });

    }

    public void indentMore() {
        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    if(stufen.size() == 1) { // Hauptknoten
                        TreeItem parent = stufen.get(0);
                        List<TreeItem> children = parent.getChildren();
                        for(int i=children.size()-1; i >= 0; i--) {
                            TreeItem t = children.get(i);
                            if(t.isExpanded()) {
                                t.setExpanded(false);
                                break;
                            }
                        }
                    }
                    stufen.add(last);
                    last.setExpanded(true);
                    last.expandedProperty().addListener((b, o, n) -> showState());
                }
            });

    }

    public void indentLess() {
        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    if(stufen.size() > 1) stufen.remove(stufen.size()-1);
                }
            });
    }

    public void setReviewAllowed(boolean a) {
        this.reviewAllowed = a;
        if(!reviewAllowed) tvAblauf.getSelectionModel().clearSelection();
    }

    public void showState() {
        Platform.runLater(new Runnable() {
                @Override
                public void run() {
                    if(reviewAllowed && tvAblauf.getSelectionModel().getSelectedIndex()>=0) {
                        TreeItem s = tvAblauf.getSelectionModel().getSelectedItem();
                        if(!s.isExpanded()) { // suche das letzte Kind
                            while(s.getChildren().size()>0){
                                List<TreeItem> c = s.getChildren();
                                s = c.get(c.size()-1);
                            }
                        }
                        gp.getGraph().setStatus(zustaende.get(calculateIndex(tvAblauf.getRoot(), s ,0)-1));
                        gp.updateImage();
                    }
                }
            });

    }

    private int calculateIndex(TreeItem t, TreeItem search, int nr) {
        if(t == search) return nr;
        nr++;
        List<TreeItem> children = t.getChildren();  
        for(TreeItem c : children) {
            int i = calculateIndex(c, search, nr);
            if(i>0) return i;
            nr = -i;
        }
        return -nr;
    }

    @FXML
    void bCopyClicked(ActionEvent event) {
        final Clipboard clipboard = Clipboard.getSystemClipboard();
        final ClipboardContent content = new ClipboardContent();
        String s = "";
        for(Object c : tvAblauf.getRoot().getChildren()) {
            if(c instanceof TreeItem) {
                s += generateClipboardContent((TreeItem) c, "");
            }
        }

        content.putString(s);

        clipboard.setContent(content);
    }

    private String generateClipboardContent(TreeItem t, String tab) {
        String s = tab+t.getValue();
        for(Object c : t.getChildren()) {
            if(c instanceof TreeItem) {
                s += generateClipboardContent((TreeItem) c, tab+"  ");
            }
        }
        return s;
    }

}
