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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

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

import com.scytl.products.ov.commons.correctness.CorrectnessError;
import com.scytl.products.ov.commons.correctness.builder.attributes.AttributesCorrectnessBuilder;
import com.scytl.products.ov.commons.correctness.builder.attributes.ContestCorrectionBuilder;
import com.scytl.products.ov.commons.correctness.feedback.CorrectnessFeedback;
import com.scytl.products.ov.commons.correctness.feedback.ReportedError;
import com.scytl.products.ov.commons.correctness.internal.AttributeCorrectnessEvaluator;
import com.scytl.products.ov.commons.correctness.internal.CorrectnessEvaluator;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AttributesSteps {
	private static final Logger LOGGER = LoggerFactory.getLogger(AttributesSteps.class);

	private AttributesCorrectnessBuilder correctness = new AttributesCorrectnessBuilder();

	private CorrectnessEvaluator<List<String>> ce = new AttributeCorrectnessEvaluator(LOGGER);

	private CorrectnessFeedback correctnessResult;
	
	private AtomicInteger errorCounter = new AtomicInteger(0);

	private ContestCorrectionBuilder contest;

	private List<List<String>> selections = new ArrayList<>();
	
	@Given(value = "a contest with name (.+)$")
	public void addContestToCorrectnessRule(String contestId) {
		contest = correctness.addContest(contestId);
	}
	
	@Given(value = "a question with correctness attribute (.+) with maximum selection of (\\d+)$")
	public void buildCorrectness(String attributeId, Integer max) {
		contest.addQuestion(attributeId, max);
	}
	
	@When(value ="the selection contains an option with attributes (.+)$")
	public void addSelectedOptionAttributes(String optionAttributes){
		String[] split = optionAttributes.split(", ");
		selections.add(Arrays.asList(split));
	}
	
	@When(value = "evaluating correctness on the encryped options$")
	public void evaluateCorrectness() throws NoSuchMethodException{
		correctnessResult = ce.checkCorrectness(selections, correctness);
		selections = new ArrayList<>();
	}
	
	@Then(value="the server-side correctness should pass$")
	public void checkSuccessfulCorrectness(){
		Assert.assertTrue(correctnessResult.getResult());
		Assert.assertNull(correctnessResult.getErrors());
	}
	
	@Then(value="the server-side correctness should fail$")
	public void checkFailedCorrectness(){
		Assert.assertFalse(correctnessResult.getResult());
		Assert.assertNotNull(correctnessResult.getErrors());
	}
	
	@Then(value="finish server-side correctness test$")
	public void finishScenario(){
		correctness = new AttributesCorrectnessBuilder();
		errorCounter = new AtomicInteger(0);
	}
	
	@Then(value = "^the attribute correctness error should be (.+), (.+)$")
	public void correctnessErrorReported(String errorType, String offendingPart) {
		errorCounter.incrementAndGet();
		List<ReportedError> errors = correctnessResult.getErrors();
		ReportedError found = null;
		for (ReportedError actualError : errors) {
			if(CorrectnessError.valueOf(errorType).equals(actualError.getErrorType()) &&
			offendingPart.equals(actualError.getReference())){
				found = actualError;
			}
		}
		Assert.assertNotNull(found);
	}
	
	@Then(value = "^the attribute correctness error does not contain any additional messages$")
	public void noMoreReportedCorrectnessErrors() {
		Assert.assertEquals(errorCounter.get(), correctnessResult.getErrors().size());
	}
	
}
