package com.gree.mall.miniapp.utils;

import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class WUtils {

    private static ExecutorService threadPool = new ThreadPoolExecutor(
            4,
            4,
            0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            new ThreadFactoryBuilder().setNameFormat("WUtils-thread-pool-%d").build(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void async(Runnable runnable){
        threadPool.execute(runnable);
    }

    public static ExecutorService buildThreadPool(int poolSize,String threadName){
        if (threadName==null){
            threadName="WUtils-thread-pool";
        }
        ExecutorService threadPool = new ThreadPoolExecutor(
                poolSize,
                poolSize,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(1024),
                new ThreadFactoryBuilder().setNameFormat(threadName+"-%d").build(),
                new ThreadPoolExecutor.AbortPolicy());
        return threadPool;
    }

    public static ExecutorService buildThreadPool(int poolSize){
        return buildThreadPool(poolSize,null);
    }

    //js逻辑的分裂
    public static String[] split(String str,String regex){
        ArrayList<String> list=new ArrayList<>();
        for (int i=0;i<str.length();){
            int ri=str.indexOf(regex,i);
            if(ri!=-1){
                list.add(str.substring(i,ri));
                i=ri+regex.length();
            }else{
                list.add(str.substring(i));
                break;
            }
        }
        if(str.endsWith(regex))list.add("");

        return list.toArray(new String[list.size()]);
    }

    //获取今天0零点时的Date对象
    public static Date getToday(){
        return new Date(System.currentTimeMillis()-(System.currentTimeMillis()+28800000)%86400000);
    }

    public static void printMethodNames(Class clazz){
        String className=clazz.getSimpleName();
        className=className.toLowerCase().charAt(0)+className.substring(1)+".";
        Method[] methods=clazz.getMethods();
        for (Method method:methods){
            String methodName=method.getName();
            if (methodName.startsWith("set")){
                System.out.println(className+methodName+"();");
            }
        }
    }


    public static void ascAdd(List<Integer> list, Integer element) {
        int size=list.size();
        for (int i=0;i<size;i++){
            if (element<list.get(i)){
                list.add(i,element);
                return;
            }
        }
        list.add(element);
    }

    private static Map<Class,Method[][]> bufferMap=new HashMap<>();

    public static <T> T clone(T model) {
        Class clazz=model.getClass();
        T clone=null;
        try {
            clone=(T)clazz.newInstance();
        }catch (Exception e){
            return null;
        }
        clone(model,clone);
        return clone;
    }

    public static <T> T clone(T source,T target) {
        Class clazz=source.getClass();
        Method[][] methods=GetMethods(clazz);
        try {
            for (Method[] method:methods){
                Object obj= method[0].invoke(source);
                method[1].invoke(target,obj);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return target;
    }

    private static Method[][] GetMethods(Class clazz){
        Method[][] methods=bufferMap.get(clazz);
        if (methods==null){
            Field[] fields=clazz.getDeclaredFields();
            int length=fields.length;
            methods=new Method[length][2];
            for (int i=0;i<length;i++){
                Field field=fields[i];
                Method[] method=methods[i];
                String fieldName=field.getName().toUpperCase().charAt(0)+field.getName().substring(1);
                try {
                    method[0]=clazz.getDeclaredMethod("get"+fieldName);
                    method[1]=clazz.getDeclaredMethod("set"+fieldName,field.getType());
                }catch (Exception e){}
            }
            bufferMap.put(clazz,methods);
        }
        return methods;
    }

    public static boolean equals(Object model1,Object model2){
        Class clazz=model1.getClass();
        if (!clazz.equals(model2.getClass())){
            return false;
        }
        Method[][] methods=GetMethods(clazz);
        for (Method[] method:methods){
            Object obj1= null;
            Object obj2= null;
            try {
                obj1= method[0].invoke(model1);
                obj2= method[0].invoke(model2);
            }catch (Exception e){}
            if (obj1==null&&obj2==null){
                continue;
            }
            if (obj1==null||obj2==null){
                return false;
            }
            if (obj1 instanceof BigDecimal){
                if (((BigDecimal)obj1).doubleValue()!=((BigDecimal)obj2).doubleValue()){
                    return false;
                }
            }else {
                if (!obj1.equals(obj2)){
                    return false;
                }
            }
        }
        return true;
    }

    public static void parseJsonKey(String jsonString) {
        JSONObject json= JSONObject.parseObject(jsonString);
        for (Map.Entry<String,Object> entry:json.entrySet()){
            Object value = entry.getValue();
            String className=value.getClass().getSimpleName();
            String key=WUtils.toCamelCase(entry.getKey());
            System.out.println(String.format("private %s %s;",className,key));
        }
    }

    public static String toCamelCase(String name){
        String[] strs=name.split("_");
        name=strs[0];
        for (int i=1;i<strs.length;i++){
            String str=strs[i];
            name+=str.toUpperCase().charAt(0)+str.substring(1);
        }
        return name;
    }

    public static void parseJsonKey(String jsonString, Class modelClass) {
        List<String> fieldNameList=new ArrayList<>();
        for (Field field:modelClass.getDeclaredFields()){
            fieldNameList.add(field.getName());
        }
        JSONObject json= JSONObject.parseObject(jsonString);
        for (Map.Entry<String,Object> entry:json.entrySet()){
            Object value = entry.getValue();
            String className=value.getClass().getSimpleName();
            String key=WUtils.toCamelCase(entry.getKey());
            if (fieldNameList.remove(key)){
                continue;
            }
            System.out.println(String.format("private %s %s;",className,key));
        }
        System.out.println(fieldNameList);
    }

    public static Map buildDemo(Class modelClass) {
        Map<String,Object> map=new HashMap();
        List<Field> fieldList=new ArrayList<>();
        if (Arrays.asList(modelClass.getInterfaces()).contains(Map.class)){
            return map;
        }
        System.out.println(modelClass.getName());
        for (;modelClass != Object.class;modelClass = modelClass.getSuperclass()){
            Field[] declaredFields = modelClass.getDeclaredFields();
            if (declaredFields.length==0){
                continue;
            }
            fieldList.addAll(Arrays.asList(declaredFields));
        }

        for (Field field:fieldList){
            String key=field.getName();
            Class type=field.getType();
            Object value=null;
            List<Class> classes = Arrays.asList(type.getInterfaces());
            if (type==String.class){
                value="";
            }else if (type==Boolean.class){
                value=false;
            }else if (type.getSuperclass() == Number.class){
                value=1;
            }else if (type==BigDecimal.class){
                value=1;
            }else if (type==Date.class){
                value="2019-11-11 11:11:11";
            }else if (Arrays.asList(type.getInterfaces()).contains(Collection.class)){
                value=new ArrayList<>();
            }else if (type.isArray()){
                value=new ArrayList<>();
            }else{
                value=buildDemo(type);
            }
            map.put(key,value);
        }
        return map;
    }
}


