package org.diagbot.bigdata.work;

import org.apache.commons.lang3.StringUtils;
import org.diagbot.bigdata.common.ApplicationCacheUtil;
import org.diagbot.bigdata.dao.model.ResultMappingFilter;
import org.diagbot.bigdata.util.BigDataConstants;
import org.diagbot.common.work.FeatureRate;
import org.diagbot.nlp.feature.FeatureType;
import org.diagbot.nlp.util.NlpCache;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName org.diagbot.bigdata.work.ResultDataProxy
 * @Description TODO
 * @Author fyeman
 * @Date 2019/1/16/016 14:55
 * @Version 1.0
 **/
public class ResultDataProxy {
    public List<FeatureRate> proxy(HttpServletRequest request, BigDataSearchData searchData, List<Map.Entry<String, Float>> featuresOrderList, String featureType) {
        int cursor = 1;
        DecimalFormat df = new DecimalFormat("0.####");
        List<FeatureRate> featureList = new ArrayList<>(10);

        Map<String, String> resultMappingVitalMap = (Map<String, String>) request.getServletContext().getAttribute(BigDataConstants.result_mapping_vital);
        Map<String, String> resultMappingDiagMap = (Map<String, String>) request.getServletContext().getAttribute(BigDataConstants.result_mapping_diag);
        Map<String, Map<String, ResultMappingFilter>> resultMappingFilterMap = (Map<String, Map<String, ResultMappingFilter>>) request.getServletContext().getAttribute(BigDataConstants.result_mapping_filter);
        for (Map.Entry<String, Float> entry : featuresOrderList) {
            //过滤特征数据, 过滤低于阈值的数据
            if (!resultFilter(request, searchData, featureType, entry.getKey(), entry.getValue())) {
                continue;
            }
            //性别年龄过滤
            Map<String, ResultMappingFilter> filterMap = resultMappingFilterMap.get(featureType);
            if (filterMap != null) {
                ResultMappingFilter filter = filterMap.get(entry.getKey());
                if (filter != null) {
                    if (filter.getSex() != null && !StringUtils.isEmpty(searchData.getSex()) && !"A".equals(searchData.getSex())
                            && filter.getSex().equals(searchData.getSex())) {      //性别过滤
                        continue;
                    }
                    //年龄过滤
                    if (filter.getAgeStart() > -1 && searchData.getAge() != 0 && searchData.getAge() < filter.getAgeStart()) {
                        continue;
                    }
                    if (filter.getAgeEnd() > -1 && searchData.getAge() != 0 && searchData.getAge() > filter.getAgeEnd()) {
                        continue;
                    }
                }
            }
            FeatureRate featureRate = new FeatureRate();
            featureRate.setRate(df.format(entry.getValue()));
            if (FeatureType.parse(featureType) == FeatureType.VITAL) {
                if (StringUtils.isEmpty(resultMappingVitalMap.get(entry.getKey()))) {
                    continue;
                } else {
                    featureRate.setFeatureName(resultMappingVitalMap.get(entry.getKey()));
                }
            } else {
                featureRate.setFeatureName(entry.getKey());
            }

            if (FeatureType.parse(featureType) == FeatureType.DIAG) {
                featureRate.setFeatureName(entry.getKey());
                if (StringUtils.isNotEmpty(resultMappingDiagMap.get(entry.getKey()))) {
                    featureRate.setExtraProperty(resultMappingDiagMap.get(entry.getKey()));
                }
            }
            featureList.add(featureRate);
            if (cursor < searchData.getLength()) {
                cursor++;
            } else {
                break;
            }
        }

        return featureList;
    }

    public boolean resultFilter(HttpServletRequest request, BigDataSearchData searchData, String featureType, String result, float threshold) {
        //过滤录入条件中已有的特征信息
        if (searchData.getInputs().get(result) != null && FeatureType.parse(featureType) != FeatureType.DIAG) {
            return false;
        }
        return true;
    }

    public Map<String, Float> synonymConvert(HttpServletRequest request, Map<String, Float> map) {
//        Map<String, String> standardInfoSynonymMap = (Map<String, String>) request.getServletContext().getAttribute(BigDataConstants.standard_info_synonym_cache);
        Map<String, String> standardInfoSynonymMap = NlpCache.getStandard_info_synonym_map();
        Map<String, Float> result = new HashMap<>();
        String synonym = "";
        for (Map.Entry<String, Float> entry : map.entrySet()) {
            synonym = standardInfoSynonymMap.get(entry.getKey());
            if (synonym != null) {
                if (result.get(synonym) == null) {
                    result.put(synonym, entry.getValue());
                } else {
                    result.put(synonym, result.get(synonym) + entry.getValue());
                }
            } else {
                result.put(entry.getKey(), entry.getValue());
            }
        }
        return result;
    }

    /**
     * 大小类数据合并
     *
     * @param request
     * @param map
     */
    public Map<String, Float> resultMerge(HttpServletRequest request, Map<String, Float> map) {
        Map<String, ApplicationCacheUtil.Node> nodesMap = (Map<String, ApplicationCacheUtil.Node>) request.getServletContext().getAttribute(BigDataConstants.standard_info_type_tree_cache);
        Map<String, Float> resultMap = new HashMap<>();
        //设定阀值
        float threshold = 0.001f;
        Map<String, Float> thresholdMap = new HashMap<>();
        for (Map.Entry<String, Float> entry : map.entrySet()) {
            if (entry.getValue() >= threshold) {
                thresholdMap.put(entry.getKey(), entry.getValue());
            }
        }

        ApplicationCacheUtil.Node node = null;
        List<String> delList = new ArrayList<>();
        for (Map.Entry<String, Float> entry : thresholdMap.entrySet()) {
            if (delList.contains(entry.getKey())) continue;

            node = nodesMap.get(entry.getKey());
            if (node != null) {
                String topName = node.getName();
                ApplicationCacheUtil.Node p = node.getParent();
                if (p != null && nodesMap.get(p.getName()) != null) {
                    topName = p.getName();
                }
                while (p != null) {
                    List<String> nodeNamesList = new ArrayList<>();
                    lookChilds(topName, p, thresholdMap, nodeNamesList);
                    if (nodeNamesList.size() > 0) {
                        topName = p.getName();
                    }
                    p = p.getParent();
                }

                if (thresholdMap.get(topName) != null) {
                    resultMap.put(topName, thresholdMap.get(topName));
                    delList.add(topName);
                }
                ApplicationCacheUtil.Node topNode = nodesMap.get(topName);
                lookChildsAndCal(resultMap, thresholdMap, topNode, delList, topNode.getName());
                delList.add(topName);
            } else {
                resultMap.put(entry.getKey(), entry.getValue());
            }
        }
        return resultMap;
    }

    private void lookChilds(String own, ApplicationCacheUtil.Node p, Map<String, Float> thresholdMap, List<String> nodeNamesList) {
        for (ApplicationCacheUtil.Node n : p.getChilds()) {
            if (own.equals(n.getName())) {
                continue;
            } else {
                if (thresholdMap.get(n.getName()) != null) {
                    nodeNamesList.add(n.getName());
                }
                if (n.getChilds().size() > 0) {
                    lookChilds("", n, thresholdMap, nodeNamesList);
                }
            }
        }
    }

    private void lookChildsAndCal(Map<String, Float> resultMap, Map<String, Float> thresholdMap, ApplicationCacheUtil.Node node, List<String> delList, String topName) {
        for (ApplicationCacheUtil.Node n : node.getChilds()) {
            if (thresholdMap.get(n.getName()) != null) {
                if (resultMap.get(topName) == null) {
                    resultMap.put(topName, thresholdMap.get(n.getName()));
                } else {
                    resultMap.put(topName, resultMap.get(topName) + thresholdMap.get(n.getName()));
                }
                delList.add(n.getName());
            }
            if (n.getChilds().size() > 0) {
                lookChildsAndCal(resultMap, thresholdMap, n, delList, topName);
            }
        }
    }
}
