/*
 * 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.mixing.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.scytl.products.ov.channel.cc.commons.slogger.ServiceTransactionInfoProvider;
import com.scytl.products.ov.commons.dto.MixingDTO;
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;

@Service
public class MixingDecryptServiceImpl implements MixingDecryptService, MessageListener {

    private static final Logger LOG = LoggerFactory.getLogger("std");

    private Queue mixingInputQueue;

    private Queue mixingOutputQueue;

    @Autowired
    private MessagingService messagingService;

    @Autowired
    private InternalMixDecryptService internalMixDecryptService;

    @Autowired
    private ServiceTransactionInfoProvider serviceTransactionInfoProvider;

    @Value("${queues.md-mixdec.req}")
    public void setMixingInputQueue(String queueName) {
        mixingInputQueue = new Queue(queueName);
    }

    @Value("${queues.md-mixdec.res}")
    public void setMixingOutputQueue(String queueName) {
        mixingOutputQueue = new Queue(queueName);
    }

    @Override
    public void startup() throws MixingDecryptException {
        try {
            messagingService.createReceiver(mixingInputQueue, this);
            LOG.info("Distributed mixing and decryption service listening on queue {}", mixingInputQueue);
        } catch (MessagingException e) {
            LOG.error("Failed to startup mixdecrypt service.");
            throw new MixingDecryptException("Failed to startup mixdecrypt service.", e);
        }
    }

    @Override
    public void shutdown() throws MixingDecryptException {
        try {
            messagingService.destroyReceiver(mixingInputQueue, this);
            LOG.info("Distributed mixing and decryption service is not listening on queue {}", mixingInputQueue);
        } catch (MessagingException e) {
            LOG.error("Failed to shutdown mixdecrypt service.");
            throw new MixingDecryptException("Failed to shutdown mixdecrypt service.", e);
        }
    }

    @Override
    public void onMessage(Object message) {
        MixingDTO dto = (MixingDTO) message;
        serviceTransactionInfoProvider.generate(dto.getPayload().getVoteSetId().getBallotBoxId().getTenantId(),
            "clientIP", "serverIP", dto.getRequestId());
        String ballotBoxId = dto.getPayload().getVoteSetId().getBallotBoxId().toString();
        LOG.info("Received ballot box {} from {} for mixing and decrypting", ballotBoxId, mixingInputQueue);

        try {
            internalMixDecryptService.executeMixing(dto);
            LOG.info("Mixing and decryption of {} from {} finished, sending results to {}, queues left to visit are {}",
                ballotBoxId, dto.getLastQueueName(), mixingOutputQueue, dto.getQueuesToVisit());

            messagingService.send(mixingOutputQueue, dto);
        } catch (MessagingException e) {
            LOG.error("Failed to send the mixing results of {} to {}", ballotBoxId, mixingOutputQueue, e);
        }
    }
}
