package com.brilliance.mda.runtime.mda.driver;

import com.brilliance.mda.runtime.mda.*;
import com.brilliance.mda.runtime.mda.impl.AbstractDaoSession;
import com.brilliance.mda.runtime.mda.impl.EnvConfig;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class MdaEnv {

    private static String encoding = "UTF-8";
    public static String LANG = "CN";
    private static Locale locale = Locale.SIMPLIFIED_CHINESE;

    private static Map<String, Map<String, List<Object>>> sessionContext = new ConcurrentHashMap<>();

   // public static ApplicationContext appContext = null;
    public static ConfigurableListableBeanFactory beanFactory = null;
    private static ThreadLocal<IContext> tl = new ThreadLocal<IContext>();
    private static ThreadLocal<IAuthInfo> tl_infos = new ThreadLocal<IAuthInfo>();
    private static ThreadLocal<Map<String, Object>> tl_gridEtyData = new ThreadLocal<>();
    private static ThreadLocal<String> moduleListCheckErrorItem = new ThreadLocal<>();

    public static <T> T getBean(String beanId, Class<T> clazz) {
        return beanFactory.getBean(beanId, clazz);
    }

    public static <T> T getBean(Class<T> clazz) {
        return beanFactory.getBean(clazz);
    }

    public static Object getBean(String beanId) {
        Object bean = null;
        try {
            bean = beanFactory.getBean(beanId);
        } catch (Exception e) {
        }

        return bean;

    }


    public static void setContext(IContext ctx) {
        //取消设置默认语言，因由TD决定
        //ctx.storeData("LANG",LANG);
        tl.set(ctx);
    }

    public static IContext getContext() {
        return tl.get();
    }

    public static void rmContext() {
        tl.remove();
        AbstractDaoSession daoSession = beanFactory.getBean(AbstractDaoSession.class);
        if (daoSession != null && daoSession.isOpenTrans()) {
            //防止有未关闭的事务
            daoSession.dbRollback();
        }
    }

    public static void clearContext() {
        rmContext();
        tl_infos.remove();
    }

    public static void clear(Object object) {
        if (object == null)
            return;
        if ((object instanceof IBaseObject)) {
            ((IBaseObject) object).clear();
        } else if ((object instanceof Collection)) {
            ((Collection) object).clear();
        } else if ((object instanceof Map)) {
            ((Map) object).clear();
        }
    }

    @SuppressWarnings("rawtypes")
    public static boolean isEmpty(Object obj) {
        if (obj == null)
            return true;
        if (obj instanceof String)
            return ((String) obj).length() == 0 || ((String) obj).equals(" ");
        if (obj instanceof BigDecimal)
            return ((BigDecimal) obj).doubleValue() == 0.0D;
        if ((obj instanceof Number)) {
            return ((Number) obj).doubleValue() == 0.0D;
        }
        if ((obj instanceof Collection)) {
            return ((Collection) obj).isEmpty();
        }
        if ((obj instanceof Map)) {
            return ((Map) obj).isEmpty();
        }
        if (obj instanceof IModule) {
            return isEmpty(MdaDriver.getDatafield((IModule) obj, "inr"));
        }
        if (obj instanceof IDatafield)
            return isEmpty(((IDatafield) obj).getValue());
        return false;
    }

    public static void setAuthInfo(IAuthInfo authInfo) {
        tl_infos.set(authInfo);
    }

    public static IAuthInfo getAuthInfo() {
        return tl_infos.get();
    }

    public static String getLoginUser() {
        //结合具体环境，从tl_infos中获取
        return tl_infos.get().getUserId();
    }

    public static String getEncoding() {
        return encoding;
    }

    public static void setEncoding(String encoding) {
        MdaEnv.encoding = encoding;
    }

    public static String getLang() {
        String lang = (String) getContext().restoreData("LANG");
        return lang;
    }

    public static <T> T getSessionContextValue(String key) {
        String uid = MdaEnv.getAuthInfo().getUserId();
        if (!sessionContext.containsKey(uid)) {
            return null;
        }
        if (!sessionContext.get(uid).containsKey(key)) {
            MdaEnv.getContext().setErrorCode(111);
            return null;
        }
        return (T) sessionContext.get(uid).get(key).get(0);
    }

    public static void setSessionContext(String key, Object... obj) {
        if (key == null) return;
        String uid = MdaEnv.getAuthInfo().getUserId();
        if (!sessionContext.containsKey(uid)) {
            sessionContext.put(uid, new ConcurrentHashMap<String, List<Object>>());
        }
        sessionContext.get(uid).put(key, Arrays.asList(obj));
    }

    /**
     * 该方法需在用户登录时先调用一次，保证把之前的缓存清除
     *
     * @param uid
     */
    public static void clearSessionContext(String uid) {
        if (sessionContext.containsKey(uid)) {
            sessionContext.get(uid).clear();
        }
    }

    public static String getRootPath() {
        return getBean(EnvConfig.class).getRootPath();
    }

    public static void removeAuthInfo() {
        tl_infos.remove();
    }

    private static ThreadLocal<Map<String, Object>> attrs = new ThreadLocal<>();

    public static void removeAttrs() {
        attrs.remove();
    }

    public static void setAttribute(String key, Object obj) {
        if (attrs.get() == null) {
            attrs.set(new HashMap<String, Object>());
        }
        attrs.get().put(key, obj);
    }

    public static Object getAttribute(String key) {
        if (key == null) return null;
        return attrs.get().get(key);
    }

    public static String getSessionId() {
        String sessionId = (String) attrs.get().get("sessionId");
        if (sessionId != null) {
            return sessionId;
        }
        return "";
    }

    public static void setGridData(String title, String columns, IStream vals) {
        Map<String, Object> data = new HashMap<>();
        data.put("title", title);
        data.put("columns", columns);
        data.put("vals", vals);
        tl_gridEtyData.set(data);
    }

    public static Map<String, Object> getGridData() {
        return tl_gridEtyData.get();
    }

    public static void removeGridData() {
        tl_gridEtyData.remove();
    }

    public static Locale getLocale() {
        if (locale == null)
            locale = Locale.SIMPLIFIED_CHINESE;
        return locale;
    }

    public static void setLocale(Locale temp_locale) {
        locale = temp_locale;
    }

    public static String getModuleListCheckErrorItem() {
        return moduleListCheckErrorItem.get();
    }

    /**
     * ModuleList 执行checkAll时，记录 module 的 path + index，方便前端页面显示错误信息
     *
     * @param prefix
     */
    public static void setModuleListCheckItem(String prefix) {
        moduleListCheckErrorItem.set(prefix);
    }

    public static void removeModuleListCheckErrorItem() {
        moduleListCheckErrorItem.remove();
    }
}
