package org.diagbot.nlp.relation.util;

import org.algorithm.core.cnn.entity.Lemma;
import org.algorithm.core.cnn.entity.Triad;
import org.diagbot.nlp.feature.FeatureType;
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.NlpCache;
import org.diagbot.nlp.util.NlpUtil;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @ClassName org.diagbot.nlp.relation.util.LemmaUtil
 * @Description TODO
 * @Author fyeman
 * @Date 2019/3/21/021 14:25
 * @Version 1.0
 **/
public class LemmaUtil {
    /**
     * 分词结果转词元结构
     * @param lexemes
     * @return
     */
    public List<Lemma> lexemeToTriadLemma(LexemePath<Lexeme> lexemes) {
        List<Lemma> lemmas = new ArrayList<>();
        for (Lexeme lexeme : lexemes) {
            if (!lexeme.getProperty().equals("99")) {
                Lemma lemma = new Lemma();
                lemma.setLen(lexeme.getLength());
                lemma.setPosition(lexeme.getOffset() + "," + (lexeme.getOffset() + lexeme.getLength() - 1));
                lemma.setText(lexeme.getText());
                lemma.setProperty(lexeme.getProperty());
                lemmas.add(lemma);
            }
        }
        return lemmas;
    }

    /**
     * 树形结构最多3层
     * @param triads
     * @param featureType
     * @return
     */
    public List<Lemma> traidToTree(List<Triad> triads, FeatureType featureType) {
        List<Lemma> lemmaTree = new ArrayList<>();
        switch (featureType) {
            case SYMPTOM:
                select(lemmaTree, triads, Constants.symptom_type);
                select(lemmaTree, triads, Constants.vital_type);
                select(lemmaTree, triads, Constants.lis_name_type);
                select(lemmaTree, triads, Constants.pacs_name_type);
                select(lemmaTree, triads, Constants.medicine_type);
        }
        return lemmaTree;
    }

    public void select(List<Lemma> lemmaTree, List<Triad> triads, NegativeEnum[] type) {
        List<Triad> has_add_triads = new ArrayList<>();
        for (Triad triad : triads) {
            Lemma left_l = null;
            Lemma right_l = null;
            if (NlpUtil.isFeature(triad.getL_1().getProperty(), type)) {
                left_l = this.copyProperties(triad.getL_1());
                right_l = this.copyProperties(triad.getL_2());
            }
            if (NlpUtil.isFeature(triad.getL_2().getProperty(), type)) {
                left_l = this.copyProperties(triad.getL_2());
                right_l = this.copyProperties(triad.getL_1());
            }
            if (left_l != null && right_l != null) {
                boolean isFindFromTree = false;
                for (Lemma l : lemmaTree) {
                    if (l.getText().equals(left_l.getText()) && l.getPosition().equals(left_l.getPosition())) {
                        left_l = l;
                        isFindFromTree = true;
                        break;
                    }
                }
                this.findRelationTriad(triads, triad, has_add_triads, right_l, type);
                left_l.add(right_l);
                if (!isFindFromTree) {      //树上已有节点 不需要添加
                    lemmaTree.add(left_l);
                }
                //已添加到树中的三元组
                has_add_triads.add(triad);
            }
        }
        triads.removeAll(has_add_triads);
    }

    public boolean findRelationTriad(List<Triad> triads, Triad current_triad, List<Triad> has_add_triads, Lemma lemma, NegativeEnum[] type) {
        boolean isFindRelation = false;
        for (Triad triad : triads) {
            if (current_triad == triad) {
                continue;
            }
            if (triad.getL_1().getText().equals(lemma.getText())
                    && triad.getL_1().getPosition().equals(lemma.getPosition())
                    && !NlpUtil.isFeature(triad.getL_2().getProperty(), type)) {
                lemma.add(this.copyProperties(triad.getL_2()));
                isFindRelation = true;
                //已添加到树中的三元组
                has_add_triads.add(triad);
            }
            if (triad.getL_2().getText().equals(lemma.getText())
                    && triad.getL_2().getPosition().equals(lemma.getPosition())
                    && !NlpUtil.isFeature(triad.getL_1().getProperty(), type)) {
                lemma.add(this.copyProperties(triad.getL_1()));
                isFindRelation = true;
                //已添加到树中的三元组
                has_add_triads.add(triad);
            }
        }
        return isFindRelation;
    }

    public Lemma copyProperties(Lemma lemma) {
        Lemma l = new Lemma();
        l.setLen(lemma.getLen());
        l.setPosition(lemma.getPosition());
        l.setProperty(lemma.getProperty());
        l.setText(lemma.getText());
        return l;
    }

    public List<Triad> findPairTraids(List<Lemma> lemmaParticiple) {
        List<Triad> triads = new ArrayList<>();
        for (int i = 0; i < lemmaParticiple.size(); i++) {
            for (int j = i + 1; j < lemmaParticiple.size(); j++) {
                Triad triad = new Triad();
                triad.setL_1(lemmaParticiple.get(i));
                triad.setL_2(lemmaParticiple.get(j));
                triads.add(triad);
            }
        }

        Map<String, List<String>> extract_relation_property_pair_map = NlpCache.getExtract_relation_property_pair_map();

        String[] prop1;
        String[] prop2;
        boolean isPair = false;
        List<String> props = null;

        List<Triad> pairTriads = new ArrayList<>();
        for (Triad triad : triads) {
            prop1 = triad.getL_1().getProperty().split(",");
            prop2 = triad.getL_2().getProperty().split(",");
            for (int i = 0; i < prop1.length; i++) {
                props = extract_relation_property_pair_map.get(prop1[i]);
                if (props == null) {
                    continue;
                }
                for (int j = 0; j < prop2.length; j++) {
                    if (props.contains(prop2[j])) {
                        isPair = true;
                        break;
                    }
                }
            }
            if (isPair) {
                pairTriads.add(triad);
            }
            isPair = false;
        }
        return pairTriads;
    }
}
