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.Constants;
import org.diagbot.nlp.util.NegativeEnum;
import org.diagbot.nlp.util.NlpCache;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;

/**
 * @ClassName org.diagbot.bigdata.work.ResultDataProxy
 * @Description TODO
 * @Author fyeman
 * @Date 2019/1/16/016 14:55
 * @Version 1.0
 **/
public class ResultDataProxy {
    protected static String[] vital_filter_data = Constants.vital_filter_data;

    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 = ApplicationCacheUtil.getDoc_result_mapping_vital_map();
        Map<String, String> resultMappingDiagMap = ApplicationCacheUtil.getDoc_result_mapping_diag_map();
        Map<String, Map<String, ResultMappingFilter>> resultMappingFilterMap = ApplicationCacheUtil.getDoc_result_mapping_filter_map();
        Map<String, Map<String, String>> synonymMap = ApplicationCacheUtil.getStandard_info_synonym_map();
        for (Map.Entry<String, Float> entry : featuresOrderList) {
            //过滤特征数据, 过滤低于阈值的数据
            if (!resultFilter(request, searchData, featureType, entry.getKey(), entry.getValue(), synonymMap)) {
                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()) && !"3".equals(searchData.getSex()) && !"3".equals(filter.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()));
            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 (!featureType.equals(Constants.feature_type_diag)) {
                if (cursor < searchData.getLength()) {
                    cursor++;
                } else {
                    break;
                }
//            } else {            //诊断最多返回5个
//                if (cursor < 5) {
//                    cursor++;
//                } else {
//                    break;
//                }
//            }
        }

        return featureList;
    }

    public boolean resultFilter(HttpServletRequest request, BigDataSearchData searchData, String featureType, String result, float threshold, Map<String, Map<String, String>> synonymMap) {
        //过滤录入条件中已有的特征信息
        if (searchData.getGraphInputs().get(result) != null && FeatureType.parse(featureType) != FeatureType.DIAG) {
            return false;
        }
        if (FeatureType.parse(featureType) == FeatureType.SYMPTOM) {
            if (searchData.getGraphInputs().get(synonymMap.get(Constants.word_property_symptom).get(result))!= null) {
                return false;
            }
        }
        int searched_position = Arrays.binarySearch(vital_filter_data, result);
        if (searched_position > -1) {
            return false;
        }
        return true;
    }

    public Map<String, Float> synonymConvert(HttpServletRequest request, Map<String, Float> map, String featureType) {
        Map<String, Map<String, String>> standardInfoSynonymMap = NlpCache.getStandard_info_synonym_map();
        Map<String, Float> result = new HashMap<>();
        String lexiconId = "";
        switch (FeatureType.parse(featureType)) {
            case SYMPTOM:
                lexiconId = NegativeEnum.SYMPTOM.toString();
                break;
            case DIAG:
                lexiconId = NegativeEnum.DISEASE.toString();
                break;
            case VITAL:
                lexiconId = NegativeEnum.VITAL_RESULT.toString();
                break;
            case LIS:
                lexiconId = NegativeEnum.LIS_TYPE.toString();
                break;
            case PACS:
                lexiconId = NegativeEnum.PACS_NAME.toString();
                break;
        }
        Map<String, String> synonymMap = standardInfoSynonymMap.get(lexiconId);
        if (synonymMap == null) return map;

        result = mapAdd(map, synonymMap, false);
        return result;
    }

    public Map<String, Float> mapAdd(Map<String, Float> map, Map<String, String> convertMap, boolean isFilter) {
        if (convertMap == null) return map;

        Map<String, Float> result = new HashMap<>();
        String synonym = "";
        for (Map.Entry<String, Float> entry : map.entrySet()) {
            synonym = convertMap.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 if (!isFilter) {
                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, NlpCache.Node> nodesMap = NlpCache.getStandard_info_type_tree_map();
        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 (!"null".equals(entry.getKey()) && entry.getValue() >= threshold) {
                thresholdMap.put(entry.getKey(), entry.getValue());
            }
        }

        NlpCache.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();
                NlpCache.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);
                }
                NlpCache.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, NlpCache.Node p, Map<String, Float> thresholdMap, List<String> nodeNamesList) {
        for (NlpCache.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, NlpCache.Node node, List<String> delList, String topName) {
        for (NlpCache.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);
            }
        }
    }
}
