package org.diagbot.nlp.feature.extract;

import org.apache.commons.lang3.StringUtils;
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.diagbot.nlp.util.NlpUtil;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class CaseToken {
    protected static String[] ignore_symbol = new String[]{"、", "."};
    protected static String[] stop_symbol = new String[]{"。", ";", "?", "；", "？", "“", "”", "\r", "\n", "[", "]", "{", "}"};
    protected static String[] negative_words = Constants.negative_words;
    protected static String[] vital_filter_data = Constants.vital_filter_data;
    //找到对应词后，词回退处理游标
    protected int back_cursor = 1;
    protected int searched_position = -1;
    protected Lexeme cursorLexeme = null;
    protected Lexeme leftFeatureLexeme = null;
    protected Lexeme rightFeatureLexeme = null;
    protected int sn = 0;
    protected String featureSize = "";

    static {
        Arrays.sort(ignore_symbol);
        Arrays.sort(stop_symbol);
        Arrays.sort(negative_words);
        Arrays.sort(vital_filter_data);
    }

    public abstract List<Map<String, Object>> analyze(LexemePath<Lexeme> lexemePath) throws Exception;

    protected void lookFeatures(List<Map<String, Object>> featuresList, int index, LexemePath<Lexeme> lexemePath, Lexeme lexeme, String featureType, NegativeEnum[] features) throws Exception {
        this.lookFeatures(featuresList, index, lexemePath, lexeme, featureType, features, true);
    }

    public void lookFeatures(List<Map<String, Object>> featuresList, int index, LexemePath<Lexeme> lexemePath, Lexeme lexeme, String featureType, NegativeEnum[] features, boolean search_negative) throws Exception {
        //第一个就是特征词
        if (index - this.back_cursor < 0) {
            this.updateFeaturesMap(featuresList, Constants.default_negative, lexeme, featureType);
            return;
        }
        boolean isFind = false;


        //查找到特征词往回追溯，直至语句段落标识
        while (index - this.back_cursor > -1) {
            leftFeatureLexeme = null;
            rightFeatureLexeme = null;

            cursorLexeme = lexemePath.get(index - this.back_cursor);
            NegativeEnum[] cursorLexemeProperty = new NegativeEnum[]{NegativeEnum.parseOfValue(cursorLexeme.getProperty())};
            //搜索到语句段落标识未找到阴性词，用"有"作为阳性词性标识
            searched_position = Arrays.binarySearch(stop_symbol, cursorLexeme.getText());
            if (searched_position > -1) {
                //如果找到段落标识符，还需要回溯标识符前面一个词性和标识符后一个词性，如果词性和特征词相同，忽略段落标识符
                //无胸闷气急，流涕，鼻塞，胸痛，腹痛头痛等不适
                if (index - this.back_cursor - 1 >= 0) {
                    leftFeatureLexeme = lexemePath.get(index - this.back_cursor - 1);
                }
                if (index - this.back_cursor + 1 < lexemePath.size()) {
                    rightFeatureLexeme = lexemePath.get(index - this.back_cursor + 1);
                }
                if (leftFeatureLexeme != null && rightFeatureLexeme != null) {
                    if (NlpUtil.isFeature(leftFeatureLexeme.getProperty(), cursorLexemeProperty)
                            && NlpUtil.isFeature(rightFeatureLexeme.getProperty(), cursorLexemeProperty)) {
                        back_cursor++;
                        continue;
                    }
                }
                this.updateFeaturesMap(featuresList, Constants.default_negative, lexeme, featureType);
                isFind = true;
                break;
            }
            if (search_negative) {
                //搜索到阴性词,放入阴性队列
                searched_position = Arrays.binarySearch(negative_words, cursorLexeme.getText());
                if (searched_position > -1) {
                    isFind = true;
//                    this.updateFeaturesMap(featuresList, "无", lexeme, featureType);
                    break;
                }
            }
            back_cursor++;
        }
        //如果一直往回追溯都没有阴性词和段落标识
        if (!isFind) {
            this.updateFeaturesMap(featuresList, Constants.default_negative, lexeme, featureType);
        }
        //重置回溯标识
        this.back_cursor = 1;
        this.searched_position = -1;
    }

    protected void updateFeaturesMap(List<Map<String, Object>> featuresList, String key, Lexeme lexeme, String featureType) throws Exception {
        boolean hasFeature = false;
        for (int i = 0; i < featuresList.size(); i++) {
            if (lexeme.getText().equals(featuresList.get(i).get("feature_name").toString())) {
                hasFeature = true;
            }
        }
        if (!hasFeature) {
            if (StringUtils.isNotEmpty(featureSize)) {
                if(featureSize.equals("all")){//featureSize为all时提取所有特征
                    Map<String, Object> fMap = new HashMap<>(10);
                    fMap.put("feature_name", lexeme.getText());
                    fMap.put("feature_type", featureType);
                    fMap.put("negative", key);
                    fMap.put("sn", String.valueOf(sn++));
                    fMap.put("property", lexeme.getProperty());
                    fMap.put("concept", lexeme.getConcept());
                    featuresList.add(fMap);
                }else {
                    if (sn < Integer.parseInt(featureSize)){
                        Map<String, Object> fMap = new HashMap<>(10);
                        fMap.put("feature_name", lexeme.getText());
                        fMap.put("feature_type", featureType);
                        fMap.put("negative", key);
                        fMap.put("sn", String.valueOf(sn++));
                        fMap.put("property", lexeme.getProperty());
                        fMap.put("concept", lexeme.getConcept());
                        featuresList.add(fMap);
                    }
                }
            }
        }
    }
    public void getFeatureSize(String fetureSize){
        this.featureSize = fetureSize;
    }
}

