package meerkat.voting.gui.managment;

import com.google.common.util.concurrent.FutureCallback;
import javafx.application.Application;
import javafx.stage.Stage;
import meerkat.protobuf.Voting;
import meerkat.voting.gui.ui.VotingBoothUI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
 * NOTE: For current state of voting-booth-gui (which doesnt have backed) this is class is unrelevant
 */

/**
 * Created by Vladimir Eliezer Tokarev on 9/17/2016.
 * This class managers the gui of the voting booth thruogth external commands
 */
public class VotingBoothGUIManager extends Application implements VotingBoothUI {
    private static final Logger logger = LoggerFactory.getLogger(VotingBoothGUIManager.class);
    private Map<String, TwoWayNode> visualPanelsMap;
    private Stage currentStage;

    @Override
    public void start(Stage primaryStage) throws Exception {
        doStartNewSession(primaryStage);
    }

    /**
     * Created new UI panels and sets their primary stage and shows the panels
     * @param primaryStage stage object which contains all the panels
     * @throws IOException
     */
    private void doStartNewSession(Stage primaryStage) throws IOException {

    }

    /**
     * Communicates with the select * panels and passes to them the questions to ask the voter
     * @param questions list of voting ballot questions (such as choose the racing candidate picture)
     * @param callback is a call back to method that handles users answers
     * @return List of voting ballot answers
     */
    private void askVoterForAnswers(List<Voting.BallotQuestion> questions, FutureCallback<List<Voting.BallotAnswer>> callback)
    {

    }

    /**
     * Method that activates the application and passes to start the primary stage (can be called outside this class)
     * @param args array of strings to pass to the start method as argument
     * @throws InterruptedException
     */
    public static void main(String[] args) throws InterruptedException {
        launch(args);
    }

    @Override
    public void callShutDown() {

    }
    /**
     * show an error to the voter. let him press a (chosen) button for handling the error.
     * @param errorMessage message to show in UI device
     * @param buttonLabels labels for buttons to present to voter
     * @param callback the number of the selected button
     */
    @Override
    public void showErrorMessageWithButtons(Voting.UIElement errorMessage, Voting.UIElement[] buttonLabels, FutureCallback<Integer> callback) {
        logger.debug("Graphical user interface call to showErrorMessageWithButtons");
    }


    /**
     * show an error to the voter. Halts the system until a technician handles it
     * @param errorMessage message to show in UI device
     * @param callback returns interrupt
     */
    @Override
    public void showErrorMessageAndHalt(Voting.UIElement errorMessage, FutureCallback<Boolean> callback) {
        logger.debug("Graphical user interface call to showErrorMessageAndHalt");
    }

    /**
     * makes the UI (and voter) wait for something else to happen, by registering a WaitForFinishUICommand in the queue
     * @param message a message to show the user on the UI device while waiting
     * @param callback a success return value of the wait (cancelling returns false)
     */
    @Override
    public void notifyVoterToWaitForFinish(Voting.UIElement message, FutureCallback<Void> callback) {
        logger.debug("Graphical user interface call to notifyVoterToWaitForFinish");
    }

    /**
     * call for the cast-or-audit phase by registering a CastOrAuditUICommand in the queue
     * @param callback the returned choice of how to finalize the ballot
     */
    @Override
    public void castOrAudit(FutureCallback<VotingBoothUI.FinalizeBallotChoice> callback) {
        logger.debug("Graphical user interface call to castOrAudit");
    }

    /**
     * call for the race voting question phase by registering a RaceVotingUICommand in the queue
     * @param questions all ballot questions to present to the voter
     * @param callback the responses to the questions collected by the UI, to send back to the controller. Responses are null if voter chose to cancel session
     */
    @Override
    public void askVoterQuestions(List<Voting.BallotQuestion> questions, FutureCallback<List<Voting.BallotAnswer>> callback) {
        logger.debug("Graphical user interface call to chooseChannel");
        try {
            askVoterForAnswers(questions, callback);
        }
        catch (Error e) {
            logger.debug(String.format("Couldn't ask voter questions: ", e));
            callback.onFailure(e);
        }
    }


    /**
     * call for the channel choice phase by registering a ChannelChoiceUICommand in the queue
     * @param questions questions to determine the right voting channel for this voter
     * @param callback that's where we store the answers to decide channel upon for the current voter
     */
    @Override
    public void chooseChannel(List<Voting.BallotQuestion> questions, FutureCallback<List<Voting.BallotAnswer>> callback) {
        logger.debug("Graphical user interface call to chooseChannel");

    }

    /**
     * start a new session by registering a StartSessionUICommand
     * @param callback - a boolean future callback to return when done
     */
    @Override
    public void startNewVoterSession(FutureCallback<Void> callback) {
        logger.debug("Graphical user interface call to startNewVoterSession");
        try {
            this.doStartNewSession(this.currentStage);
            callback.onSuccess(null);
        } catch (IOException e) {
            logger.error(String.format("Couldn't start new session of the voting process :", e));
            callback.onFailure(e);
        }
    }

}
