package com.mooctest.service;

import com.mooctest.cluster.ClusterAnalyzer;
import com.mooctest.cluster.Group;
import com.mooctest.image.FingerPrint;
import com.mooctest.data.BugDTO;
import com.mooctest.data.DiffImg;
import com.mooctest.nlp.DistanceMatrix;
import com.mooctest.util.IndexUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static com.mooctest.util.ImageUtil.*;
import static java.util.stream.Collectors.toMap;

@Service
public class DiffImgService {

    @Autowired
    MasterReportService masterReportService;

    public Map<String, List<Group<String, DiffImg>>> genDiffImgClusters(Map<String, List<DiffImg>> masterDiffImgMap) {
        ClusterAnalyzer<String> analyzer = new ClusterAnalyzer<>();
        Map<String, List<Group<String, DiffImg>>> masterDiffImgClustersMap = new HashMap<>();
        masterDiffImgMap.forEach((masterId, diffImgs) -> {
            if (diffImgs.size() > 2) {

                double[][] distMatrix = DistanceMatrix.genImgDist(diffImgs);
                List<String> imgIds = diffImgs.stream()
                        .map(diffImg -> diffImg.getBugId() + "_" + diffImg.getIndex())
                        .collect(Collectors.toList());

                Map<String, DiffImg> diffImgMap = diffImgs.stream()
                        .collect(toMap(diffImg -> diffImg.getBugId() + "_" + diffImg.getIndex(), Function.identity()));
                try {
                    List<Set<String>> imgClusters = analyzer.HAC(distMatrix, imgIds, 0.01);
                    List<Group<String, DiffImg>> diffImgSets = new ArrayList<>(imgClusters.size());
                    for (int i = 0; i < imgClusters.size(); i++) {
                        Set<DiffImg> diffImgSet = imgClusters.get(i).stream()
                                .map(imgId -> diffImgMap.get(imgId))
                                .collect(Collectors.toSet());
                        diffImgSets.add(new Group<>(IndexUtil.joinDiffImg(masterId, String.valueOf(i)), diffImgSet));

                    }
                    masterDiffImgClustersMap.put(masterId, diffImgSets);
                } catch (IllegalArgumentException e) {

                }

            } else {
                List<Group<String, DiffImg>> diffImgSets = new ArrayList<>();
                diffImgSets.add(new Group<>(IndexUtil.joinDiffImg(masterId, String.valueOf(0)), new HashSet<>(diffImgs)));

                masterDiffImgClustersMap.put(masterId, diffImgSets);
            }
        });
        return masterDiffImgClustersMap;
    }

    public Map<String, List<DiffImg>> genMasterDiffImgMap(Map<String, Set<String>> masterClusterMap, Map<String, BugDTO> bugMap) {
        Map<String, List<DiffImg>> masterDiffImgMap = new HashMap<>();
        masterClusterMap.forEach((masterId, cluster) -> {
            List<DiffImg> diffImgs = genDiffImg(masterId, cluster, bugMap);
            masterDiffImgMap.put(masterId, diffImgs);
        });
        return masterDiffImgMap;
    }
    public List<DiffImg> genDiffImg(
            String masterId,
            Set<String> cluster,
            Map<String, BugDTO> bugMap) {

        long[] ids = masterReportService.getExamIdAndCaseIdByMasterId(masterId);
        long examId = ids[0];
        long caseId = ids[1];
        String taskId = examId + "_" + caseId;

        BugDTO masterReport = bugMap.get(masterId);
        List<DiffImg> diffImgs = new LinkedList<>();
        cluster.forEach(bugId -> { //遍历所有报告，找出每个聚类的差异图片
            if (!bugId.equals(masterId)) {
                BugDTO report = bugMap.get(bugId);
                String[] imgUrls = report.getImgUrls();
                for (int i = 0; i < imgUrls.length; i++) {
                    File imgFile = checkFileExist(genImagePath(taskId, bugId, i));
                    if (imgFile == null) {
                        continue;
                    }
                    boolean isSim = isSimilarWithMasterReport(masterReport, imgFile, taskId);
                    if (!isSim) {
                        diffImgs.add(new DiffImg(masterId, bugId, imgUrls[i], i));
                    }
                }
            }
        });
        return diffImgs;
    }

    private boolean isSimilarWithMasterReport(BugDTO masterReport, File imgFile, String taskId) {

        String[] masterImgs = masterReport.getImgUrls();
        FingerPrint reportImgFingerPrint = readImgFingerPrint(imgFile);
        for (int i = 0; i < masterImgs.length; i++) {
            String imgPath2 = genImagePath(taskId, masterReport.getId(), i);
            File img = checkFileExist(imgPath2);
            if (img == null) {
                continue;
            }
            FingerPrint masterImgFingerPrint = readImgFingerPrint(img);
            float sim = masterImgFingerPrint.compare(reportImgFingerPrint);
            if (sim > 0.85) {
                return true;
            }
        }

        return false;
    }

}
