package com.palmnest.application.core.util;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


//import java.util.Base64;

public class Java_AES_Cipher {

	private static String CIPHER_NAME    = "AES/CBC/PKCS5PADDING";
	private static int    CIPHER_KEY_LEN = 16; //128 bits

	private static Logger LOG = LoggerFactory.getLogger(Java_AES_Cipher.class);

	/**
	 * Generate 16 bytes initialization vector
	 *
	 * @return iv - initialization vector
	 */
	public static String makeIv() {
		try {
			Random random = ThreadLocalRandom.current();
			byte[] randomBytes = new byte[10];
			random.nextBytes(randomBytes);
			//String encoded = Base64.getUrlEncoder().encodeToString(randomBytes);
			String encoded = Base64.encodeBase64String(randomBytes);
			return encoded;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return "1234567891234567";

	}

	/**
	 * Encrypt data using AES Cipher (CBC) with 128 bit key
	 *
	 * @param key  - key to use should be 16 bytes long (128 bits)
	 * @param data - data to encrypt
	 * @return encryptedData data in base64 encoding with iv attached at end after a :
	 */
	public static String encrypt(String key, String data) {

		LOG.info("encrypt start===");
		LOG.info("encrypt key===" + key);
		LOG.info("encrypt data===" + data);

		try {
			String iv = Java_AES_Cipher.makeIv();
			if (key.length() < Java_AES_Cipher.CIPHER_KEY_LEN) {
				int numPad = Java_AES_Cipher.CIPHER_KEY_LEN - key.length();

				for (int i = 0; i < numPad; i++) {
					key += "0"; //0 pad to len 16 bytes
				}

			} else if (key.length() > Java_AES_Cipher.CIPHER_KEY_LEN) {
				key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
			}


			IvParameterSpec initVector = new IvParameterSpec(iv.getBytes("UTF-8"));
			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

			Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
			cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);

			byte[] encryptedData = cipher.doFinal((data.getBytes()));

			//String base64_EncryptedData = Base64.getEncoder().encodeToString(encryptedData);
			//String base64_IV = Base64.getEncoder().encodeToString(iv.getBytes("UTF-8"));
			String base64_EncryptedData = Base64.encodeBase64String(encryptedData);
			String base64_IV = Base64.encodeBase64String(iv.getBytes("UTF-8"));

			LOG.info("encrypt end===");

			return base64_EncryptedData + ":" + base64_IV;

		} catch (Exception ex) {
			ex.printStackTrace();
			LOG.info(LogExceptionStackUtil.LogExceptionStack(ex));
			System.out.println(LogExceptionStackUtil.LogExceptionStack(ex));
			throw new RuntimeException("请检查网络或稍后再试" + LogExceptionStackUtil.LogExceptionStack(ex));
		}
	}

	/**
	 * Decrypt data using AES Cipher (CBC) with 128 bit key
	 *
	 * @param key  - key to use should be 16 bytes long (128 bits)
	 * @param data - encrypted data with iv at the end separate by :
	 * @return decrypted data string
	 */

/*    public static String decrypt(String key, String data) {
        try {

            //String[] parts = data.split("");
        	String[] parts = data.split("\\|");

            //IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(parts[1]));
            IvParameterSpec iv = new IvParameterSpec(Base64.decodeBase64(parts[1]));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            //byte[] decodedEncryptedData = Base64.getDecoder().decode(parts[0]);
            byte[] decodedEncryptedData = Base64.decodeBase64(parts[0]);

            byte[] original = cipher.doFinal(decodedEncryptedData);

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }*/
	public static String decrypt(String key, String data) {
		try {

			String[] parts = data.split(":");

			//IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(parts[1]));
			IvParameterSpec iv = new IvParameterSpec(Base64.decodeBase64(parts[1]));
			SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

			Cipher cipher = Cipher.getInstance(Java_AES_Cipher.CIPHER_NAME);
			cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

			//byte[] decodedEncryptedData = Base64.getDecoder().decode(parts[0]);
			byte[] decodedEncryptedData = Base64.decodeBase64(parts[0]);

			byte[] original = cipher.doFinal(decodedEncryptedData);

			return new String(original);
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return null;
	}

}