package com.younike.common.utils.encrypt;

import com.younike.common.utils.string.StringUtils;
import org.springframework.web.util.HtmlUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Objects;


/**
 * 自定义加密解密
 *
 * @author zhougd
 */
public class Encrypt {

    /**
     * Mybatis字段异或加密KEY
     */
    public static final int MYBATIS_SECRECT_KEY = 1024;

    /**
     * 自定义加密
     *
     * @param password
     * @return
     */
    private static String encryptKey(String param1, String param2, String password) {

        if (StringUtils.isEmpty(password)) {
            return null;
        }

        password = HtmlUtils.htmlUnescape(password);

        String replaceChar = " ";
        for (int i = 0; i < param1.length(); i++) {
            if (!StringUtils.isNumber(param1.substring(i, i + 1))) {
                replaceChar = param1.substring(i, i + 1);
                break;
            }
        }

        String result = StringUtils.leftPad(String.valueOf(password.length()), 3).replace(" ", replaceChar);

        int times = 0;
        int residue = password.length() % param2.length();
        if (residue == 0) {
            times = password.length() / param2.length();
        } else {
            times = password.length() / param2.length() + 1;
        }

        int keyLength = param2.length();
        int idLength = param1.length() / times;

        String[] keys = new String[times];
        String[] userIds = new String[times];

        for (int i = 0; i < times; i++) {
            if (i == times - 1) {
                keys[i] = StringUtils.substring(password, i * keyLength);
                userIds[i] = StringUtils.substring(param1, i * idLength);
            } else {
                keys[i] = StringUtils.substring(password, i * keyLength, (i + 1) * keyLength);
                userIds[i] = StringUtils.substring(param1, i * idLength, (i + 1) * idLength);
            }
        }

        for (int i = times - 1; i >= 0; i--) {
            result = result + keys[i] + userIds[i];
        }

        System.out.println("自定义加密=" + result);
        return result;
    }

    /**
     * 加密
     *
     * @param userId
     * @param loginName
     * @param password
     * @return
     * @throws Exception
     */
    public static String encryptStr(String userId, String loginName, String password) throws Exception {
        return encryptKey(userId, loginName, password);
    }

    /**
     * 自定义解密
     *
     * @param userId
     * @param loginName
     * @param password
     * @return
     */
    private static String decryptKey(String userId, String loginName, String password) {

        if (StringUtils.isEmpty(password)) {
            return null;
        }

        String result = StringUtils.EMPTY;

        String passwordLength = StringUtils.substring(password, 0, 3);
        for (int i = 0; i < passwordLength.length(); i++) {
            if (StringUtils.isNumber(passwordLength.substring(i, i + 1))) {
                passwordLength = StringUtils.right(passwordLength, passwordLength.length() - i);
                break;
            }
        }

        int times = 0;
        int residue = Integer.valueOf(passwordLength) % loginName.length();
        if (residue == 0) {
            times = Integer.valueOf(passwordLength) / loginName.length();
        } else {
            times = Integer.valueOf(passwordLength) / loginName.length() + 1;
        }

        int keyLength = loginName.length();
        int idLength = userId.length() / times;
        int idResidue = userId.length() - idLength * times;

        String[] keys = new String[times];
        password = StringUtils.right(password, password.length() - 3);

        for (int i = times - 1; i >= 0; i--) {
            if (i == 0) {
                password = StringUtils.left(password, password.length() - idLength - idResidue);
                keys[i] = password;
            } else {
                password = StringUtils.left(password, password.length() - idLength);
                keys[i] = StringUtils.right(password, keyLength);
                password = StringUtils.left(password, password.length() - keyLength);
            }

            result = result + keys[i];
        }
        System.out.println("自定义解密=" + result);

        return result;
    }

    /**
     * 解密
     *
     * @param userId
     * @param loginName
     * @param password
     * @return
     * @throws Exception
     */
    public static String decryptStr(String userId, String loginName, String password) throws Exception {
        return decryptKey(userId, loginName, new String(password));
    }




    /**
     * Mybatis字段具体加密
     *
     * @param field
     * @param parameterObject
     * @param <T>
     * @return
     * @throws IllegalAccessException
     */
    public static <T> T encrypt(Field field, T parameterObject) throws IllegalAccessException {
        field.setAccessible(true);
        Object object = field.get(parameterObject);
        field.set(parameterObject, xorEncode(String.valueOf(object)));
        return parameterObject;
    }

    /**
     * 异或加密
     *
     * @param param
     * @return
     */
    public static String xorEncode(String param) {
        char[] charArray = param.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            charArray[i] = (char) (charArray[i] ^ MYBATIS_SECRECT_KEY);
        }
        return new String(charArray);
    }


    /**
     * Mybatis属性具体解密
     *
     * @param field
     * @param result
     * @throws IllegalAccessException
     */
    public static void decrypt(Field field, Object result) throws IllegalAccessException {
        field.setAccessible(true);
        Object object = field.get(result);
        field.set(result, xorEncode(String.valueOf(object)));
    }

    public static void main(String[] args) {

        try {
//			String encryptKey = encryptStr("ON1900054", "20", "1.2");
//			String decryptKey = decryptStr("ON1900054", "20", encryptKey);
//			System.out.println("64位加密=" + encryptKey);
//			System.out.println("64位解密=" + decryptKey);
            System.out.println(xorEncode("2012"));
            System.out.println(xorEncode(xorEncode("2012")));
            System.out.println(xorEncode("20121"));
            System.out.println(xorEncode(xorEncode("20121")));
            System.out.println(xorEncode("1112"));
            System.out.println(xorEncode(xorEncode("1112")));
            System.out.println(xorEncode("abc12"));
            System.out.println(xorEncode(xorEncode("abc12")));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
