package meerkat.voting.gui.managment;

import javafx.stage.Stage;
import meerkat.voting.gui.configuration.VotingBoothConfiguration;
import meerkat.voting.gui.panels.ballot_summary.BallotSummaryLoader;
import meerkat.voting.gui.panels.cast_or_audit.CastOrAuditLoader;
import meerkat.voting.gui.panels.select_candidate_by_picture.SelectCandidateByPictureLoader;
import meerkat.voting.gui.panels.straight_channel_section.StraightChannelSectionLoader;
import meerkat.voting.gui.panels.thank_for_audditing.ThankForAuditingLoader;
import meerkat.voting.gui.panels.vote_have_been_cast.VoteHaveBeenCastLoader;
import meerkat.voting.gui.panels.welcome_splash.WelcomeSplashLoader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by Vladimir Eliezer Tokarev on 8/27/2016.
 * ChainBuilder builds all the two way nodes that are in current project (voting-booth-gui)
 *              and connects between all of them so they can keep their flow
 */
public class ChainBuilder {

    /**
     * Creates all  the twoWayNodes and connects between them
     *
     * The flow of Voting booth gui is next
     *                        Welcome Splash screen
     *                              \/
     *                    Channel selection screen
     *                             \/
     *                   Select Candidate Name screen
     *                     \/            /\
     *                  Select candidate by picture screen
     *                     \/            /\
     *                  Ballot summary no pictures
     *                            \/
     *                      Cast Or audit screen
     *                      \/                \/
     *              thank for voting   thank for auditing
     * In order to maintain this order next technique was implemented every "screen" will have the next screen
     * and the previous this way the flow between will be easy .
     * The Build method creates all the screens and connect between them
     */
    public static Map<String, TwoWayNode> Build(Stage primaryStage, VotingBoothConfiguration configuration) throws IOException {
        VotersBallot votersBallot = new VotersBallot();

        WelcomeSplashLoader welcomeSplashLoader = new WelcomeSplashLoader(primaryStage, configuration);
        TwoWayNode welcomeSplashController = welcomeSplashLoader.GetWelcomeSplash();
        welcomeSplashController.SetVotersBallot(votersBallot);
        // Calling the update method for the splash controller to run its graphics changes
        welcomeSplashController.UpdateNode();

        StraightChannelSectionLoader straightChannelSectionLoader = new StraightChannelSectionLoader(primaryStage, configuration);
        TwoWayNode straightChannelSectionController = straightChannelSectionLoader.GetStraightChannelSection();
        straightChannelSectionController.SetVotersBallot(votersBallot);
        welcomeSplashController.SetNext(straightChannelSectionController);
        straightChannelSectionController.SetPrevious(welcomeSplashController);

//        SelectCandidateNameLoader selectCandidateNameLoader = new SelectCandidateNameLoader(primaryStage, configuration);
//        TwoWayNode selectCandidateNameController = selectCandidateNameLoader.GetSelectCandidateName();
//        selectCandidateNameController.SetVotersBallot(votersBallot);
//        selectCandidateNameController.SetPrevious(straightChannelSectionController);


        SelectCandidateByPictureLoader selectCandidateByPictureLoader =
                new SelectCandidateByPictureLoader(primaryStage,configuration);
        TwoWayNode selectCandidateByPictureController = selectCandidateByPictureLoader.GetSelectCandidateByPicture();
        selectCandidateByPictureController.SetVotersBallot(votersBallot);
        selectCandidateByPictureController.SetPrevious(straightChannelSectionController);
//        selectCandidateNameController.SetNext(selectCandidateByPictureController);
        straightChannelSectionController.SetNext(selectCandidateByPictureController);

        BallotSummaryLoader ballotSummaryLoader = new BallotSummaryLoader(primaryStage, configuration);
        TwoWayNode ballotSummaryController = ballotSummaryLoader.GetBallotSummary();
        ballotSummaryController.SetVotersBallot(votersBallot);
        ballotSummaryController.SetPrevious(selectCandidateByPictureController);
        selectCandidateByPictureController.SetNext(ballotSummaryController);

        ThankForAuditingLoader thankForAuditingLoader = new ThankForAuditingLoader(primaryStage, configuration);
        TwoWayNode thankForAuditingController = thankForAuditingLoader.GetThankForAuditing();
        thankForAuditingController.SetVotersBallot(votersBallot);
        thankForAuditingController.SetPrevious(welcomeSplashController);

        CastOrAuditLoader castOrAuditLoader = new CastOrAuditLoader(primaryStage, configuration);
        TwoWayNode castOrAuditController = castOrAuditLoader.GetCastOrAudit();
        castOrAuditController.SetVotersBallot(votersBallot);
        ballotSummaryController.SetNext(castOrAuditController);
        castOrAuditController.SetPrevious(thankForAuditingController);

        VoteHaveBeenCastLoader voteHaveBeenCastLoader = new VoteHaveBeenCastLoader(primaryStage, configuration);
        TwoWayNode voteHaveBeenCastController = voteHaveBeenCastLoader.GetVoteHaveBeenCast();
        voteHaveBeenCastController.SetVotersBallot(votersBallot);
        voteHaveBeenCastController.SetPrevious(welcomeSplashController);
        castOrAuditController.SetNext(voteHaveBeenCastController);

        /**
         * all other two way nodes initialized
         */

        primaryStage.setScene(welcomeSplashController.GetCurrentScene());

        Map<String, TwoWayNode> nameToTwoWayNodeMap = new HashMap<>();
        nameToTwoWayNodeMap.put("welcomeSplashController", welcomeSplashController);
        nameToTwoWayNodeMap.put("straightChannelSectionController", straightChannelSectionController);
        //nameToTwoWayNodeMap.put("selectCandidateNameController", selectCandidateNameController);
        nameToTwoWayNodeMap.put("selectCandidateByPictureController", selectCandidateByPictureController);
        nameToTwoWayNodeMap.put("ballotSummaryController", ballotSummaryController);
        nameToTwoWayNodeMap.put("voteHaveBeenCastController", voteHaveBeenCastController);
        nameToTwoWayNodeMap.put("thankForAuditing", thankForAuditingController);

        final Logger logger = LoggerFactory.getLogger(ChainBuilder.class);
        logger.debug("Created all of the two nodes and conntected between them. (for more explanation please" +
                " check ChainBuilder.java file.");

        return nameToTwoWayNodeMap;
    }
}
