package control;

import imp.*;
import graph.*;

import javafx.fxml.*;
import javafx.scene.control.*;
import javafx.event.*;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.*;
import javafx.scene.Node;
import javafx.scene.text.*;
import javafx.geometry.Pos;
import javafx.stage.*;          // Dateiöffnen / Speichern-Dialog
import java.io.File;  
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

import java.util.List;
import javafx.collections.ObservableList;
import java.util.Optional;

/**
 * Die Klasse EditTabMitController stellt einen Tab inclusive ihres Controllers
 * zur Editierung eines Graphs dar.
 *
 * @author Thomas Schaller
 * @version 03.03.2023 (v7.1)
 * v7.1: Aktualisierung der Anzeige bei Wechsel gewichtet/ungewichtet angepasst
 * v6.9: Context-Menü schließt, wenn an andere Stelle geklickt wird
 */

public class EditTabMitController extends TabMitController {

    public EditTabMitController(Graph graph, GraphOptions options) {
        this.graph = graph;
        this.options = options;

    }

    @FXML
    private CheckBox cbGerichtet;

    @FXML
    private CheckBox cbGewichtet;

    @FXML
    private RadioButton rLeer;

    @FXML
    private ToggleGroup tgKnoten;

    @FXML
    private RadioButton rNummer;

    @FXML
    private RadioButton rWert;

    @FXML
    private CheckBox cbInfotext;

    @FXML
    private Label lBildname;

    @FXML
    private RadioButton rbMatrix;

    @FXML
    private ToggleGroup tgMatrixListe;

    @FXML
    private RadioButton rbListe;

    @FXML
    private Slider sGroesse;

    private FileChooser dateidialog;

    public void initialize() {

        dateidialog = new FileChooser();
        dateidialog.setInitialDirectory(new File("images"));

        options.showEdgeWeights = graph.isGewichtet();
        options.bildAnzeigen = true;
        options.showVertexInfo = true;

        viewer.setGraph(graph,options);
        viewer.setEditable();

        cbGerichtet.setSelected(graph.isGerichtet());
        cbGewichtet.setSelected(graph.isGewichtet());
        cbInfotext.setSelected(options.showVertexInfo);

        tgKnoten.selectToggle(rLeer);
        if(options.showVertexValue) { tgKnoten.selectToggle(rWert); }
        if(options.showVertexText) { tgKnoten.selectToggle(rNummer); }

        cbGerichtet.selectedProperty().addListener((cb, oldValue, newValue) -> setGerichtet(newValue));
        cbGewichtet.selectedProperty().addListener((cb, oldValue, newValue) -> setGewichtet(newValue));
        cbInfotext.selectedProperty().addListener((cb, oldValue, newValue) -> setInfotext(newValue));
        tgKnoten.selectedToggleProperty().addListener((tg, oldValue, newValue) -> setKnotenTyp(newValue));
        if(options.saveAsMatrix) 
            tgMatrixListe.selectToggle(rbMatrix);
        else
            tgMatrixListe.selectToggle(rbListe);

        tgMatrixListe.selectedToggleProperty().addListener((tg, oldValue, newValue) -> options.saveAsMatrix = (newValue == rbMatrix));
        lBildname.setText(options.bildDatei);
        super.initialize();

        // this.setOnSelectionChanged(e -> {if(!this.isSelected()) this.getTabPane().getTabs().remove(this);});
        sGroesse.valueProperty().addListener((s,oldValue,newValue) -> sGroesseAendern(newValue));    

    }

    void sGroesseAendern(Number size) {
        options.vertexSize = size.intValue();
        update();
    }

    void setGerichtet(boolean gerichtet) {
        graph.setGerichtet(gerichtet);
        update();
    }

    void setGewichtet(boolean gewichtet) {
        graph.setGewichtet(gewichtet);
        options.showEdgeWeights = gewichtet;
        if(graph.isGewichtet()) {
            options.kanteKurztext = new String[]{"Gewicht"};
            options.kanteLangtext = new String[]{"Gewicht","Markiert","Gelöscht"};
        } else {
            options.kanteKurztext = new String[]{};
            options.kanteLangtext = new String[]{"Markiert","Gelöscht"};
        }
        update();
    }

    void setInfotext(boolean anzeigen) {
        options.showVertexInfo = anzeigen;
        update();
    }    

    void setKnotenTyp(Toggle t) {
        if(t == rWert) { options.showVertexValue = true; options.showVertexText = false;}
        if(t == rNummer) { options.showVertexValue = false; options.showVertexText = true;}
        if(t == rLeer) { options.showVertexValue = false; options.showVertexText = false;}

        update();
    }

    @FXML
    void bBildLaden(ActionEvent event) {
        String workingDir = System.getProperty("user.dir");
        File file = dateidialog.showOpenDialog(null);
        if (file != null) {
            try{
                Files.copy( file.toPath(), (new File(workingDir+"\\images\\"+file.getName())).toPath(), StandardCopyOption.REPLACE_EXISTING);
                options.bildDatei = file.getName();
                lBildname.setText(options.bildDatei);
                update();
            } catch( Exception e) {
                System.out.println("Fehler beim Kopieren des Bildes");
            }
        }
    }

    @FXML
    void bBildLoeschen(ActionEvent event) {
        options.bildDatei = "";
        lBildname.setText(options.bildDatei);
        update();
    }

    @FXML
    void bDistanzenBestimmen(ActionEvent event) {
        for(Kante k: graph.getAlleKanten()) {
            Knoten s = k.getStart();
            Knoten z = k.getZiel();
            k.setGewicht(Math.round(Math.sqrt((s.getX()-z.getX())*(s.getX()-z.getX())+
                        (s.getY()-z.getY())*(s.getY()-z.getY()))));
        }
        update();
    }

    @FXML
    void graphClicked(MouseEvent event) { // MousePressed-Event
        viewer.mouseClicked(event);
        viewer.mouseDown(event);
        if((viewer.getSelectedKnoten() != null || viewer.getSelectedKante() != null) && event.isSecondaryButtonDown()) { // Contextmenu
            ContextMenu contextMenu = new ContextMenu();
            MenuItem item1 = new MenuItem("Löschen");
            item1.setOnAction(e -> this.mLoesche());
            MenuItem item2 = new MenuItem("Gewicht ändern...");
            item2.setOnAction(e -> this.mWertAendern());
            MenuItem item3 = new MenuItem("Infotext ändern...");
            item3.setOnAction(e -> this.mInfotextAendern());

            // Add MenuItem to ContextMenu
            contextMenu.getItems().clear();
            contextMenu.getItems().add(item1);

            if(viewer.getSelectedKante()!=null && graph.isGewichtet())
                contextMenu.getItems().add(item2);
            if (viewer.getSelectedKnoten() != null)    
                contextMenu.getItems().add( item3 );

            getViewer().setContextMenu(contextMenu);
            //contextMenu.show(viewer, event.getScreenX(), event.getScreenY());
        }
    }

    public void mLoesche() {
        viewer.setContextMenu(null);
        if(viewer.getSelectedKnoten() != null) {
            graph.entferneKnoten(viewer.getSelectedKnoten());
            update();
        }
        if(viewer.getSelectedKante() != null) {
            graph.entferneKante(viewer.getSelectedKante());
            update();
        }
    }

    public void mWertAendern() {
        viewer.setContextMenu(null);

        Knoten k = viewer.getSelectedKnoten();
        Kante ka = viewer.getSelectedKante();
        if(k != null || ka !=null) {
            double v;
            if(k != null) v = k.getDoubleWert(); 
            else v = ka.getGewicht();
            TextInputDialog dialog = new TextInputDialog(""+v);
            dialog.setHeaderText(null);
            dialog.setTitle("Wert ändern");
            dialog.setContentText("Bitte geben Sie den neuen Wert ein:");

            Optional<String> result = dialog.showAndWait();
            if (result.isPresent()){
                try{
                    v = Double.parseDouble(result.get());
                    if(k != null) k.setWert(v);          
                    else ka.setGewicht(v);
                    update();
                } catch (Exception e) {
                    System.out.println("Keine Zahl eingegeben");
                }
            }
        }
    }

    public void mInfotextAendern() {
        viewer.setContextMenu(null);

        Knoten k = viewer.getSelectedKnoten();
        if(k != null ) {
            TextInputDialog dialog = new TextInputDialog(k.getInfotext());
            dialog.setHeaderText(null);
            dialog.setTitle("Infotext ändern");
            dialog.setContentText("Bitte geben Sie den Infotext ein:");

            Optional<String> result = dialog.showAndWait();
            if (result.isPresent()){
                String t = result.get();
                t.replaceAll(",","");
                k.setInfotext(t);          
                update();
            }
        }
    }

}
