package kr.co.icontrols.ilp300_700.ftp;

import android.util.Base64;
import android.util.Log;

import com.artncore.commons.define;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;

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

public class AES {
    /** 사진 암호화 관련 */
    boolean bLOG_WARN = true;
    public static final String ALGORITHM = "AES";
    public static final String TRANSFORMATION = ALGORITHM + "/ECB/PKCS5Padding";
    public static final String TRANSFORMATION_NOPADDING = ALGORITHM + "/ECB/NoPadding";
    private final static String TAG = "API_AES";
    private void LOG_WARN(String log) {
        if (bLOG_WARN) Log.w(TAG, log);
    }
    private void LOG(String log) {
        if (bLOG_WARN) Log.v(TAG, log);
    }


    private boolean isUusePadding = false;

    public void SetType(boolean _isUusePadding)
    {
        isUusePadding = _isUusePadding;
    }

    private Cipher initCryptConfig(int mode) {
        Cipher cipher = null;
        try {
            byte[] hKey = getAESKey();
            if (hKey != null) {
                if(isUusePadding)
                {
                    cipher = Cipher.getInstance(TRANSFORMATION_NOPADDING);
                }
                else
                {
                    cipher = Cipher.getInstance(TRANSFORMATION);
                }

                SecretKeySpec key = new SecretKeySpec(hKey, ALGORITHM);
                cipher.init(mode, key);
            }
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] initCryptConfig(int mode)");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        }
        return cipher;
    }

    private byte[] getAESKey() {
        byte[] hKeyData = null;
        try {
           //AES_Key aes_key = new AES_Key();
            //String strKey_en = aes_key.encryptString("I/ZqCpsbHk47KC81");
            //String strKey_en = aes_key.encryptString("VISITOR_PICTURE_");

            String strKey = "RAsqCpsb4287C81d";//aes_key.decryptString(strKey_en);
            //Log.d("AES","------------------------------AES ->USE ECB , Key : (for AES KEY),  En Key is : " + strKey_en + ", De Key : " + strKey);
            //String strKey =  aes_key.decryptString(InitInfo.getAES_Key(aes_key));
            //String strKey =  aes_key.decryptString(InitInfo.getAESKeyString());
            hKeyData = new byte[16];
            byte[] b = strKey.getBytes("UTF-8");
            int len = b.length;
            if (len > hKeyData.length) {
                len = hKeyData.length;
            }
            System.arraycopy(b, 0, hKeyData, 0, len);
            return hKeyData;
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] getAESKey()");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        }
        return hKeyData;
    }


    /**
     * ByteArray 암호화
     * @param byteArray
     * @return
     */
    public byte[] encryptByteArray(byte[] byteArray) {
        byte[] output = null;

        try {
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            if (cipher != null) {
                //String 정보 암호화
                output = cipher.doFinal(byteArray);
            }
           // Log.d("AES","------------------------------AES ->Input ByteArray is : " + InitInfo.UtillToByteString(byteArray) + ", En Key : " + InitInfo.UtillToByteString(output));
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        } finally {

        }

        return output;
    }

    public String encryptPictureFileToHex(File sourceFile) {
        InputStream input = null;
        String result = "";
        String original_str = "";
        try {
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            if (cipher != null) {
                input = new BufferedInputStream(new FileInputStream(sourceFile));
                LOG("[encryptPictureFile] input.available [" + input.available() + "]");
                byte[] buffer = new byte[1024];
                int read = -1;
                while((read = input.read(buffer)) != -1) {
                    byte[] original = Arrays.copyOf(buffer, read);
                    byte[] array = cipher.update(buffer, 0, read);
                    original_str += Base64.encodeToString(original , 0);
                    result += Base64.encodeToString(array , 0);
                }
                byte[] array = cipher.doFinal();
                Log.d("AES","------------------------------AES ->Input File Base64Encoding is : " + original_str);
                Log.d("AES","------------------------------AES ->Input File En Base64Encoding is : " + result);
                result += Base64.encodeToString(array , 0);
                //sourceFile.delete(); // 암호화하기 이전 파일은 삭제
            } else {
                LOG_WARN("[encryptPictureFile] cipher is null!");
            }
        } catch (RuntimeException re) {
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
        } finally {
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.input.close"); }
            }
        }

        return result;
    }


    public void encryptPictureFileToHex_test(File sourceFile) {
        InputStream input = null;
        String result = "";
        String original_str = "";
        try {
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            if (cipher != null) {
                input = new BufferedInputStream(new FileInputStream(sourceFile));
                LOG("[encryptPictureFile] input.available [" + input.available() + "]");
                byte[] buffer = new byte[1024];
                int read = -1;
                while((read = input.read(buffer)) != -1) {
                    byte[] original = Arrays.copyOf(buffer, read);
                    byte[] array = cipher.update(buffer, 0, read);
                    original_str += Base64.encodeToString(original , 0);
                    result += Base64.encodeToString(array , 0);
                }
                byte[] array = cipher.doFinal();
                Log.d("AES","------------------------------AES ->Input En File  Base64Encoding is : " + result);
                Log.d("AES","------------------------------AES ->Input De File Base64Encoding is : " + original_str);

                result += Base64.encodeToString(array , 0);
                //sourceFile.delete(); // 암호화하기 이전 파일은 삭제
            } else {
                LOG_WARN("[encryptPictureFile] cipher is null!");
            }
        } catch (RuntimeException re) {
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
        } finally {
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.input.close"); }
            }
        }
    }


    /**
     * byte 복호화
     * @param byteArray
     * @return
     */
    public byte[] decryptbyteArray(byte[] byteArray) {

        byte[] output = null;
        try {
            //
            Cipher cipher = initCryptConfig(Cipher.DECRYPT_MODE);
            if (cipher != null) {
                output = cipher.doFinal(byteArray);
            }
           // Log.d("AES","------------------------------AES ->En ByteArray is : " + InitInfo.UtillToByteString(byteArray) + ", De ByteArray is : " + InitInfo.UtillToByteString(output));
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decryptPictureFile(File sourceFile, File destFile)");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        } finally {

        }
        return output;
    }

    


    /**
     * 스트링 정보 복호화
     * @param source
     * @return
     */
    public String decryptString(String source) {
        byte[] decrypt_str;
        String output = "";
        byte[] byteArray= Base64.decode(source, 0);
        try {
            //
            Cipher cipher = initCryptConfig(Cipher.DECRYPT_MODE);
            if (cipher != null) {
                decrypt_str = cipher.doFinal(byteArray);
                output = new String(decrypt_str);
            } else {

            }
            Log.d("AES","------------------------------AES ->En String is : " + source + ", De String is : " + output);
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decryptPictureFile(File sourceFile, File destFile)");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        } finally {

        }
        return output;
    }

    /**
     * 스트링 정보 암호화
     * @param source
     */
    public String encryptString(String source) {
        String output = "";
        byte[] encrypt_str = null;
        try {
//            LOG("[encryptPictureFile] sourceFile [" + sourceFile.getPath() + "]");
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            byte[] byteArray=source.getBytes("UTF-8");
            if (cipher != null) {
                //String 정보 암호화
                encrypt_str = cipher.doFinal(byteArray);
                output = Base64.encodeToString(encrypt_str,0);
            } else {
            }
            Log.d("AES","------------------------------AES ->Input String is : " + source + ", En String is : " + output);
        } catch (RuntimeException re) {
            //LogUtil.errorLogInfo("", TAG, re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
            //e.printStackTrace();
            //LogUtil.errorLogInfo("", TAG, e);
        } finally {

        }

        return output;
    }

    /**
     * 사진 정보 암호화
     * @param sourceFile
     */
    public void encryptPictureFile(File sourceFile) {
        InputStream input = null;
        OutputStream output = null;
        try {
//            LOG("[encryptPictureFile] sourceFile [" + sourceFile.getPath() + "]");
            Cipher cipher = initCryptConfig(Cipher.ENCRYPT_MODE);
            if (cipher != null) {
                input = new BufferedInputStream(new FileInputStream(sourceFile));
                LOG("[encryptPictureFile] input.available [" + input.available() + "]");
                output = new BufferedOutputStream(new FileOutputStream(define.VISITOR_PICTURE_LOCATION + "/ENCRYPTED_" + sourceFile.getName()));
                byte[] buffer = new byte[1024];
                int read = -1;
                while((read = input.read(buffer)) != -1) {
                    output.write(cipher.update(buffer, 0, read));
                }
                output.write(cipher.doFinal());
                //sourceFile.delete(); // 암호화하기 이전 파일은 삭제
            } else {
                LOG_WARN("[encryptPictureFile] cipher is null!");
            }
        } catch (RuntimeException re) {
            Log.d(TAG, ""+re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] encryptPictureFile(Fie sourceFile)");
            //e.printStackTrace();

        } finally {
            if (output != null) {
                try { output.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.output.close"); }
            }
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] encryptPictureFile.input.close"); }
            }
        }
    }

    /**
     * 방문자사진 복호화 기능 수행
     * @param sourceFile 암호화된 파일 (/sdcrad/Bestin/VisitorPicture/ 폴더에 저장)
     * @param destFile 복호화 파일 (/sdcrad/Bestin/VisitorPicture/Decrypt/ 폴더에 저장)
     * @return destFile (사진을 복호화하여 파일 리턴)
     */
    public File decryptPictureFile(File sourceFile, File destFile) {
        InputStream input = null;
        OutputStream output = null;
        try {
            if (sourceFile.exists()) {
                Cipher cipher = initCryptConfig(Cipher.DECRYPT_MODE);
                if (cipher != null) {
                    input = new BufferedInputStream(new FileInputStream(sourceFile));
                    LOG("[decryptPictureFile] input.available [" + input.available() + "]");
                    output = new BufferedOutputStream(new FileOutputStream(destFile.getPath()));
                    byte[] buffer = new byte[1024];
                    int read = -1;
                    while ((read = input.read(buffer)) != -1) {
                        output.write(cipher.update(buffer, 0, read));
                    }
                    output.write(cipher.doFinal());
                    return destFile;
                } else {
                    LOG_WARN("[decryptPictureFile] cipher is null!");
                }
            } else {
//                LOG("[decryptPictureFile] Do not need to decrypt File!! [" + destFile.getPath() + "]");
                return new File(define.VISITOR_PICTURE_LOCATION + "/" + destFile.getName()); // 기존에 암호화 안되어 저장했던 사진은 복호화 하면 안됨
            }
        } catch (RuntimeException re) {
            Log.d( TAG, ""+re);
        } catch (Exception e) {
            Log.e(TAG, "[Exception] decryptPictureFile(File sourceFile, File destFile)");

        } finally {
            if (output != null) {
                try { output.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] decryptPictureFile.output.close"); }
            }
            if (input != null) {
                try { input.close(); } catch (IOException ie) { Log.e(TAG, "[Exception] decryptPictureFile.input.close"); }
            }
        }
        return null;
    }


}
