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

import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
import com.scytl.cryptolib.asymmetric.service.AsymmetricService;
import com.scytl.products.ov.commons.beans.TestBean;
import com.scytl.products.ov.commons.beans.TestConstructorBean;
import com.scytl.products.ov.commons.configuration.JSONSignatureConfiguration;
import com.scytl.products.ov.commons.sign.JSONSigner;

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.security.KeyPair;
import java.security.Security;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class JSONVerifierTest {

	public static final String FOO_BAR = "fooBar";

	public static final int TWO = 2;

	private static JSONVerifier sut;

	private static TestBean bean;

	private static TestConstructorBean constructorBean;

	private static KeyPair keyPairForSigning;

	private static String signedBean;

	private static String signedConstructorBean;

	@Rule
	public ExpectedException expectedException = ExpectedException.none();

	@BeforeClass
	public static void setUp() throws GeneralCryptoLibException {

        Security.addProvider(new BouncyCastleProvider());
        
		sut = new JSONVerifier();

		bean = new TestBean();
		bean.setFieldOne(FOO_BAR);
		bean.setFieldTwo(TWO);

		constructorBean = new TestConstructorBean(FOO_BAR, TWO);

		AsymmetricService asymmetricService = new AsymmetricService();
		keyPairForSigning = asymmetricService.getKeyPairForSigning();

		JSONSigner signer = new JSONSigner(JSONSignatureConfiguration.RSA_PSS_SHA256);
		signedBean = signer.sign(keyPairForSigning.getPrivate(), bean);
		signedConstructorBean = signer.sign(keyPairForSigning.getPrivate(), constructorBean);
	}

	@Test
	public void verify_correctly_a_given_signature() {
		TestBean recoveredBean = sut.verify(keyPairForSigning.getPublic(), signedBean, TestBean.class);
		assertThat(recoveredBean.getFieldOne().equals(bean.getFieldOne()), is(true));
		assertThat(recoveredBean.getFieldTwo() == bean.getFieldTwo(), is(true));
	}

	@Test
	public void verify_correctly_a_given_signature_of_a_bean_without_setters() {
		TestConstructorBean recoveredConstructorBean =
			sut.verify(keyPairForSigning.getPublic(), signedConstructorBean, TestConstructorBean.class);
		assertThat(recoveredConstructorBean.getFieldOne().equals(bean.getFieldOne()), is(true));
		assertThat(recoveredConstructorBean.getFieldTwo() == bean.getFieldTwo(), is(true));
	}

	@Test
	public void verify_correctly_a_given_signature_of_a_bean_with_setters_but_passing_class_without_setters() {
		TestConstructorBean recoveredConstructorBean =
			sut.verify(keyPairForSigning.getPublic(), signedBean, TestConstructorBean.class);
		assertThat(recoveredConstructorBean.getFieldOne().equals(bean.getFieldOne()), is(true));
		assertThat(recoveredConstructorBean.getFieldTwo() == bean.getFieldTwo(), is(true));
	}

	@Test
	public void throw_an_exception_when_wrong_bean_class_is_given() {
		expectedException.expect(IllegalArgumentException.class);
		sut.verify(keyPairForSigning.getPublic(), signedBean, Exception.class);
	}

}
