package ru.yandex.webmaster3.api.http.util;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Base64;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author avhaliullin
 */
public class StringObfuscationUtil {
    //          128 bit ==> 16 bytes =>      0123456701234567
    private static final byte[] KEY_BYTES = "Thisisnotsecurty".getBytes();
    private static final byte[] IV_BYTES = "Notasecuritytoo!".getBytes();
    private static final Key KEY = new SecretKeySpec(KEY_BYTES, "AES");
    private static final IvParameterSpec IV = new IvParameterSpec(IV_BYTES);
    private static final String METHOD = "AES/CBC/PKCS5PADDING";

    private static final int RANDOM_PREFIX_LEN = 4;

    public static String encodeASCII(String s) {
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(METHOD);
            cipher.init(Cipher.ENCRYPT_MODE, KEY, IV);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        try {
            byte[] prefix = new byte[RANDOM_PREFIX_LEN];
            ThreadLocalRandom.current().nextBytes(prefix);
            byte[] payload = s.getBytes();
            cipher.update(prefix);
            byte[] encrypted = cipher.doFinal(payload);
            return Base64.getUrlEncoder().encodeToString(encrypted);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public static String decodeASCII(String s) {
        Cipher cipher;
        try {
            cipher = Cipher.getInstance(METHOD);
            cipher.init(Cipher.DECRYPT_MODE, KEY, IV);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        try {
            byte[] binary = Base64.getUrlDecoder().decode(s);
            String decrypted = new String(cipher.doFinal(binary), StandardCharsets.US_ASCII);
            return decrypted.substring(RANDOM_PREFIX_LEN);
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }
}
