/*
 * 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.au.services.domain.service.validation;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;

import java.security.cert.CertificateException;
import java.util.Iterator;

import javax.enterprise.inject.Instance;

import com.scytl.products.ov.au.services.domain.service.authenticationcontent.AuthenticationContentService;
import com.scytl.products.ov.commons.beans.exceptions.AuthTokenValidationException;
import com.scytl.products.ov.commons.validation.ValidationResult;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner;
import org.slf4j.Logger;

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.products.ov.commons.beans.domain.model.authentication.AuthenticationContent;
import com.scytl.products.ov.au.services.domain.model.authentication.AuthenticationToken;
import com.scytl.products.ov.au.services.domain.model.information.VoterInformation;
import com.scytl.products.ov.au.services.domain.model.information.VoterInformationRepository;
import com.scytl.products.ov.au.services.domain.model.validation.AuthenticationTokenValidation;
import com.scytl.products.ov.commons.beans.exceptions.ResourceNotFoundException;
import com.scytl.products.ov.commons.beans.validation.ValidationErrorType;

@RunWith(MockitoJUnitRunner.class)
public class AuthenticationTokenValidationServiceTest {

	@InjectMocks
	@Spy
	AuthenticationTokenValidationServiceImpl validationService = new AuthenticationTokenValidationServiceImpl();

	@InjectMocks
	AuthenticationToken authenticationTokenMock = new AuthenticationToken();

	@Mock
	VoterInformationRepository voterInformationRepositoryMock;

	@Mock
	Instance<AuthenticationTokenValidation> authenticationTokenValidationsMock;

	@Mock
	Iterator<AuthenticationTokenValidation> iteratorMock;

	@Mock
	AuthenticationTokenValidation authenticationTokenValidationMock;

	@Mock
	private AuthenticationContent authenticationContentMock;

	@Mock
	private AuthenticationContentService authenticationContentServiceMock;

	@Mock
	Logger logger;

	@Before
	public void setUp() {
		when(authenticationTokenValidationsMock.iterator()).thenReturn(iteratorMock);
	}

	@Test
	public void validateFalse() throws GeneralCryptoLibException, ResourceNotFoundException, CertificateException {
		when(iteratorMock.next()).thenReturn(authenticationTokenValidationMock);
		when(iteratorMock.hasNext()).thenReturn(true, false);
		validationService.setValidations(authenticationTokenValidationsMock);

		String tenantId = "1";
		String electionEventId = "1";
		String votingCardId = "1";
		ValidationResult resultMock = new ValidationResult();
		resultMock.setResult(false);
		VoterInformation voterInformation = new VoterInformation();
		when(voterInformationRepositoryMock.findByTenantIdElectionEventIdCredentialId(tenantId, electionEventId,
			votingCardId)).thenReturn(voterInformation);
		when(authenticationTokenValidationMock.execute(tenantId, electionEventId, votingCardId, authenticationTokenMock))
			.thenThrow(new AuthTokenValidationException(ValidationErrorType.FAILED));
		doReturn(authenticationContentMock).when(validationService).getAuthenticationContent(anyString(), anyString());
		
		ValidationResult result =
			validationService.validate(tenantId, electionEventId, votingCardId, authenticationTokenMock);

		assertFalse(result.isResult());
	}

	@Test
	public void validateTrue() throws GeneralCryptoLibException, ResourceNotFoundException, CertificateException {
		when(iteratorMock.next()).thenReturn(authenticationTokenValidationMock);
		when(iteratorMock.hasNext()).thenReturn(true, false);
		validationService.setValidations(authenticationTokenValidationsMock);

		String tenantId = "1";
		String electionEventId = "1";
		String votingCardId = "1";
		VoterInformation voterInformation = new VoterInformation();
		ValidationResult resultMock = new ValidationResult();
		when(voterInformationRepositoryMock.findByTenantIdElectionEventIdCredentialId(tenantId, electionEventId,
			votingCardId)).thenReturn(voterInformation);
		when(authenticationTokenValidationMock.execute(tenantId, electionEventId, votingCardId, authenticationTokenMock))
			.thenReturn(resultMock);

		doReturn(authenticationContentMock).when(validationService).getAuthenticationContent(anyString(), anyString());
		when(validationService.getAuthenticationContent(tenantId, electionEventId)).thenReturn(authenticationContentMock);
		
		ValidationResult result =
			validationService.validate(tenantId, electionEventId, votingCardId, authenticationTokenMock);

		assertTrue(result.isResult());
	}


	@Test
	public void getAuthenticationContent() throws ResourceNotFoundException {

		String tenantId = "1";
		String electionEventId = "1";
		when(authenticationContentServiceMock.getAuthenticationContent(anyString(), anyString())).thenReturn(authenticationContentMock);
		validationService.getAuthenticationContent(tenantId, electionEventId);
	}
}
