package meerkat.voting.controller.callbacks;

import meerkat.protobuf.Voting.*;
import meerkat.voting.controller.commands.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * A controller callback for the channel-choice request to the UI.
 * Upon receiving the answers for the channel-choice questions, the callback registers a new ChannelDeterminedCommand
 * to the controller queue, so the controller can then process the answers and set the channel.
 * If voter cancelled during the process, a cancelling exception is thrown and a RestartVotingCommand is
 * registered through the onFailure() method
 */
public class ChannelChoiceCallback extends ControllerCallback<List<BallotAnswer>> {
    protected final static Logger logger = LoggerFactory.getLogger(ChannelChoiceCallback.class);
    protected final UIElement unsuccessfulChannelChoiceMessage;

    public ChannelChoiceCallback(int requestId,
                                 long ballotSerialNumber,
                                 LinkedBlockingQueue<ControllerCommand> controllerQueue,
                                 UIElement unsuccessfulChannelChoiceMessage) {
        super(requestId, ballotSerialNumber, controllerQueue);
        this.unsuccessfulChannelChoiceMessage = unsuccessfulChannelChoiceMessage;
    }

    @Override
    public void onSuccess(List<BallotAnswer> result) {
        logger.debug("callback for channel choice returned success");
        // register the chosen BallotAnswers to a command in the controller queue
        enqueueCommand(new ChannelDeterminedCommand(getRequestIdentifier(), getBallotSerialNumber(), result));
    }

    @Override
    public void onFailure(Throwable t) {
        if (t instanceof VoterCancelThrowable) {
            // voter has cancelled during the UI channel choice process. A VoterCancelThrowable is thrown
            logger.debug("ChannelChoiceCallback got a cancellation response");
            enqueueCommand(new RestartVotingCommand(getRequestIdentifier(), getBallotSerialNumber()));
        }
        else {
            logger.error("channel choice initiated a failure: " + t);
            enqueueCommand(new ReportErrorCommand(getRequestIdentifier(),
                    getBallotSerialNumber(),
                    unsuccessfulChannelChoiceMessage));
        }
    }
}
