package fabrik.simulator.pic16f84;

import com.gluonhq.charm.glisten.control.ToggleButtonGroup;

import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;

import javafx.scene.control.*;
import javafx.stage.FileChooser;

import java.io.File;
import java.io.IOException;

import java.io.BufferedReader;

import java.io.FileReader;

import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;

import javafx.stage.Stage;


import java.util.Arrays;
import java.util.Objects;

import static fabrik.simulator.pic16f84.Commands.totalExecutionTime;


public class Controller_Frontend {

    private int [] prog;
    private int [][] read;
    private int [] ind;



    @FXML
    private Button stepintoButton;

    @FXML
    private TableView<Table.DataEntry> tableView;

    @FXML
    private ListView<String> lstContentListView;

    @FXML
    private Label pclLabel;

    @FXML
    private Label statusLabel;

    @FXML
    private Label fsrLabel;

    @FXML
    private Label pclathLabel;

    @FXML
    private Label intconLabel;

    @FXML
    private Button stepButton;

    @FXML
    private Button autoRunGUI;

    @FXML
    private Button stopButton;

    @FXML
    private Label totalExecutionTimeLabel;

    @FXML
    private CheckBox wdtCheck;

    private static volatile boolean isAutoRunActive = true;
    private static volatile boolean isSleeping = false;

    public static void stopRunFromBackend(){
        isAutoRunActive = false;
        if (isSleeping)
            isSleeping = false;
        else
            DataRegister.resetPC();
    }

    public static void sleep() {
        isSleeping = true;
    }

    @FXML
    private void stopAutoRun(ActionEvent event) {
        isAutoRunActive = false;
    }


    @FXML
    private void autoRunGUI(ActionEvent event) {
        if (!isAutoRunActive) {
            isAutoRunActive = true;
        }
        Thread autoRunThread = new Thread(() -> {
            try {
                while (DataRegister.getPC() < prog.length && isAutoRunActive){

                    Platform.runLater(() -> {
                        try {
                            stepintoButton(null);

                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
                    Thread.sleep(50); //Verzögerungszeit in Millisekunden
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        autoRunThread.setDaemon(true);
        autoRunThread.start();


    }


    @FXML
    private void stepintoButton(ActionEvent event) throws IOException {
        if (lstContentListView.getItems().isEmpty()) {
            // Datei ist nicht geladen oder leer
            return;
        }

        // Aktuelle Zeile abrufen
        int currentIndex = ind[DataRegister.getPC()];

        // Scrollen zur ausgewählten Zeile
        lstContentListView.scrollTo(currentIndex -2);

        // Zeile auswählen
        lstContentListView.getSelectionModel().clearSelection();
        lstContentListView.getSelectionModel().select(currentIndex);

        String selectedRowStyle = "-fx-control-inner-background: red;";
        lstContentListView.setCellFactory(column -> new ListCell<String>() {
            @Override
            protected void updateItem(String item, boolean empty) {
                super.updateItem(item, empty);
                setText(item);
                if (getIndex() == currentIndex) {
                    setStyle(selectedRowStyle);
                } else {
                    setStyle("");
                }
            }
        });

        // Befehle ausführen
        if (!isSleeping) {
            Commands.decode(prog[DataRegister.getPC()]);
            DataRegister.increasePC();
        }
        else
            Commands.decode(0);
        WatchdogTimer.testAndTrigger();
        Table.refresh();
        Stage stage = (Stage) stepintoButton.getScene().getWindow();
        CreateWindow.refreshTable(stage);
        IOPorts.refreshUI(getTRISbuttons(), getPORTbuttons());
        totalExecutionTimeLabel.setText("Total Execution Time: " + Commands.getTotalExecutionTime() + " µs");
    }


    @FXML
    protected void selectFileLST(ActionEvent event){
        File selectedFile = chooseLSTFile();
        if(selectedFile != null){
            read = ParseFile.parseDatei(selectedFile.getAbsolutePath());
            prog = read [0];
            ind = read[1];
            System.out.println(Arrays.toString(Arrays.stream(prog).toArray()));
            displayLSTFileContent(selectedFile);
            }
    }

    private File chooseLSTFile() {
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("Open LST File");
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("LST Files", "*.lst", "*.LST"),
                new FileChooser.ExtensionFilter("All Files", "*.*"));
        return fileChooser.showOpenDialog(null);
    }

    @FXML
    private void displayLSTFileContent(File selectedFile) {
        try (BufferedReader reader = new BufferedReader(new FileReader(selectedFile))) {
            ObservableList<String> contentList = FXCollections.observableArrayList();
            String line;
            while ((line = reader.readLine()) != null) {
                contentList.add(line);
            }
            lstContentListView.setItems(contentList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @FXML
    public void toggleWatchdog(ActionEvent actionEvent) {
        if (wdtCheck.isSelected())
            WatchdogTimer.enable();
        else
            WatchdogTimer.disable();
    }

    @FXML
    private ToggleButtonGroup bgTRISA0;
    @FXML
    private ToggleButtonGroup bgTRISA1;
    @FXML
    private ToggleButtonGroup bgTRISA2;
    @FXML
    private ToggleButtonGroup bgTRISA3;
    @FXML
    private ToggleButtonGroup bgTRISA4;
    @FXML
    private ToggleButtonGroup bgTRISB0;
    @FXML
    private ToggleButtonGroup bgTRISB1;
    @FXML
    private ToggleButtonGroup bgTRISB2;
    @FXML
    private ToggleButtonGroup bgTRISB3;
    @FXML
    private ToggleButtonGroup bgTRISB4;
    @FXML
    private ToggleButtonGroup bgTRISB5;
    @FXML
    private ToggleButtonGroup bgTRISB6;
    @FXML
    private ToggleButtonGroup bgTRISB7;
    @FXML
    private ToggleButtonGroup bgPORTA0;
    @FXML
    private ToggleButtonGroup bgPORTA1;
    @FXML
    private ToggleButtonGroup bgPORTA2;
    @FXML
    private ToggleButtonGroup bgPORTA3;
    @FXML
    private ToggleButtonGroup bgPORTA4;
    @FXML
    private ToggleButtonGroup bgPORTB0;
    @FXML
    private ToggleButtonGroup bgPORTB1;
    @FXML
    private ToggleButtonGroup bgPORTB2;
    @FXML
    private ToggleButtonGroup bgPORTB3;
    @FXML
    private ToggleButtonGroup bgPORTB4;
    @FXML
    private ToggleButtonGroup bgPORTB5;
    @FXML
    private ToggleButtonGroup bgPORTB6;
    @FXML
    private ToggleButtonGroup bgPORTB7;

    private static ToggleButtonGroup[] allTRISbuttons;
    private static ToggleButtonGroup[] allPORTbuttons;

    public void initialize() {
        ToggleButtonGroup [] allTRISButtons = {bgTRISA0, bgTRISA1, bgTRISA2, bgTRISA3, bgTRISA4, bgTRISB0, bgTRISB1, bgTRISB2, bgTRISB3, bgTRISB4, bgTRISB5, bgTRISB6, bgTRISB7};
        ToggleButtonGroup [] allPORTButtons = {bgPORTA0, bgPORTA1, bgPORTA2, bgPORTA3, bgPORTA4, bgPORTB0, bgPORTB1, bgPORTB2, bgPORTB3, bgPORTB4, bgPORTB5, bgPORTB6, bgPORTB7};
        for (int i = 0; i<allPORTButtons.length; i++) {
            ToggleButtonGroupExt.get().addAlwaysOneSelectedSupport(allTRISButtons[i]);
            ToggleButtonGroupExt.get().addAlwaysOneSelectedSupport(allPORTButtons[i]);
        }
        setTRISbuttons(allTRISButtons);
        setPORTbuttons(allPORTButtons);

        lstContentListView.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);

        autoRunGUI.setOnAction(this::autoRunGUI);
        stopButton.setOnAction(this::stopAutoRun);
    }



    private static void setTRISbuttons(ToggleButtonGroup[] allButtons) {
        allTRISbuttons = allButtons;
    }

    public static ToggleButtonGroup [] getTRISbuttons() {
        return allTRISbuttons;
    }

    private static void setPORTbuttons(ToggleButtonGroup[] allButtons) {
        allPORTbuttons = allButtons;
    }

    public static ToggleButtonGroup [] getPORTbuttons() {
        return allPORTbuttons;
    }

}




