/*
 * 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.ui.ws.rs.application;

import com.fasterxml.jackson.core.JsonProcessingException;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.sdm.application.service.VotingCardSetComputationService;
import java.io.IOException;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.web.util.UriComponentsBuilder;

import com.scytl.products.oscore.logging.api.writer.SecureLoggingWriter;
import com.scytl.products.oscore.logging.core.provider.TransactionInfoProvider;
import com.scytl.products.ov.commons.beans.domain.model.messaging.PayloadSignatureException;
import com.scytl.products.ov.commons.beans.domain.model.messaging.PayloadVerificationException;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.sdm.application.service.IdleStatusService;
import com.scytl.products.ov.sdm.application.service.VotingCardSetPrecomputationService;
import com.scytl.products.ov.sdm.application.service.VotingCardSetService;
import com.scytl.products.ov.sdm.domain.model.decryption.ValidationJobStatus;
import com.scytl.products.ov.sdm.domain.model.generator.DataGeneratorResponse;
import com.scytl.products.ov.sdm.domain.model.precompute.DataPrecomputeResponse;
import com.scytl.products.ov.sdm.domain.model.status.InvalidStatusTransitionException;
import com.scytl.products.ov.sdm.domain.model.status.Status;
import com.scytl.products.ov.sdm.domain.model.votingcardset.VotingCardSetUpdateInputData;
import com.scytl.products.ov.sdm.domain.service.ProgressManagerService;
import com.scytl.products.ov.sdm.infrastructure.cc.PayloadStorageException;

@RunWith(MockitoJUnitRunner.class)
@ContextConfiguration
public class VotingCardSetResourceTest {

    @Mock
    VotingCardSetPrecomputationService votingCardSetPrecomputationService;

    @Mock
    VotingCardSetComputationService votingCardSetComputationService;

    @Mock
    VotingCardSetService votingCardSetService;

    @Mock
    IdleStatusService idleStatusService;

    @Mock
    ProgressManagerService<ValidationJobStatus> progressManagerService;

    @Mock
    TransactionInfoProvider transactionInfoProvider;

    @Mock
    SecureLoggingWriter secureLogger;

    @InjectMocks
    VotingCardSetResource sut = new VotingCardSetResource();

    @Before
    public void setUp()
            throws ResourceNotFoundException, IOException, InvalidStatusTransitionException, GeneralCryptoLibException,
            PayloadStorageException, PayloadSignatureException {
        DataGeneratorResponse response = mock(DataGeneratorResponse.class);
        when(response.isSuccessful()).thenReturn(true);
        when(votingCardSetService.generate(any(), any())).thenReturn(response);

        DataPrecomputeResponse dataPrecomputeResponse = mock(DataPrecomputeResponse.class);
        when(dataPrecomputeResponse.isSuccessful()).thenReturn(true);
        doNothing().when(votingCardSetPrecomputationService).precompute(anyString(), anyString(), anyString(),
            anyString());
    }

    @Test
    public void testCorrectStatusTransition()
            throws ResourceNotFoundException, InvalidStatusTransitionException, IOException, GeneralCryptoLibException,
            PayloadStorageException, PayloadSignatureException, JsonProcessingException, PayloadVerificationException {
        assertEquals(HttpStatus.NO_CONTENT, getResultingStatusCode(Status.PRECOMPUTED));
        assertEquals(HttpStatus.NO_CONTENT, getResultingStatusCode(Status.COMPUTING));
        assertEquals(HttpStatus.NO_CONTENT, getResultingStatusCode(Status.VCS_DOWNLOADED));
    }

    @Test
    public void testUnsupportedStatusTransition()
            throws ResourceNotFoundException, InvalidStatusTransitionException, IOException, GeneralCryptoLibException,
            PayloadStorageException, PayloadSignatureException, JsonProcessingException, PayloadVerificationException {
        doThrow(InvalidStatusTransitionException.class).when(votingCardSetService).download(anyString(), anyString());
        assertEquals(HttpStatus.BAD_REQUEST, getResultingStatusCode(Status.VCS_DOWNLOADED));
    }

    @Test
    public void testGenerate() throws IOException, ResourceNotFoundException, InvalidStatusTransitionException {
        String electionEventId = "electionEvent";
        String votingCardSetId = "votingCardSet";
        UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromUriString("");

        ResponseEntity<?> response = sut.createVotingCardSet(electionEventId, votingCardSetId, uriBuilder);

        assertTrue(response.getStatusCode().equals(HttpStatus.CREATED));
    }

    private HttpStatus getResultingStatusCode(Status status)
            throws ResourceNotFoundException, InvalidStatusTransitionException, IOException, GeneralCryptoLibException,
            PayloadStorageException, PayloadSignatureException, JsonProcessingException, PayloadVerificationException {
        String electionEventId = "electionEvent";
        String votingCardSetId = "votingCardSet";
        return sut
            .setVotingCardSetStatus(electionEventId, votingCardSetId,
                new VotingCardSetUpdateInputData(status, null, null))
            .getStatusCode();
    }
}
