package be.iminds.ilabt.jfed.ui.javafx.util;

import be.iminds.ilabt.jfed.util.ExtraInfoCallback;
import be.iminds.ilabt.jfed.util.JFedPasswordManager;
import javafx.application.Platform;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Window;
import javafx.util.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * ExtraInfoCallBackGUIs
 */
public class ExtraInfoCallBackGUIs {
    private static final Logger LOG = LoggerFactory.getLogger(ExtraInfoCallBackGUIs.class);
    private static boolean prepared = false;

    /**
     * User feedback needed by library. A bit of a hack.
     * <p/>
     * May be called multiple times, will happen only once.
     */
    public static void prepareExtraInfoCallback(final Window window) {
        if (prepared) return;

        ExtraInfoCallback.setAnyLoginCallback(
                new ExtraInfoCallback.AnyLoginCallback() {
                    private JFedPasswordManager.LoginInfo cachedLogin = null;
                    private boolean loginScreenShown = false;

                    private Pair<String, String> showLoginScreen(String friendlyServiceName) {
                        HBox hboxUserName = new HBox(10);
                        hboxUserName.getChildren().add(new ImageView(ExtraInfoCallBackGUIs.class.getResource("images/user.png").toExternalForm()));
                        final TextField txUserName = new TextField();
                        txUserName.setPromptText("User Name");
                        hboxUserName.getChildren().add(txUserName);


                        HBox hboxPassword = new HBox(10);
                        hboxPassword.getChildren().add(new ImageView(ExtraInfoCallBackGUIs.class.getResource("images/lock.png").toExternalForm()));
                        final PasswordField txPassword = new PasswordField();
                        txPassword.setPromptText("Password");
                        hboxPassword.getChildren().add(txPassword);


                        final VBox content = new VBox(10);

                        final Label lbMessage =
                                new Label("Please enter your " + friendlyServiceName + " credentials:");
                        // lbMessage.getStyleClass().addAll("message-banner");
                        content.getChildren().add(lbMessage);
                        content.getChildren().add(hboxUserName);
                        content.getChildren().add(hboxPassword);

                        Dialog<ButtonType> dlg = new Dialog<>();
                        dlg.initOwner(window);
                        dlg.setTitle(friendlyServiceName + " Login");
                        DialogPane dlgPane = new DialogPane();

                        dlgPane.setContent(content);
                        dlgPane.setGraphic(new ImageView(ExtraInfoCallBackGUIs.class.getResource("images/login.png").toExternalForm()));
                        ButtonType loginButtonType = new ButtonType("Login", ButtonBar.ButtonData.OK_DONE);
                        ButtonType noAccountButtonType =
                                new ButtonType("I don't have a " + friendlyServiceName + " account", ButtonBar.ButtonData.CANCEL_CLOSE);
                        dlgPane.getButtonTypes().setAll(loginButtonType, noAccountButtonType);
                        dlg.setDialogPane(dlgPane);

                        Platform.runLater(txUserName::requestFocus);
                        Optional<ButtonType> response = dlg.showAndWait();


                        return response.isPresent() && response.get() == loginButtonType ?
                                new Pair<>(txUserName.getText(), txPassword.getText()) :
                                null;
                    }


                    @Override
                    public JFedPasswordManager.LoginInfo getLogin(String serviceName, String friendlyServiceName) {
                        if (!loginScreenShown) {
                            Pair<String, String> res = null;
                            if (Platform.isFxApplicationThread())
                                res = showLoginScreen(friendlyServiceName);
                            else {
                                FutureTask<Pair<String, String>> futureTask =
                                        new FutureTask<>(() -> showLoginScreen(friendlyServiceName));
                                Platform.runLater(futureTask);

                                try {
                                    res = futureTask.get();
                                } catch (InterruptedException | ExecutionException e) {
                                    LOG.error("Error while showing " + friendlyServiceName + " login screen", e);
                                }
                            }
                            if (res == null)
                                cachedLogin = null;
                            else
                                cachedLogin =
                                        new JFedPasswordManager.LoginInfo(serviceName, res.getKey(), res.getValue());

                            loginScreenShown = true;

                        }
                        if (cachedLogin == null)
                            throw new ExtraInfoCallback.NoAccountException();
                        return cachedLogin;
                    }
                }

        );

        prepared = true;
    }
}
