/*
 * 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.commons.correctness;

import java.util.Arrays;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.scytl.products.ov.commons.correctness.builder.options.VotingOptionCorrectnessBuilder;
import com.scytl.products.ov.commons.correctness.feedback.CorrectnessFeedback;
import com.scytl.products.ov.commons.correctness.feedback.ReportedError;

public class CachedOptionsCorrectnessTest {
	
	private static final Logger LOGGER = LoggerFactory.getLogger(CachedAttributeCorrectnessTest.class);
	
	private final CachedOptionCorrectnessEvaluator ce = new CachedOptionCorrectnessEvaluator(LOGGER);
	
	@Test
	public void correctnessEvalutionMultipleTimesTest(){
		String[] avaiableSelections1 = { "vo1", "vo2", "vo3" };
		String[] avaiableSelections2 = { "vo4", "vo5", "vo6" };
		
		VotingOptionCorrectnessBuilder cb = new VotingOptionCorrectnessBuilder();
		cb.withSelectionCorrectness("list1").withVotingOptions(Arrays.asList(avaiableSelections1))
				.withMinSelection(2).withMaxSelection(2).finish().withSelectionCorrectness("list2")
				.withVotingOptions((Arrays.asList(avaiableSelections2))).withMinSelection(1).withMaxSelection(1).finish();
		String correctness = CorrectnessFeedback.decorateRule(cb, false);
	

		String[] rawSelection1 = { "vo5", "vo1", "vo3" };
		String[] rawSelection2 = { "vo2", "vo4", "vo6", "vo7" };
		
		List<String> selection1 = Arrays.asList(rawSelection1);
		List<String> selection2 = Arrays.asList(rawSelection2);
		
		for (int i = 0; i < 1000; i++) {
			CorrectnessFeedback evaluateCorrectness = ce.evaluateCorrectness(correctness, selection1);
			Assert.assertTrue(evaluateCorrectness.getResult());
			Assert.assertNull(evaluateCorrectness.getErrors());
			evaluateCorrectness = ce.evaluateCorrectness(correctness, selection2);
			Assert.assertFalse(evaluateCorrectness.getResult());
			Assert.assertNotNull(evaluateCorrectness.getErrors());
			int passcount = 0;
			for (int j = 0; j < 3; j++) {
				ReportedError errors = evaluateCorrectness.getErrors().get(j);
				CorrectnessError errorType = errors.getErrorType();
				String reference = errors.getReference();
				if("list1".equals(reference) && CorrectnessError.MIN_ERROR.equals(errorType)){
					passcount++;
				} else if("list2".equals(reference) && CorrectnessError.MAX_ERROR.equals(errorType)){
					passcount++;
				} else if("list1".equals(reference) && CorrectnessError.MAX_ERROR.equals(errorType)){
					passcount++;
				}
			}
			Assert.assertEquals(passcount, 3);
		}
	}

	@Test
	public void alternatingCorrectnessEvalutionMultipleTimesTest(){
		String[] avaiableSelections1 = { "vo1", "vo2", "vo3" };
		String[] avaiableSelections2 = { "vo4", "vo5", "vo6" };
		
		VotingOptionCorrectnessBuilder cb1 = new VotingOptionCorrectnessBuilder();
		cb1.withSelectionCorrectness("list1").withVotingOptions(Arrays.asList(avaiableSelections1))
				.withMinSelection(2).withMaxSelection(2).finish().withSelectionCorrectness("list2")
				.withVotingOptions((Arrays.asList(avaiableSelections2))).withMinSelection(1).withMaxSelection(1).finish();
		String correctness1 = CorrectnessFeedback.decorateRule(cb1, false);
		
		String[] avaiableSelections21 = { "vo1", "vo2", "vo3" };
		String[] avaiableSelections22 = { "vo4", "vo5", "vo6", "vo7" };
		
		VotingOptionCorrectnessBuilder cb2 = new VotingOptionCorrectnessBuilder();
		cb1.withSelectionCorrectness("list1").withVotingOptions(Arrays.asList(avaiableSelections21))
				.withMinSelection(1).withMaxSelection(1).finish().withSelectionCorrectness("list2")
				.withVotingOptions((Arrays.asList(avaiableSelections22))).withMinSelection(3).withMaxSelection(3).finish();
		String correctness2 = CorrectnessFeedback.decorateRule(cb2, false);
	

		String[] rawSelection1 = { "vo5", "vo1", "vo3" };
		String[] rawSelection2 = { "vo2", "vo4", "vo6", "vo7" };
		
		List<String> selection1 = Arrays.asList(rawSelection1);
		List<String> selection2 = Arrays.asList(rawSelection2);
		
		for (int i = 0; i < 1000; i++) {
			CorrectnessFeedback evaluateCorrectness = ce.evaluateCorrectness(correctness1, selection1);
			Assert.assertTrue(evaluateCorrectness.getResult());
			Assert.assertNull(evaluateCorrectness.getErrors());
			evaluateCorrectness = ce.evaluateCorrectness(correctness2, selection2);
			Assert.assertTrue(evaluateCorrectness.getResult());
			Assert.assertNull(evaluateCorrectness.getErrors());
		}
	}
}
