package com.sunxung.factoring.component.aspect;

import com.sunxung.factoring.component.util.SpringUtil;
import com.sunxung.factoring.component.util.StringUtil;
import com.sunxung.factoring.component.util.ThreadLocalUtil;
import com.sunxung.factoring.entity.GridPage;
import com.sunxung.factoring.entity.ResponseJson;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.Org;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.OrgService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description:web层数据响应切面
 * @Date:2017年6月7日 下午2:41:49
 */
@Aspect
@Component
public class JsonResultAspect {

    /**
     * 字典项类路径名称
     */
    private final static String DICTIONARY_NAME = Dictionary.class.getName();
    /**
     * 组织机构类路径名称
     */
    private final static String ORG_NAME = Org.class.getName();
    /**
     * 缓存类路径
     */
    private static Map<String, Map<String, List<Method>>> classCache = new HashMap<String, Map<String, List<Method>>>();

    /**
     * 响应返回数据包装
     *
     * @param pjp 切入点
     * @throws Throwable
     */
    @SuppressWarnings("unchecked")
    @Around(value = "execution(public * com.sunxung.factoring.web..*.do*(..))")
    public Object doAfterReturning(ProceedingJoinPoint pjp) throws Throwable {
        Object obj = pjp.proceed();
        if (obj instanceof GridPage) {
            try {
                fillOtherInfo((GridPage<Object>) obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return obj;
        } else if (obj instanceof ResponseJson) {
            return obj;
        } else if (obj instanceof ResponseEntity) {
            return obj;
        } else {
            return new ResponseJson(obj);
        }
    }

    /**
     * 填充字典项、组织机构信息
     */
    private void fillOtherInfo(GridPage<Object> gridPage) throws Exception {
        List<Object> resultList = gridPage.getRows();
        if (resultList == null || resultList.isEmpty()) {
            return;
        }
        Class<? extends Object> cls = resultList.get(0).getClass();
        if (classCache.get(cls.getName()) == null) {
            invokeMethod(cls);
        }
        fillDictionary(classCache.get(cls.getName()).get(DICTIONARY_NAME), resultList);
        // fillOrg(classCache.get(cls.getName()).get(ORG_NAME), resultList);
    }

    private void invokeMethod(Class<? extends Object> cls) {
        List<Method> orgMethods = new ArrayList<Method>();
        List<Method> dictMethods = new ArrayList<Method>();
        for (Method method : cls.getMethods()) {
            if (method.getReturnType().getName().equals(DICTIONARY_NAME)) {
                dictMethods.add(method);
            }
            if (method.getReturnType().getName().equals(ORG_NAME)) {
                orgMethods.add(method);
            }
        }
        Map<String, List<Method>> methods = new HashMap<String, List<Method>>();
        methods.put(DICTIONARY_NAME, dictMethods);
        methods.put(ORG_NAME, orgMethods);
        classCache.put(cls.getName(), methods);
    }

    /**
     * 填充组织机构
     *
     * @param methods
     * @param resultList
     */
    private void fillOrg(List<Method> methods, List<Object> resultList) {
        try {
            Long loginOrgId = ThreadLocalUtil.getOrgId();
            for (Object result : resultList) {
                for (Method method : methods) {
                    Org org = (Org) method.invoke(result);
                    if (org == null) {
                        continue;
                    }
                    Org newOrg = getOrgService().getAll(org.getId());
                    if (newOrg != null) {
                        String orgNmae = newOrg.getName();
                        if (newOrg.getParent() != null && StringUtil.isNotEmpty(newOrg.getParent().getName())
                                && !loginOrgId.equals(newOrg.getId())) {
                            orgNmae = newOrg.getParent().getName() + " -> " + orgNmae;
                        }
                        org.setName(orgNmae);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 填充字典项
     *
     * @param methods
     * @param resultList
     */
    private void fillDictionary(List<Method> methods, List<Object> resultList) {
        try {
            for (Object result : resultList) {
                for (Method method : methods) {
                    Dictionary dictionary = (Dictionary) method.invoke(result);
                    if (dictionary == null) {
                        continue;
                    }
                    Dictionary newDictionary = getDictionaryService().get(dictionary.getId());
                    if (newDictionary != null) {
                        dictionary.setName(newDictionary.getName());
                        dictionary.setCode(newDictionary.getCode());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static DictionaryService dictionaryService;

    private DictionaryService getDictionaryService() {
        if (dictionaryService == null) {
            dictionaryService = SpringUtil.getBeanByType(DictionaryService.class);
        }
        return dictionaryService;
    }

    private static OrgService orgService;

    private OrgService getOrgService() {
        if (orgService == null) {
            orgService = SpringUtil.getBeanByType(OrgService.class);
        }
        return orgService;
    }
}
