import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import java.util.NoSuchElementException;
import java.util.List;

public class Frontend extends Application implements FrontendInterface {

    private static BackendInterface back;

    public static void setBackend(BackendInterface back) { Frontend.back = back; }

    @Override
    public void start(Stage stage) throws Exception {
        setBackend(new Backend(new DijkstraGraph<>()));
        back.loadGraphData("campus.dot");
        Pane root = new Pane();
        createAllControls(root);

        Scene scene = new Scene(root, 800, 600);
        stage.setScene(scene);
        stage.setTitle("P2");
        stage.show();
    }

    @Override
    public void createAllControls(Pane parent) {
        createShortestPathControls(parent);
        createPathListDisplay(parent);
        createAdditionalFeatureControls(parent);
        createAboutAndQuitControls(parent);
    }

    @Override
    public void createShortestPathControls(Pane parent) {
        Label srcLabel = new Label("Path Start Selector:");
        srcLabel.setId("srcLabel");
        srcLabel.setLayoutX(32);
        srcLabel.setLayoutY(16);
        parent.getChildren().add(srcLabel);

        Label dstLabel = new Label("Path End Selector:");
        dstLabel.setId("dstLabel");
        dstLabel.setLayoutX(32);
        dstLabel.setLayoutY(48);
        parent.getChildren().add(dstLabel);

        List<String> locationsList = back.getListOfAllLocations();
        ObservableList<String> locations = FXCollections.observableArrayList(locationsList);
        final ComboBox srcSelector = new ComboBox(locations);
        srcSelector.setId("srcSelector");
        srcSelector.setPrefWidth(150);
        srcSelector.setLayoutX(200);
        srcSelector.setLayoutY(16);
        parent.getChildren().add(srcSelector);

        final ComboBox dstSelector = new ComboBox(locations);
        dstSelector.setId("dstSelector");
        dstSelector.setLayoutX(200);
        dstSelector.setLayoutY(48);
        dstSelector.setPrefWidth(150);
        parent.getChildren().add(dstSelector);

        Button search = new Button("Search Button");
        search.setId("searchButton");
        search.setOnAction( e -> {
            Label pathLabel = (Label) parent.lookup("#path");
            String src = (String) srcSelector.getValue();
            String dst = (String) dstSelector.getValue();
            String pathString = "";
            try {
                List<String> shortestPath = back.findShortestPath(src, dst);
                pathString = "Results List:\n\t" + String.join("\n\t", shortestPath);

                CheckBox withTimes = (CheckBox) parent.lookup("#showTimesBox");
                if (withTimes.isSelected()) {
                    pathString += "\n\nResults List (with walking times):\n\t" +
                            shortestPath.get(0);
                    List<Double> times = back.getTravelTimesOnPath(src, dst);
                    for (int i = 0; i < times.size(); ++i) {
                        pathString += "\n\t-(" + times.get(i) + "sec)->" + shortestPath.get(i + 1);
                    }
                }
                pathLabel.setText(pathString);
            } catch (NoSuchElementException e1) {
                pathString = "Please select a valid location on campus for source and destination.";
                pathLabel.setText(pathString);
            }
        });
        search.setLayoutX(32);
        search.setLayoutY(80);
        parent.getChildren().add(search);
    }

    @Override
    public void createPathListDisplay(Pane parent) {
        Label path = new Label("Results List:");
        path.setId("path");
        path.setLayoutX(32);
        path.setLayoutY(112);
        parent.getChildren().add(path);
    }

    @Override
    public void createAdditionalFeatureControls(Pane parent) {
        this.createTravelTimesBox(parent);
        this.createFurthestDestinationControls(parent);
    }

    @Override
    public void createTravelTimesBox(Pane parent) {
        CheckBox showTimesBox = new CheckBox("Show Walking Times");
        showTimesBox.setId("showTimesBox");
        showTimesBox.setLayoutX(200);
        showTimesBox.setLayoutY(80);
        parent.getChildren().add(showTimesBox);
    }

    @Override
    public void createFurthestDestinationControls(Pane parent) {
        Label locationLabel = new Label("Location Selector:");
        locationLabel.setId("locationLabel");
        locationLabel.setLayoutX(450);
        locationLabel.setLayoutY(16);
        parent.getChildren().add(locationLabel);

        List<String> locationsList = back.getListOfAllLocations();
        ObservableList<String> locations = FXCollections.observableArrayList(locationsList);
        final ComboBox locationSelector = new ComboBox(locations);
        locationSelector.setId("locationSelector");
        locationSelector.setLayoutX(450);
        locationSelector.setLayoutY(40);
        parent.getChildren().add(locationSelector);

        Label furthestFromLabel = new Label("Most Distant Location:");
        furthestFromLabel.setId("furthestFromLabel");
        furthestFromLabel.setLayoutX(450);
        furthestFromLabel.setLayoutY(110);
        parent.getChildren().add(furthestFromLabel);

        Button furthestFromButton = new Button("Find Most Distant Location");
        furthestFromButton.setId("furthestFromButton");
        furthestFromButton.setOnAction( e -> {
            try {
                String location = back.getMostDistantLocation((String) locationSelector.getValue());
                furthestFromLabel.setText("Most Distant Location:\n" + location);
            } catch (NoSuchElementException e2) {
                furthestFromLabel.setText("Please select a valid location on campus.");
            }
        });
        furthestFromButton.setLayoutX(450);
        furthestFromButton.setLayoutY(75);
        parent.getChildren().add(furthestFromButton);
    }

    @Override
    public void createAboutAndQuitControls(Pane parent) {
        Button about = new Button("About");
        about.setId("about");
        about.setOnAction( e -> {
            Label aboutLabel = new Label("Here to help UW students who hate Google Maps!");
            aboutLabel.setId("aboutLabel");
            aboutLabel.setLayoutX(96);
            aboutLabel.setLayoutY(560);
            parent.getChildren().add(aboutLabel);
        });
        about.setLayoutX(32);
        about.setLayoutY(560);
        parent.getChildren().add(about);

        Button quit = new Button("Quit");
        quit.setId("quit");
        quit.setOnAction( e -> {
            quit.setText("Goodbye :)");
            Platform.exit();
        });
        quit.setLayoutX(740);
        quit.setLayoutY(560);
        parent.getChildren().add(quit);
    }

}
