package com.ffii.tbms.log;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ffii.core.utils.MapUtils;
import com.ffii.core.utils.NumberUtils;


public class LogUtils{

    public static final String DIFF = "diff";
    public static final String ADD = "add";
    public static final String DEL = "del";
    public static final String SAME = "same";

    public static final String ACTION_CREATE = "Create";
    public static final String ACTION_UPDATE = "Update";
    public static final String ACTION_DELETE = "Delete";

    public static Map<String, Object> objectToMap(Object obj){
        ObjectMapper mapper = new ObjectMapper();
        Map<String, Object> map = mapper.convertValue(obj, Map.class);
        return map;
    }

    public static Map<String, Object> compare(Object newObj, Object oldObj){
        Map<String, Object> diff = new HashMap<>();
        Map<String, Object> add = new HashMap<>();
        Map<String, Object> same = new HashMap<>();

        Map<String, Object> newMap = filter(objectToMap(newObj));
        Map<String, Object> oldMap = filter(objectToMap(oldObj));

        for (Map.Entry<String,Object> entry : newMap.entrySet()){
            if(oldMap.containsKey(entry.getKey())){
                if(isNullDiff(entry.getValue(), oldMap.get(entry.getKey()))){
                    if(isBigDecimalDiff(entry.getValue(), oldMap.get(entry.getKey()))){
                        diff.put(entry.getKey(), entry.getValue());
                    }else{
                        same.put(entry.getKey(), entry.getValue());
                    }
                }else{
                    same.put(entry.getKey(), entry.getValue());
                }
                oldMap.remove(entry.getKey());
            }else{
                add.put(entry.getKey(), entry.getValue());
            }
        }
        return MapUtils.toHashMap(DIFF, diff,
                                    ADD, add,
                                    DEL, oldMap,
                                    SAME, same);
    }

    private static boolean isBigDecimalDiff(Object newObj, Object oldObj){
        if(newObj instanceof BigDecimal){
            BigDecimal n = NumberUtils.toDecimal(newObj);
            BigDecimal o = NumberUtils.toDecimal(oldObj);
            return n.compareTo(o) != 0;
        }
        return true;
    }

    private static boolean isNullDiff(Object newObj, Object oldObj){
        if(oldObj == null && newObj == null) return false;
        if(oldObj == null || newObj == null) return true;
        return !oldObj.equals(newObj);
    }

    public static Map<String, Object> filter(Map<String, Object> map){
        map.remove("created");
        map.remove("modified");
        map.remove("createdBy");
        map.remove("modifiedBy");
        map.remove("versionId");
        return map;
    }

}