package com.mooctest.service;

import com.hankcs.hanlp.seg.Segment;
import com.hankcs.hanlp.seg.common.Term;
import com.hankcs.hanlp.utility.SentencesUtil;
import com.mooctest.cluster.Group;
import com.mooctest.cluster.MyClusterAnalyzer;
import com.mooctest.data.BugDTO;
import com.mooctest.data.DiffText;
import com.mooctest.util.IndexUtil;
import com.mooctest.util.NLPUtil;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.mooctest.util.NLPUtil.SENTENCE_LENGTH_THRESH;
import static com.mooctest.util.NLPUtil.TXT_SIMILAR_THRESHOLD_LOW;
import static java.util.stream.Collectors.toMap;

@Service
public class DiffTextService {

    public Map<String, List<Group<String, DiffText>>> genDiffTextClusters(Map<String, List<DiffText>> masterDiffTextMap) {
        MyClusterAnalyzer<String> diffTextAnalyzer = new MyClusterAnalyzer<String>();
        Map<String, List<Group<String, DiffText>>> masterDiffTextClustersMap = new HashMap<>();
        masterDiffTextMap.forEach((masterId, diffTexts) -> {
            if (diffTexts.size() > 1) {

                //<bugId_sentenceIdx, diffText>
                Map<String, DiffText> diffTextMap = diffTexts.stream()
                        .collect(toMap(diffText -> diffText.getBugId() + "_" + diffText.getIndex(), Function.identity()));

                diffTexts.forEach(diffText ->
                        diffTextAnalyzer.addDocument(diffText.getBugId() + "_" + diffText.getIndex(), diffText.getSentence()));
                List<Set<String>> diffTextClusters = diffTextAnalyzer.repeatedBisection(1.0);
                List<Group<String, DiffText>> diffTextSets = new ArrayList<>(diffTextClusters.size());

                for (int i = 0; i < diffTextClusters.size(); i++) {
                    Set<DiffText> diffTextSet = diffTextClusters.get(i).stream()
                            .map(sentenceId -> diffTextMap.get(sentenceId))
                            .collect(Collectors.toSet());
                    diffTextSets.add(new Group<>(IndexUtil.joinDiffText(masterId, String.valueOf(i)), diffTextSet));
                }

                masterDiffTextClustersMap.put(masterId, diffTextSets);
                diffTextAnalyzer.clearDocs();
            } else if (diffTexts.size() == 1) {
                List<Group<String, DiffText>> diffTextSets = new ArrayList<>(1);
                Set<DiffText> set = new HashSet<>();
                set.add(diffTexts.get(0));
                diffTextSets.add(new Group<>(IndexUtil.joinDiffText(masterId, "0"), set));
                masterDiffTextClustersMap.put(masterId, diffTextSets);
            }
        });
        return masterDiffTextClustersMap;
    }
    public Map<String, List<DiffText>> genMasterDiffTextMap(Map<String, Set<String>> masterClusterMap, Map<String, BugDTO> bugMap) {

        Map<String, List<DiffText>> masterDiffTextMap = new HashMap<>();
        masterClusterMap.forEach((masterId, cluster) -> {

            List<DiffText> diffTexts = genDiffText(masterId, cluster, bugMap);
            masterDiffTextMap.put(masterId, diffTexts);
        });
        return masterDiffTextMap;
    }


    public List<DiffText> genDiffText(
            String masterId,
            Set<String> cluster,
            Map<String, BugDTO> bugMap) {

        BugDTO masterReport = bugMap.get(masterId);

        Segment segment = NLPUtil.getDefaultSegment();
        List<List<Term>> masterWords = segment.seg2sentence(masterReport.getDescription(), true);

        List<DiffText> diffTexts = new LinkedList<>();

        cluster.forEach(bugId -> {
            if (!bugId.equals(masterId)) {

                BugDTO report = bugMap.get(bugId);
                List<String> reportSts = SentencesUtil.toSentenceList(report.getDescription());

                int sentenceIdx = 0;// 句子在报告中的顺序
                for (String sentence : reportSts) {
                    boolean isSimilar = isSimilarWithMasterReport(masterWords, sentence);
                    if (!isSimilar) {
                        //存储，masterId bugId sentence
                        diffTexts.add(new DiffText(masterId, bugId, sentence, sentenceIdx));
                    }
                    sentenceIdx++;
                }
            }
        });

        return diffTexts;
    }

    /**
     * 传入的句子和master report 是否相似，只要与master的任意句子相似即可
     *
     * @param masterWords
     * @param sentence
     * @return
     */
    public boolean isSimilarWithMasterReport(List<List<Term>> masterWords, String sentence) {
        Segment segment = NLPUtil.getDefaultSegment();
        List<Term> stsWords = segment.seg(sentence);
        if (stsWords.size() <= SENTENCE_LENGTH_THRESH) {
            return true;
        }
        for (List<Term> masterStsWords : masterWords) {

            if (isJaccardSimilar(masterStsWords, stsWords)) {
                return true;
            }
        }
        return false;
    }

    public boolean isJaccardSimilar(List<Term> stsWords1, List<Term> stsWords2) {
        int inter = 0;
        int union = 0;
        for (Term term1 : stsWords1) {
            for (Term term2 : stsWords2) {
                if (term1.word.equals(term2.word)) {//之后换成 word2vector 改进前后对比
                    inter = inter + 1;
                }
            }
        }
        union = stsWords1.size() + stsWords2.size() - inter;

        double similar = (inter * 1.0) / (union * 1.0);

        if (similar >= TXT_SIMILAR_THRESHOLD_LOW) {
            return true;
        }
        return false;

    }
}
