package org.diagbot.bigdata.work;

import org.algorithm.util.AlgorithmClassify;
import org.diagbot.bigdata.common.ApplicationCacheUtil;
import org.diagbot.bigdata.util.BigDataConstants;
import org.diagbot.common.work.SearchData;
import org.diagbot.nlp.feature.FeatureAnalyze;
import org.diagbot.nlp.feature.FeatureType;
import org.diagbot.nlp.participle.ParticipleUtil;
import org.diagbot.nlp.participle.word.Lexeme;
import org.diagbot.nlp.participle.word.LexemePath;
import org.diagbot.nlp.util.Constants;
import org.diagbot.nlp.util.NegativeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.regex.Pattern;

/**
 * @ClassName org.diagbot.bigdata.work.ParamsDataProxy
 * @Description TODO
 * @Author fyeman
 * @Date 2019/1/16/016 14:04
 * @Version 1.0
 **/
public class ParamsDataProxy {
    Logger logger = LoggerFactory.getLogger(ParamsDataProxy.class);

    public void createSearchData(HttpServletRequest request, SearchData searchData) throws Exception {
        //消除空格
        if (searchData.getSymptom() != null) {
            searchData.setSymptom(searchData.getSymptom().trim());
        }
        if (searchData.getDiag() != null) {
            searchData.setDiag(searchData.getDiag().trim());
        }
        //计算年龄区间
        if (searchData.getAge() > 0) {
            searchData.setAge_start(searchData.getAge() - 5);
            searchData.setAge_end(searchData.getAge() + 5);
        }
        //修改性别代码
        if (!StringUtils.isEmpty(searchData.getSex())) {
            if ("M".equals(searchData.getSex())) {
                searchData.setSex("1");
            } else if ("F".equals(searchData.getSex())) {
                searchData.setSex("2");
            } else {
                searchData.setSex("3");
            }
        } else {
            searchData.setSex("3");
        }
        //默认查询门诊数据
        if (StringUtils.isEmpty(searchData.getResourceType())) {
            searchData.setResourceType(BigDataConstants.resource_type_o);
        }
        //给症状末尾添加诊断依据标准词
        if (searchData.getSymptom() != null) {
            LexemePath<Lexeme> featureData = ParticipleUtil.participle(searchData.getSymptom());
            if (featureData != null) {
                addStandWord(featureData, ApplicationCacheUtil.getKl_result_mapping_standword_map(), searchData);
            }
        }
        //所有信息参与推送
        searchData.setSymptom(searchData.getSymptom() + searchData.getVital()
                + searchData.getLis() + searchData.getPacs() + searchData.getPast() + searchData.getOther() + searchData.getIndications());
        searchData.setSymptom(searchData.getSymptom().trim());
        //一次推送多个类别信息
        String[] featureTypes = searchData.getFeatureType().split(",");
        //featureType统一转换
        String[] convertFeatureTypes = new String[featureTypes.length];
        for (int i = 0;i<featureTypes.length; i++) {
            convertFeatureTypes[i] = convertFeatureType(searchData.getSysCode(), featureTypes[i]);
        }
        searchData.setFeatureTypes(convertFeatureTypes);

        //获取入参中的特征信息
        FeatureAnalyze fa = new FeatureAnalyze();

        if (!StringUtils.isEmpty(searchData.getSymptom())) {
            List<Map<String, Object>> featuresList = fa.start(searchData.getSymptom(), FeatureType.FEATURE);
            paramFeatureInit(searchData, featuresList);

            // 清洗特征词，去除词性不匹配的词
            searchData = cleanFeature(featuresList, fa, searchData);

            //如果既往史中诊断信息，需要提取这个特征
            featuresList = fa.start(searchData.getOther(), FeatureType.DIAG);
            paramFeatureInit(searchData, featuresList);
        }

        if (!StringUtils.isEmpty(searchData.getDiag()) && StringUtils.isEmpty(searchData.getSymptom())) {
            List<Map<String, Object>> featuresList = fa.start(searchData.getDiag(), FeatureType.DIAG);
            paramFeatureInit(searchData, featuresList);
        }
    }

    /**
     * featureType转算法模型类型
     *
     * @param sysCode
     * @param featureTypes
     * @param searchData
     */
    public AlgorithmClassify[] createAlgorithmClassify(String sysCode, String[] featureTypes, SearchData searchData) {
        AlgorithmClassify[] classifies = new AlgorithmClassify[featureTypes.length];
        //下了诊断且其他信息全为空 反推标识
        boolean reverse = !StringUtils.isEmpty(searchData.getDiag()) && StringUtils.isEmpty(searchData.getSymptom());
        for (int i = 0; i < featureTypes.length; i++) {
//            featureTypes[i] = convertFeatureType(sysCode, featureTypes[i]);
            if (featureTypes[i] != null) {
                //模型
                switch (FeatureType.parse(featureTypes[i])) {
                    case SYMPTOM:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_SYMPTOM;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_SYMPTOM;
                        }
                        break;
                    case DIAG:
                        if (reverse) {
                            classifies[i] = null;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG;
                        }
                        break;
                    case VITAL:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_VITAL;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_VITAL;
                        }
                        break;
                    case LIS:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_LIS;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_LIS;
                        }
                        break;
                    case PACS:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_PACS;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_PACS;
                        }
                        break;
                    case TREAT:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_TREAT;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_TREAT;
                        }
                        break;
                    case HISTORY:
                        if (reverse) {
                            classifies[i] = AlgorithmClassify.NEURAL_DIAG_HISTORY;
                        } else {
                            classifies[i] = AlgorithmClassify.NEURAL_HISTORY;
                        }
                        break;
                }
            }
        }
        return classifies;
    }

    /**
     * 外部系统featureType需要转化为大数据定义的featureType
     *
     * @param sysCode
     * @param featureType
     * @return
     */
    private String convertFeatureType(String sysCode, String featureType) {
        if (StringUtils.isEmpty(sysCode) || sysCode.equals("1")) {
            if ("1".equals(featureType)) {
                return BigDataConstants.feature_type_symptom;
            }
            if ("7".equals(featureType)) {
                return BigDataConstants.feature_type_diag;
            }
            if ("4".equals(featureType)) {
                return BigDataConstants.feature_type_vital;
            }
            if ("5".equals(featureType)) {
                return BigDataConstants.feature_type_lis;
            }
            if ("6".equals(featureType)) {
                return BigDataConstants.feature_type_pacs;
            }
            if ("3".equals(featureType)) {
                return BigDataConstants.feature_type_history;
            }
            if ("8".equals(featureType)) {
                return BigDataConstants.feature_type_treat;
            }
            if ("22".equals(featureType)) {
                return BigDataConstants.feature_type_labelpush;
            }
            if ("11".equals(featureType)) {
                return BigDataConstants.feature_type_manju;
            }
            return null;
        }
        return featureType;
    }

    /**
     * 推送模型入参
     *
     * @param searchData
     * @throws Exception
     */
    private void paramFeatureInit(SearchData searchData, List<Map<String, Object>> featuresList) throws Exception {
        if (featuresList != null && featuresList.size() > 0) {
            //            BeanUtils.setProperty(searchData, property_list, featuresList);
            Map<String, Object> featureMap = null;
            for (int i = 0; i < featuresList.size(); i++) {
                featureMap = featuresList.get(i);
                Map<String, String> map = new HashMap<>();
                for (Map.Entry<String, Object> entry : featureMap.entrySet()) {
                    map.put(entry.getKey(), String.valueOf(entry.getValue()));
                }
                map.put("featureType", String.valueOf(featureMap.get("feature_type")));
                map.put("featureName", String.valueOf(featureMap.get("feature_name")));
                if (Constants.default_negative.equals(featureMap.get("negative"))) {
                    searchData.getInputs().put(map.get("feature_name"), map);
                } else {
                    searchData.getFilters().put(map.get("feature_name"), map);
                }
                map.put("property", String.valueOf(featureMap.get("property")));
                map.put("concept", String.valueOf(featureMap.get("concept")));
            }
        }
    }

    /**
     * 给SearchData中症状末尾添加诊断依据标准词
     *
     * @param lexemes
     * @param standWords
     * @param sData
     * @return
     */
    public SearchData addStandWord(List<Lexeme> lexemes, Map<String, List<Map<String, String>>> standWords, SearchData sData) {
        List<Lexeme> feature = new ArrayList<>();
        //收集分词结果中体征指标或体征指标值（数字）
        for (Lexeme lexeme : lexemes) {
            if (lexeme.getProperty().contains(",")) {
                ApplicationCacheUtil.setProterty(lexeme); //如果分词后词性有多个，只选一个(暂时只处理症状,体征)
            }
            NegativeEnum lexemeNegativeEnum = NegativeEnum.parseOfValue(lexeme.getProperty());
            if (lexemeNegativeEnum == NegativeEnum.VITAL_INDEX || lexemeNegativeEnum == NegativeEnum.SYMPTOM || lexemeNegativeEnum == NegativeEnum.DIGITS
                    || lexemeNegativeEnum == NegativeEnum.EVENT_TIME || lexemeNegativeEnum == NegativeEnum.UNIT
                    ) {
                feature.add(lexeme);
            }
        }
        //根据收集到的分词结果把体征指标和对应体征指标值（数字）拼接
        List<String> featureType = new ArrayList<>();
        for (int i = 0; i < feature.size(); i++) {
            boolean featureTypeState = true;
            if (i < feature.size() - 2) {
                if ((NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.VITAL_INDEX
                        && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS
                        && NegativeEnum.parseOfValue(feature.get(i + 2).getProperty()) == NegativeEnum.UNIT)
                        ||
                        (NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.VITAL_INDEX
                                && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS
                                && NegativeEnum.parseOfValue(feature.get(i + 2).getProperty()) == NegativeEnum.EVENT_TIME)
                        ||
                        (NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.SYMPTOM
                                && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS
                                && NegativeEnum.parseOfValue(feature.get(i + 2).getProperty()) == NegativeEnum.UNIT)
                        ||
                        (NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.SYMPTOM
                                && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS
                                && NegativeEnum.parseOfValue(feature.get(i + 2).getProperty()) == NegativeEnum.EVENT_TIME)) {
                    featureType.add(feature.get(i).getText() + "\t" + feature.get(i + 1).getText() + "\t"
                            + feature.get(i + 2).getText());
                    featureTypeState = false;
                }
            }
            if (featureTypeState && i < feature.size() - 1) {
                if ((NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.VITAL_INDEX
                        && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS)
                        ||
                        (NegativeEnum.parseOfValue(feature.get(i).getProperty()) == NegativeEnum.SYMPTOM
                                && NegativeEnum.parseOfValue(feature.get(i + 1).getProperty()) == NegativeEnum.DIGITS)) {
                    featureType.add(feature.get(i).getText() + "\t" + feature.get(i + 1).getText());
                }
            }
        }
        //将标准词中体征指标值（数字）与分词结果中体征指标值（数字）比较
        for (String f : featureType) {
            String[] features = f.split("\t");
            if (standWords.containsKey(features[0])) {
                List<Map<String, String>> standWordList = standWords.get(features[0]);
                for (Map<String, String> standWordMap : standWordList) {
                    if (standWordMap.containsKey("unit") && standWordMap.containsKey("value")) {
                        if (features.length == 2) {
                            judgment(sData, features, standWordMap);
                        } else {
                            if (standWordMap.get("unit").equals(features[2])) {
                                judgment(sData, features, standWordMap);
                            }
                        }
                    } else if (standWordMap.containsKey("value")) {
                        if (features.length == 2) {
                            judgment(sData, features, standWordMap);
                        }
                    }
                }
            }
        }
        return sData;
    }

    //将标准词中体征指标值（数字）与分词结果中体征指标值（数字）比较
    private void judgment(SearchData sData, String[] features, Map<String, String> standWordMap) {
        if (hasDigit(features[1])) {
            if (">".equals(standWordMap.get("op"))) {
                //单独处理  血压≥140/90mmHg   类似情况
                if (features[1].contains("/")) {
                    if (standWordMap.get("value").contains("/")) {
                        String[] feature = features[1].split("/");
                        Integer featuresSBP = Integer.valueOf(feature[0]); //分词特征收缩压
                        Integer featuresDBP = Integer.valueOf(feature[1]); //分词特征舒张压

                        String[] values = standWordMap.get("value").split("/");
                        Integer standWordSBP = Integer.valueOf(values[0]); //标准词收缩压
                        Integer standWordDBP = Integer.valueOf(values[1]); //标准词舒张压
                        if (featuresSBP > standWordSBP && featuresDBP > standWordDBP) {
                            sData.setSymptom(sData.getSymptom() + "," + standWordMap.get("standword"));
                            System.out.println(sData.getSymptom());
                        }
                    }
                } else {
                    String num = getNum(standWordMap.get("value"));
                    if (Double.valueOf(getNum(features[1])) > Double.valueOf(num)) {
                        sData.setSymptom(sData.getSymptom() + "," + standWordMap.get("standword"));
                        System.out.println(sData.getSymptom());

                    }
                }
            } else if ("<".equals(standWordMap.get("op"))) {
                //单独处理  血压小于90/60mmHg   类似情况
                if (standWordMap.get("value").contains("/")) {
                    if (features[1].contains("/")) {
                        String[] feature = features[1].split("/");
                        Integer featuresSBP = Integer.valueOf(feature[0]); //收缩压
                        Integer featuresDBP = Integer.valueOf(feature[1]); //舒张压

                        String[] values = standWordMap.get("value").split("/");
                        Integer standWordSBP = Integer.valueOf(values[0]); //收缩压
                        Integer standWordDBP = Integer.valueOf(values[1]); //舒张压
                        if (featuresSBP < standWordSBP && featuresDBP < standWordDBP) {
                            sData.setSymptom(sData.getSymptom() + "," + standWordMap.get("standword"));
                            System.out.println(sData.getSymptom());
                        }
                    }
                } else {
                    String num = getNum(standWordMap.get("value"));
                    if (Double.valueOf(getNum(features[1])) < Double.valueOf(num)) {
                        sData.setSymptom(sData.getSymptom() + "," + standWordMap.get("standword"));
                        System.out.println(sData.getSymptom());
                    }
                }
            }
        }
    }

    private boolean hasDigit(String content) {
        boolean flag = false;
        if (Pattern.compile(".*\\d+.*").matcher(content).matches()) {
            flag = true;
        }
        return flag;
    }

    private String getNum(String standWord) {
        StringBuffer sb = new StringBuffer();
        for (String num : standWord.replaceAll("[^0-9]", ",").split(",")) {
            if (num.length() > 0) {
                sb.append(num);
            }
        }
        return sb.toString();
    }

    private SearchData cleanFeature(List<Map<String, Object>> featuresList, FeatureAnalyze fa,
                                    SearchData searchData) {
        // 在输入的辅检文本中，只提取辅检信息
        String[] PACS_Feature = {Constants.word_property_PACS,
                Constants.word_property_PACS_Detail, Constants.word_property_PACS_Result};
        searchData = removeFeature(searchData.getPacs(), fa, searchData, PACS_Feature,  FeatureType.PACS);

        // 在输入的化验文本中，只提取化验信息
        String[] LIS_Feature = {Constants.word_property_LIS,
                Constants.word_property_LIS_Detail, Constants.word_property_LIS_Result};
        searchData = removeFeature(searchData.getLis(), fa, searchData, LIS_Feature,  FeatureType.LIS);

        return searchData;
    }

    private SearchData removeFeature(String text, FeatureAnalyze fa,
                                     SearchData searchData, String[] properties,  FeatureType featureType) {
        String name = "";
        Boolean related = false;

        try {
            List<Map<String, Object>> featureList = fa.start(text, featureType);
            if (featureList != null) {
                for (Map<String, Object> item : featureList) {
                    name = item.get("feature_name").toString();
                    String[] property = item.get("property").toString().split(",");
                    for (String prop : property) {
                        if (Arrays.asList(properties).contains(prop)) {
                            related = true;
                            break;
                        }
                    }

                    if (!related) {
                        searchData.getInputs().remove(name);
                    }

                    related = false;
                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            return searchData;
        }
    }
}
