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

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;

import com.scytl.products.ov.commons.beans.Ballot;
import com.scytl.products.ov.utils.ConfigObjectMapper;
import com.scytl.products.ov.validation.commons.beans.BigIntegerFactor;
import com.scytl.products.ov.validation.commons.beans.Factorization;
import com.scytl.products.ov.validation.commons.beans.ValidationFailure;
import com.scytl.products.ov.validation.commons.beans.ValidationFailureCodes;
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;

public class VoteValidatorTest {

  private static Ballot ballot;

  @BeforeClass
  public static void init() throws IOException {
    ConfigObjectMapper _configObjectMapper = new ConfigObjectMapper();
    ballot =
        _configObjectMapper
            .fromJSONFileToJava(new File("src/test/resources/l_c_ballot_lc.json"), Ballot.class);
  }

  @Test
  public void validate_when_reminder_after_factorisation_is_not_one() {
    VoteValidator voteValidator = new VoteValidator();
    Factorization factorization = getReminderFailedDecomposition();
    List<ValidationFailure> validationFailures = new ArrayList<>();
    assertFalse(voteValidator.validate(ballot, factorization, validationFailures));
    assertThat(validationFailures.size(), is(2));
    assertThat(validationFailures.get(0).getCode(), is(ValidationFailureCodes.RULE_VALIDATION));
    assertThat(validationFailures.get(1).getMessage(),
        is("There were some options left after factorizing."));
    assertThat(validationFailures.get(1).getCode(),
        is(ValidationFailureCodes.NON_FACTORIZABLE_REMAINDER));
  }

  private Factorization getReminderFailedDecomposition() {
    List<BigIntegerFactor> factors = new ArrayList<>();
    factors.add(new BigIntegerFactor("100003"));
    factors.add(new BigIntegerFactor("100019"));

    return new Factorization(BigInteger.valueOf(100003 * 100019), factors, BigInteger.TEN);
  }

  private Factorization getAllTypesOfFailureDecomposition() {
    List<BigIntegerFactor> factors = new ArrayList<>();
    factors.add(new BigIntegerFactor("100003", 3));
    factors.add(new BigIntegerFactor("100019", 2));

    return new Factorization(BigInteger.valueOf(100003 * 100019), factors, BigInteger.valueOf(13));
  }

  @Test
  public void validate_when_factorisation_contains_different_failures() {
    VoteValidator voteValidator = new VoteValidator();
    Factorization factorization = getAllTypesOfFailureDecomposition();
    List<ValidationFailure> validationFailures = new ArrayList<>();
    assertFalse(voteValidator.validate(ballot, factorization, validationFailures));
    assertThat(validationFailures.size(), is(3));
    assertThat(validationFailures.get(0).getCode(), is(ValidationFailureCodes.RULE_VALIDATION));
    assertThat(validationFailures.get(1).getCode(),
        is(ValidationFailureCodes.NON_FACTORIZABLE_REMAINDER));
    assertThat(validationFailures.get(2).getCode(), is(ValidationFailureCodes.DUPLICATED_FACTOR));
  }
}
