package com.ssyf.plugs.cache.helper;


import cn.hutool.json.JSONUtil;
import com.ssyf.common.core.util.SimpleLockerUtil;
import com.ssyf.common.core.util.TypeEnhanceUtil;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.cache.Cache;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.support.SimpleValueWrapper;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;

/**
 * 缓存帮助类
 * @author huwei
 * @date 2022/11/29 8:50
 */
public class CacheHelper {

    /**
     * 封装数据标识
     */
    private static final String WRAP_VALUE_MARK = "@@#@disSerializationPrefix@@#@";

    /**
     * 获取或创建缓存对象
     * @param cacheName
     * @param cacheManager
     * @return
     */
    public static Cache getOrCreateCache(String cacheName , EhCacheCacheManager cacheManager) {
        Cache cache = cacheManager.getCache(cacheName);
        if (cache == null) {
            Lock lock = SimpleLockerUtil.getLocker(cacheName ,CacheHelper.class.getSimpleName() ,"getOrCreateCache");
            lock.lock();
            try{
                cache = cacheManager.getCache(cacheName);
                if (cache == null) {
                    cacheManager.getCacheManager().addCacheIfAbsent(cacheName);
                    cache = cacheManager.getCache(cacheName);
                }
            }finally {
                lock.unlock();
            }
        }
        return cache;
    }

    /**
     * 封装存储值，规避存储值不能序列化而导致的问题
     * @param value
     * @return
     */
    public static <T> Object wrapValue(T value){
        if(value == null){
            return null;
        }
        //基础类型
        if(TypeEnhanceUtil.isBaseType(value)){
            return value;
        }
        //尝试封装内容,在不改变缓存数据格式的基础上，添加数据封装标识，用于数据还原
        try{
            Map<Object, Object> map = JSONUtil.toBean(JSONUtil.toJsonStr(value), Map.class);
            map.put(WRAP_VALUE_MARK, value.getClass());
            return map;
        }catch (Exception e){}
        //没有序列化，存在缓存失败的风险
        if(!Serializable.class.isAssignableFrom(value.getClass())) {
            return new ValueWrapper<T>().setValue(value);
        }
        //不做处理
        return value;
    }

    /**
     * 解析数据
     * @param wrapValue
     * @param <T>
     * @return
     */
    public static final <T> T parseValue(Object wrapValue) {
        if(wrapValue == null){
            return null;
        }
        //springboot封装
        if(SimpleValueWrapper.class.isAssignableFrom(wrapValue.getClass())){
            return parseValue(((SimpleValueWrapper)wrapValue).get());
        }

        //封装数据对象解析
        if(ValueWrapper.class.isAssignableFrom(wrapValue.getClass())){
            return parseValue(((ValueWrapper)wrapValue).getValue());
        }
        //封装标识解析
        if(Map.class.isAssignableFrom(wrapValue.getClass())){
            Map<Object, Object> map = (Map<Object, Object>) wrapValue;
            if(map.get(WRAP_VALUE_MARK) != null){
                //复制，防止操作源数据
                Map<Object ,Object> temp = new HashMap<>();
                temp.putAll(map);
                Class<?> cls = (Class<?>) temp.get(WRAP_VALUE_MARK);
                temp.remove(WRAP_VALUE_MARK);
                return (T) JSONUtil.toBean(JSONUtil.toJsonStr(temp) ,cls);
            }
        }
        //原值
        return (T) wrapValue;
    }

    /**
     * 数据封装类
     * @author huwei
     * @date 2023/9/21 14:31
     */
    @Data
    @Accessors(chain = true)
    public static class ValueWrapper<T> implements Serializable{
        T value;
    }
}
