package net.javacomm.protocol.crypto;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;



public class TestCrypto {

  private final static Logger log = LogManager.getLogger(TestCrypto.class);

  public TestCrypto() {}



  @Test
  public void encryptDecryptAES() {
    String klartext = "thorsten";
    SecretKey secretAES = Crypto.createAES();
    String geheim = Crypto.encryptAES(klartext, secretAES);
    log.info(klartext);
    log.info(geheim);
    log.info(geheim);
    log.info("--");
    String orig = Crypto.decryptAES(geheim, secretAES);

    assertEquals(klartext, orig);
    log.info(orig);

  }



  /**
   * @throws NoSuchAlgorithmException
   * @throws InvalidKeySpecException
   */
  @RepeatedTest(value = 20)
  public void createRSAGenerator() throws NoSuchAlgorithmException, InvalidKeySpecException {
    KeyPair keypair = Crypto.createRSAGenerator();
    PrivateKey privateKey = keypair.getPrivate();
    PublicKey publicKey = keypair.getPublic();

    String first = java.util.Base64.getEncoder().encodeToString(privateKey.getEncoded());
    String second = java.util.Base64.getEncoder().encodeToString(publicKey.getEncoded());

    KeyPair keypair2 = Crypto.createRSAGenerator();
    PrivateKey privateKey2 = keypair2.getPrivate();
    PublicKey publicKey2 = keypair2.getPublic();

    String third = java.util.Base64.getEncoder().encodeToString(privateKey2.getEncoded());
    String fourth = java.util.Base64.getEncoder().encodeToString(publicKey2.getEncoded());

    assertNotEquals(first, third);
    assertNotEquals(second, fourth);

    log.info(privateKey.getFormat());
    log.info(privateKey.getEncoded().length);
    log.info(first.length());

    log.info(publicKey.getFormat());
    log.info(publicKey.getEncoded().length);
    log.info(second.length());

  }



  @Test
  public void loadPublicRSAKey()
      throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, NoSuchPaddingException,
      IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException {
    KeyPair keypair = Crypto.createRSAGenerator();
    PublicKey publicKey = keypair.getPublic();

    String encodedPublicKey = java.util.Base64.getEncoder().encodeToString(publicKey.getEncoded());
    log.info("Base64 encoded Public Key");
    log.info(encodedPublicKey);
    log.info("--");
    PublicKey restorePublicKey = Crypto.loadPublicRSAKey(encodedPublicKey);

    String encodedResoredKey = java.util.Base64.getEncoder().encodeToString(restorePublicKey.getEncoded());
    log.info(encodedResoredKey);

    assertEquals(publicKey, restorePublicKey);

    log.info("----------");
    log.info("Struppi");

    String struppi1 = Crypto.encrypteRSA("Struppi", publicKey);
    log.info(struppi1);
    String struppi2 = Crypto.encrypteRSA("Struppi", restorePublicKey);
    log.info(struppi2);

    PrivateKey privateKey = keypair.getPrivate();

    String decryptedText = Crypto.decryptRSA(struppi1, privateKey);

    log.info("Entschlüsselter Text: " + decryptedText);

    String decryptedText2 = Crypto.decryptRSA(struppi2, privateKey);;
    log.info("Entschlüsselter Text2: " + decryptedText2);

    assertEquals(decryptedText, decryptedText2);

//    Set<String> sec = Security.getAlgorithms("Cipher");
//    sec.forEach(s -> {
//      log.info(s);
//    });

    // AES_128/GCM/NOPADDING

//    AES_128/CBC/PKCS5Padding

  }
}
