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

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import javax.ws.rs.core.MediaType;

import com.scytl.products.ov.commons.dto.ChoiceCodeGenerationReqPayload;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.scytl.products.ov.commons.infrastructure.exception.OvCommonsInfrastructureException;
import com.scytl.products.ov.commons.infrastructure.remote.client.InputStreamTypedOutput;
import com.scytl.products.ov.commons.infrastructure.remote.client.RestClientConnectionManager;
import com.scytl.products.ov.commons.infrastructure.remote.client.RetrofitConsumer;
import com.scytl.products.ov.commons.infrastructure.remote.client.RetrofitException;
import com.scytl.products.ov.commons.ui.ws.rs.ObjectMappers;
import com.scytl.products.ov.sdm.application.exception.VotingCardSetChoiceCodesServiceException;
import com.scytl.products.ov.sdm.infrastructure.clients.OrchestratorClient;

import okhttp3.ResponseBody;
import retrofit2.Retrofit;

@Service
public class VotingCardSetChoiceCodesService {

    @Value("${OR_URL}")
    private String orchestratorUrl;

    @Value("${tenantID}")
    private String tenantId;

    /**
     * Sends the primes list and verification card IDs to the compute end-point.
     */
    public void sendToCompute(ChoiceCodeGenerationReqPayload payload)
            throws JsonProcessingException, RetrofitException {

        // Encapsulate the payload into a typed input stream.
        InputStreamTypedOutput computeRequestBody = prepareComputeRequestBody(payload);

		try (ResponseBody responseBody = RetrofitConsumer
				.processResponse(getOrchestratorClient().compute(computeRequestBody))) {
			//This block is intentionally left blank (Using the Closeable) 
		}
    }

    /**
     * Download choice codes computations contributions
     */
    public InputStream download(String electionEventId, String verificationCardSetId, int chunkId)
            throws RetrofitException {
        return RetrofitConsumer
            .processResponse(
                getOrchestratorClient().download(tenantId, electionEventId, verificationCardSetId, chunkId))
            .byteStream();
    }

    /**
     * Prepares the body for compute call
     */
    private InputStreamTypedOutput prepareComputeRequestBody(ChoiceCodeGenerationReqPayload payload)
            throws JsonProcessingException {
        // The whole object is in memory three times before being
        // streamed (SV-5964).
        InputStream choiceCodeGenerationRequestPayloadJsonInputStream =
            new ByteArrayInputStream(ObjectMappers.toJson(payload).getBytes(StandardCharsets.UTF_8));

        return new InputStreamTypedOutput(MediaType.APPLICATION_JSON,
            choiceCodeGenerationRequestPayloadJsonInputStream);
    }

    /**
     * Gets the orchestrator Retrofit client
     */
	private OrchestratorClient getOrchestratorClient() {
		try {
			Retrofit restAdapter = RestClientConnectionManager.getInstance()
					.getRestClientWithJacksonConverter(orchestratorUrl);
			return restAdapter.create(OrchestratorClient.class);
		} catch (OvCommonsInfrastructureException e) {
			throw new VotingCardSetChoiceCodesServiceException("Error trying to get Orchestrator Client", e);
		}
	}
}
