package com.infinite.focus.server.encryptdecrypthelper;

import java.io.IOException;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.cloudinary.json.JSONObject;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

public class EncryptDecryptHelper {

	public static String key = "1234567812345678";
	public static String iv = "1234567812345678";
	
	public static String encrypt(String needToEncryptData) {
		try{
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            return Base64.getEncoder().encodeToString(cipher.doFinal(needToEncryptData.getBytes("UTF-8")));
        } catch (Exception e) {
        	System.out.println("Error while decrypting: " + e.toString());
        }
		return null;
	}
	
	public static String decrypt(String needToDecryptData) {
		try{
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
            return new String(cipher.doFinal(Base64.getDecoder().decode(needToDecryptData)));
        } catch (Exception e) {
        	System.out.println("Error while decrypting: " + e.toString());
        }
		return null;
	}
	
	public static Object getDataClassFromEncryptRequest(EncryptRequest request, Class<?> typeParameterClass) throws JsonParseException, JsonMappingException, IOException {

		if (request.isEncrypted()) {

			String encryptedData = request.getData().toString();

			System.out.println("encryptedData " + encryptedData);

			String decryptedData = EncryptDecryptHelper.decrypt(encryptedData);

			System.out.println("decryptedData " + decryptedData);
			
			//create ObjectMapper instance
		    ObjectMapper objectMapper = new ObjectMapper();

			return objectMapper.readValue(decryptedData, typeParameterClass); 
		} else {

			String data = new Gson().toJson(request.getData());

			System.out.println("data" + data);
			
			String encryptedData =  EncryptDecryptHelper.encrypt(data);
			
			System.out.println("encryptedData " + encryptedData);
			
			//create ObjectMapper instance
		    ObjectMapper objectMapper = new ObjectMapper();

			return objectMapper.readValue(data, typeParameterClass); 
		}
	}

	public static Long getIdFromEncryptRequestByKey(EncryptRequest request, String key) throws Exception {
		
		Long db_record_id = 0L;
		
		try {
			
			JSONObject jsonObj = EncryptDecryptHelper.getDataFromEncryptRequest(request);
			
			if (jsonObj.has(key)) {
				db_record_id = jsonObj.getLong(key);
			}
			
		} catch (Exception e) {
			throw new Exception(e.getLocalizedMessage());
		}
		
		return db_record_id;
	}
	
	public static JSONObject getDataFromEncryptRequest(EncryptRequest request) {

		if (request.isEncrypted()) {

			String encryptedData = request.getData().toString();

			System.out.println("encryptedData " + encryptedData);

			String decryptedData = EncryptDecryptHelper.decrypt(encryptedData);

			System.out.println("decryptedData " + decryptedData);

//			String data = decryptedData;// new Gson().toJson(decryptedData);
//
//			System.out.println("jsonString " + data);

			return new JSONObject(decryptedData);
		} else {

			String data = new Gson().toJson(request.getData());

			System.out.println("data" + data);
			
			String encryptedData =  EncryptDecryptHelper.encrypt(data);
			
			System.out.println("encryptedData " + encryptedData);

			return new JSONObject(data);
		}
	}

	public static Object getEncryptResponse(EncryptRequest request, Object response) throws Exception {

		if (request.isEncrypted()) {

			ObjectMapper mapper = new ObjectMapper();

			String json;

			try {
				json = mapper.writeValueAsString(response);
			} catch (JsonProcessingException e) {
				throw new Exception(e.getLocalizedMessage());
			}

			System.out.println("response " + json);

			String encryptedData = EncryptDecryptHelper.encrypt(json);

			System.out.println("encryptedData " + encryptedData);

			return encryptedData;
		} else {

			System.out.println("response " + response);

			return response;
		}
	}

	public static void main(String[] args) {
		String data = "{\"category_id\":1}";		
		String encryptedString = EncryptDecryptHelper.encrypt(data);
		System.out.println("Encrypted String: " + encryptedString);
		String decryptedString = EncryptDecryptHelper.decrypt(encryptedString);
		System.out.println("Decrypted String: " + decryptedString);
	}
}