/*
 * Copyright 2018 Scytl Secure Electronic Voting SA
 *
 * All rights reserved
 *
 * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
 */
package com.scytl.products.ov.channel.cc.orchestrator.ui.ws.rs.config;

import java.util.Collections;
import java.util.function.Consumer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.scytl.products.ov.commons.beans.domain.model.vote.VoteSetId;
import com.scytl.products.ov.commons.dto.MixingDTO;
import com.scytl.products.ov.commons.dto.mixing.MixingPayload;
import com.scytl.products.ov.commons.dto.mixing.MixingPayloadImpl;
import com.scytl.products.ov.commons.messaging.MessageListener;
import com.scytl.products.ov.commons.messaging.MessagingException;
import com.scytl.products.ov.commons.messaging.MessagingService;
import com.scytl.products.ov.commons.messaging.Queue;

/**
 * Message listener for the mock mixing control component node.
 */
public class MockMixingNodeListener implements MessageListener {

    private static final Logger logger = LoggerFactory.getLogger(MockMixingNodeListener.class);

    private final MessagingService messagingService;

    private final String nodeName;

    private final String requestQueueName;

    private final String responseQueueName;

    private Consumer<MixingDTO> dtoProcessor;

    public MockMixingNodeListener(MessagingService messagingService, String nodeName, String requestQueueName,
            String responseQueueName) {
        this.messagingService = messagingService;
        this.nodeName = nodeName;
        this.requestQueueName = requestQueueName;
        this.responseQueueName = responseQueueName;
    }

    /**
     * Allows setting up a function that will be passed a mixing DTO, and it
     * outputs another mixing DTO, for custom processing.
     *
     * @param dtoProcessor
     *            the function in question
     */
    public void setDTOProcessor(Consumer<MixingDTO> dtoProcessor) {
        this.dtoProcessor = dtoProcessor;
    }

    @Override
    public void onMessage(Object message) {
        MixingDTO dto = (MixingDTO) message;
        MixingPayload inputPayload = dto.getPayload();
        VoteSetId voteSetId = inputPayload.getVoteSetId();

        logger.info("Node {} received vote set {} for mixing", nodeName, voteSetId);

        // If a custom processing function for the DTO has been set up, use it.
        if (null != dtoProcessor) {
            dtoProcessor.accept(dto);
        }

        MixingPayload outputPayload = new MixingPayloadImpl(inputPayload, inputPayload.getVoteEncryptionKey(),
            inputPayload.getVotes(), Collections.emptyList(), inputPayload.getVotes(), "", Collections.emptyList());

        // Mock the processed payload.
        dto.update(requestQueueName, nodeName, outputPayload);

        logger.info("Payload {} has been processed by node {}", outputPayload.getVoteSetId(), nodeName);

        try {
            // Send the output DTO.
            messagingService.send(new Queue(responseQueueName), dto);
        } catch (MessagingException e) {
            throw new RuntimeException("Oh fish", e);
        }
    }
}
