/**
 *
 */
package cn.citycraft.GsonAgent.api.utils;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

/**
 * Gson代理工具类(来自7老板)
 *
 * @since 2016年1月5日 下午1:33:57
 * @author 尘曲,喵♂呜
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Utils {
    public static final String[] REPLACEMENT_CHARS;
    public static final String[] HTML_SAFE_REPLACEMENT_CHARS;

    static {
        REPLACEMENT_CHARS = new String[128];
        for (int i = 0; i <= 0x1f; i++) {
            REPLACEMENT_CHARS[i] = String.format("\\u%04x", i);
        }
        REPLACEMENT_CHARS['"'] = "\\\"";
        REPLACEMENT_CHARS['\\'] = "\\\\";
        REPLACEMENT_CHARS['\t'] = "\\t";
        REPLACEMENT_CHARS['\b'] = "\\b";
        REPLACEMENT_CHARS['\n'] = "\\n";
        REPLACEMENT_CHARS['\r'] = "\\r";
        REPLACEMENT_CHARS['\f'] = "\\f";
        HTML_SAFE_REPLACEMENT_CHARS = REPLACEMENT_CHARS.clone();
        HTML_SAFE_REPLACEMENT_CHARS['<'] = "\\u003c";
        HTML_SAFE_REPLACEMENT_CHARS['>'] = "\\u003e";
        HTML_SAFE_REPLACEMENT_CHARS['&'] = "\\u0026";
        HTML_SAFE_REPLACEMENT_CHARS['='] = "\\u003d";
        HTML_SAFE_REPLACEMENT_CHARS['\''] = "\\u0027";
    }

    public static <T> T deepCopyObject(final T obj) {
        try {
            return (T) obj.getClass().getDeclaredMethod("deepCopy").invoke(obj);
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static Field getDeclareField(final Class clzz, final String fieldName) throws Exception {
        final Field field = clzz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field;
    }

    public static Object invokeField(final Object object, final Field field) {
        try {
            return field.get(object);
        } catch (final Exception e) {
        }
        return null;
    }

    public static int[] invokeIntArrayField(final Object object, final Field field) {
        try {
            return (int[]) invokeField(object, field);
        } catch (final Exception e) {
        }
        return null;
    }

    public static int invokeIntField(final Object object, final Field field) {
        try {
            return ((Number) invokeField(object, field)).intValue();
        } catch (final Exception e) {
        }
        return 0;
    }

    public static String invokeStringField(final Object object, final Field field) {
        try {
            return (String) invokeField(object, field);
        } catch (final Exception e) {
        }
        return null;
    }

    public static void modifyField(final Object object, final Field field, final Object value) {
        try {
            field.set(object, value);
        } catch (final Exception e) {
        }
    }

    public static <T> T newInstance(final Class<T> clzz) {
        try {
            final Constructor<T> constructor = clzz.getDeclaredConstructor();
            constructor.setAccessible(true);
            return constructor.newInstance();
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T newInstance(final Class<T> clzz, final Class[] types, final Object[] args) {
        if (args.length == 0 || types.length == 0) {
            return newInstance(clzz);
        }
        try {
            final Constructor<T> constructor = clzz.getDeclaredConstructor(types);
            constructor.setAccessible(true);
            return constructor.newInstance(args);
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T newInstance(final Class<T> clzz, final Object... args) {
        final Class[] argClasses = new Class[args.length];
        for (int i = 0; i < argClasses.length; i++) {
            argClasses[i] = args[i].getClass();
        }
        return newInstance(clzz, argClasses, args);
    }
}
