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

import java.security.KeyManagementException;

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.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.channel.cc.commons.keymanagement.FingerprintGeneratorException;
import com.scytl.products.ov.channel.cc.commons.services.ChoiceCodesKeyRepository;
import com.scytl.products.ov.channel.cc.commons.slogger.ServiceTransactionInfoProvider;
import com.scytl.products.ov.commons.dto.KeyCreationDTO;
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 ChoiceCodesKeyGenerationServiceImpl implements ChoiceCodesKeyGenerationService, MessageListener {

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

    private Queue keyGenerationInputQueue;

    private Queue keyGenerationOutputQueue;

    @Autowired
    private MessagingService messagingService;

    @Autowired
    private ChoiceCodesKeyRepository choiceCodesKeyRepository;

    @Autowired
    private ServiceTransactionInfoProvider serviceTransactionInfoProvider;

    @Value("${queues.cg-keygen.req}")
    public void setKeyGenerationInputQueue(String queueName) {
        keyGenerationInputQueue = new Queue(queueName);
    }

    @Value("${queues.cg-keygen.res}")
    public void setKeyGenerationOutputQueue(String queueName) {
        keyGenerationOutputQueue = new Queue(queueName);
    }

    @Override
    public void startup() throws ChoiceCodesGenerationException {
        try {
            messagingService.createReceiver(keyGenerationInputQueue, this);
        } catch (MessagingException e) {
            LOG.error("Failed to initialize choice codes generation service.", e);
            throw new ChoiceCodesGenerationException("Failed to initialize choice codes key generation service.", e);
        }
    }

    @Override
    public void shutdown() throws ChoiceCodesGenerationException {
        try {
            messagingService.destroyReceiver(keyGenerationInputQueue, this);
        } catch (MessagingException e) {
            LOG.error("Failed to stop choice codes generation service.", e);
            throw new ChoiceCodesGenerationException("Failed to stop choice codes key generation service.", e);
        }
    }

    @Override
    public void onMessage(Object message) {
        KeyCreationDTO data = (KeyCreationDTO) message;
        serviceTransactionInfoProvider.generate("tenantID", "clientIP", "serverIP", data.getRequestId());
        LOG.info("Generating partial key");

        try {
            KeyCreationDTO toBeReturned = createKeyCreationDTO(data);
            messagingService.send(keyGenerationOutputQueue, toBeReturned);
        } catch (MessagingException | GeneralCryptoLibException | KeyManagementException
                | FingerprintGeneratorException e) {
            LOG.error("Failed to send the key generation result", e);
        }
    }

    private KeyCreationDTO createKeyCreationDTO(KeyCreationDTO data)
            throws GeneralCryptoLibException, KeyManagementException, FingerprintGeneratorException {
        KeyCreationDTO toBeReturned = new KeyCreationDTO(data);
        choiceCodesKeyRepository.addGeneratedKey(toBeReturned);

        return toBeReturned;
    }

}
