/*
 * 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 com.scytl.products.ov.validation.decompress.GroupElementDecompressor;
import org.junit.BeforeClass;
import org.junit.Test;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import com.scytl.products.ov.validation.commons.beans.BigIntegerFactor;
import com.scytl.products.ov.validation.commons.beans.Factorization;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

public class GroupElementDecompressorTest {

    private static final GroupElementDecompressor _groupElementDecompressor = new GroupElementDecompressor();

    private static List<BigInteger> _ballotOptions;

    @BeforeClass
    public static void setUp() {
        _ballotOptions = new ArrayList<>();
        _ballotOptions.add(new BigInteger("2"));
        _ballotOptions.add(new BigInteger("3"));
        _ballotOptions.add(new BigInteger("5"));
        _ballotOptions.add(new BigInteger("7"));
    }

    @Test
    public void decompress_only_one_valid_value() {

        BigInteger compressedElement = new BigInteger("5");
        BigIntegerFactor expectedElement1 = new BigIntegerFactor("5");

        Factorization output = _groupElementDecompressor.decompress(compressedElement, _ballotOptions);
        List<BigIntegerFactor> decompressedElements = output.getFactors();

        assertThat(decompressedElements.size(), is(1));
        assertThat(decompressedElements.get(0), is(expectedElement1));
        assertThat(output.getRemainder(), is(BigInteger.ONE));
    }

    @Test
    public void decompress_multiple_valid_values() {

        BigInteger compressedElement = new BigInteger("15");

        BigIntegerFactor expectedElement1 = new BigIntegerFactor("3");
        BigIntegerFactor expectedElement2 = new BigIntegerFactor("5");

        Factorization output = _groupElementDecompressor.decompress(compressedElement, _ballotOptions);
        List<BigIntegerFactor> decompressedElements = output.getFactors();

        assertThat(decompressedElements.size(), is(2));
        assertThat(decompressedElements, hasItems
                (expectedElement1, expectedElement2));
        assertThat(output.getRemainder(), is(BigInteger.ONE));
    }

    @Test
    public void decompress_with_quotient_bigger_than_1_values_that_cannot_be_factorized_with_ballot_options() {

        BigInteger compressedElement = new BigInteger("33");

        Factorization output = _groupElementDecompressor.decompress(compressedElement, _ballotOptions);
        assertThat(output.getFactors().size(), is(1));
        assertThat(output.getFactors().get(0).getBase(), is(BigInteger.valueOf(3)));
        assertThat(output.getFactors().get(0).getExponent(), is(1));
        assertThat(output.getRemainder(), is(BigInteger.valueOf(11)));
    }

    @Test
    public void not_decompress_prime_number_that_is_not_factor() {

        BigInteger compressedElement = new BigInteger("43");

        Factorization output = _groupElementDecompressor.decompress(compressedElement, _ballotOptions);
        assertThat(output.getRemainder(), is(compressedElement));
        assertThat(output.getFactors().size(), is(0));
    }

    @Test
    public void decompress_value_with_duplicated_factor() {

        BigInteger compressedElement = new BigInteger("9");

        Factorization output = _groupElementDecompressor.decompress(compressedElement, _ballotOptions);

        assertThat(output.getFactors().size(), is(1));
        assertThat(output.getFactors().get(0).getBase(), is(BigInteger.valueOf(3)));
        assertThat(output.getFactors().get(0).getExponent(), is(2));
        assertThat(output.getRemainder(), is(BigInteger.valueOf(1)));
    }
}
