package com.xixun.communicate;

import java.lang.reflect.Method;

/**
 * Created by Administrator on 2018/08/18.
 */

public class Base64 {

    /**
     * writer: huhx
     */
        private static final String CODES = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

        // base64解密
        public static byte[] base64Decode(String input) {
            if (input.length() % 4 != 0) {
                input=input.substring(0,input.length()-input.length() % 4);
                //throw new IllegalArgumentException("Invalid base64 input");
            }
            byte decoded[] = new byte[((input.length() * 3) / 4) - (input.indexOf('=') > 0 ? (input.length() - input.indexOf('=')) : 0)];
            char[] inChars = input.toCharArray();
            int j = 0;
            int b[] = new int[4];
            for (int i = 0; i < inChars.length; i += 4) {
                // This could be made faster (but more complicated) by precomputing
                // these index locations.
                b[0] = CODES.indexOf(inChars[i]);
                b[1] = CODES.indexOf(inChars[i + 1]);
                b[2] = CODES.indexOf(inChars[i + 2]);
                b[3] = CODES.indexOf(inChars[i + 3]);
                decoded[j++] = (byte) ((b[0] << 2) | (b[1] >> 4));
                if (b[2] < 64) {
                    decoded[j++] = (byte) ((b[1] << 4) | (b[2] >> 2));
                    if (b[3] < 64) {
                        decoded[j++] = (byte) ((b[2] << 6) | b[3]);
                    }
                }
            }
            return decoded;
        }

        // base64加密
        public static String base64Encode(byte[] in) {
            StringBuilder out = new StringBuilder((in.length * 4) / 3);
            int b;
            for (int i = 0; i < in.length; i += 3) {
                b = (in[i] & 0xFC) >> 2;
                out.append(CODES.charAt(b));
                b = (in[i] & 0x03) << 4;
                if (i + 1 < in.length) {
                    b |= (in[i + 1] & 0xF0) >> 4;
                    out.append(CODES.charAt(b));
                    b = (in[i + 1] & 0x0F) << 2;
                    if (i + 2 < in.length) {
                        b |= (in[i + 2] & 0xC0) >> 6;
                        out.append(CODES.charAt(b));
                        b = in[i + 2] & 0x3F;
                        out.append(CODES.charAt(b));
                    } else {
                        out.append(CODES.charAt(b));
                        out.append('=');
                    }
                } else {
                    out.append(CODES.charAt(b));
                    out.append("==");
                }
            }
            return out.toString();
        }

        public static void main(String[] args) {
            String input = "I love you, huhx!";
            String encode = base64Encode(input.getBytes());
            System.out.println("encode: " + encode);

            String decode = new String(base64Decode(encode));
            System.out.println("decode: " + decode);
        }


    /***
     * encode by Base64
     */
    public static String encodeBase64(byte[]input) throws Exception{
        Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
        Method mainMethod= clazz.getMethod("encode", byte[].class);
        mainMethod.setAccessible(true);
        Object retObj=mainMethod.invoke(null, new Object[]{input});
        return (String)retObj;
    }
    /***
     * decode by Base64
     */
    public static byte[] decodeBase64(String input) throws Exception{
        Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
        if (clazz==null) return null;
        Method mainMethod= clazz.getMethod("decode", String.class);
        if (mainMethod==null) return null;

        mainMethod.setAccessible(true);
        Object retObj=mainMethod.invoke(null, input);
        return (byte[])retObj;
    }


}
