import os.path
import shutil

import numpy as np
import matplotlib.pyplot as plt


def showHist(err, correct, date):
    err = np.array(err)
    correct = np.array(correct)

    fig, axs = plt.subplots(2, 1)
    axs[0].hist(err, bins=50, edgecolor='black')
    axs[0].set_xlim([0, 1])
    axs[0].set_title('err')
    axs[1].hist(correct, bins=50, edgecolor='black')
    axs[1].set_xlim([0, 1])
    axs[1].set_title('correct')
    plt.title(date)
    plt.savefig('comparisonResult/Hist_' + date + '.png')
    plt.show()


def showgrid(recall, prec, date):
    x = np.linspace(start=-0, stop=1, num=11, endpoint=True).tolist()
    plt.figure(figsize=(10, 6))
    plt.plot(x, recall, color='red', label='recall')
    plt.plot(x, prec, color='blue', label='PrecisePos')
    plt.legend()
    plt.xlabel('threshold')
    plt.title(date)
    # plt.ylabel('Similarity')
    plt.grid(True, linestyle='--', alpha=0.5)
    # plt.savefig('accuracy_recall_grid.png')
    plt.savefig('comparisonResult/grid_' + date + '.png')
    plt.show()
    plt.close()


def read_txt_file(filePth):
    with open(filePth, 'r', encoding='utf-8') as f:
        lines = f.readlines()
        dict = {}
        all_list = []
        barcode_list = []
        similarity_list = []
        split_flag = False
        clean_lines = [line.strip().replace("'", '').replace('"', '') for line in lines]
        for line in clean_lines:
            stripped_line = line.strip()
            if not stripped_line:
                split_flag = False
                all_list.append(dict)
                dict = {}
                barcode_list, similarity_list = [], []
                continue

            label = line.split(':')[0]
            value = line.split(':')[1]
            if label == 'SeqDir':
                dict['SeqDir'] = value
            if label == 'Deleted':
                dict['Deleted'] = value
            if label == 'List':
                split_flag = True
                continue
            if split_flag:
                dict['barcode'] = barcode_list
                dict['similarity'] = similarity_list
                barcode_list.append(label)
                similarity_list.append(value)
        all_list.append(dict)
        all_list = [d for d in all_list if d]
    return all_list


def move_file(seqdirs, filePth):
    comparisonData = os.path.basename(filePth).split('.')[0]
    comparisonData = os.sep.join(['D:\Project\ieemoo\image_quality_assessment\comparisonData', comparisonData])
    print('comparisonData', comparisonData)
    for seqdir in seqdirs:
        print(seqdir[0], seqdir[1])
        err_pair = os.sep.join([comparisonData, 'err_pair', seqdir[1]])
        if not os.path.exists(err_pair):
            os.makedirs(err_pair)
        for comparison in os.listdir(comparisonData):
            print(os.sep.join([comparisonData, comparison]))
            print(os.sep.join([err_pair, comparison]))
            try:
                if seqdir[0] in comparison:
                    shutil.copytree(os.sep.join([comparisonData, comparison]),
                                    os.sep.join([err_pair, comparison]))
                if seqdir[1] in comparison:
                    shutil.copytree(os.sep.join([comparisonData, comparison]),
                                    os.sep.join([err_pair, comparison]))
            except Exception as e:
                continue


def compute_recall_precision(err_similarity, correct_similarity, date=None):
    # ths = np.linspace(0, 1, 11)
    ths = np.linspace(start=-0, stop=1, num=11, endpoint=True).tolist()
    recall, prec = [], []
    for th in ths:
        TP = len([num for num in correct_similarity if num >= th])
        FP = len([num for num in err_similarity if num >= th])
        if (TP + FP) == 0:
            prec.append(1)
            recall.append(0)
        else:
            prec.append(TP / (TP + FP))
            recall.append(TP / (len(err_similarity) + len(correct_similarity)))
    # print(recall)
    # print(prec)
    showgrid(recall, prec, date)
    return recall, prec


def deal_one_file(filePth):
    date = filePth.split('\\')[-1].split('.')[0]
    all_list = read_txt_file(filePth)
    num = 0
    err_barcode_list, correct_barcode_list, err_similarity, correct_similarity, seqdirs = [], [], [], [], []
    for s_list in all_list:
        seqdir = s_list['SeqDir'].strip()
        delete = s_list['Deleted'].strip()
        barcodes = [s.strip() for s in s_list['barcode']]
        similarity = [float(s.strip()) for s in s_list['similarity']]
        if delete in barcodes[:1]:
            num += 1
            correct_barcode_list.append(delete)
            correct_similarity.append(similarity[0])
        else:
            seqdirs.append((seqdir, delete))
            err_barcode_list.append(delete)
            err_similarity.append(similarity[0])

    compute_recall_precision(err_similarity, correct_similarity, date)
    showHist(err_similarity, correct_similarity, date)
    move_file(seqdirs, filePth)  # 统计错误对
    return err_similarity, correct_similarity


def main(filesPth):
    err_similarities, correct_similarities = [], []
    dir_lists = os.listdir(filesPth)
    # dir_lists = ['deletedBarcode_10_0716_pm_3.txt']
    for name in dir_lists:
        filePth = os.sep.join([filesPth, name])
        err_similarity, correct_similarity = deal_one_file(filePth)
        err_similarities += err_similarity
        correct_similarities += correct_similarity
    compute_recall_precision(err_similarities, correct_similarities, date='zong')
    showHist(err_similarities, correct_similarities, date='zong')
    print('END')


if __name__ == '__main__':
    # filePth = 'D:\Project\ieemoo\image_quality_assessment\comparisonResult\deletedBarcode_10_0722_pm_01.txt'
    # read_txt_file(filePth)

    filesPth = 'comparisonResult'
    main(filesPth)

    # for name in os.listdir('comparisonData\deletedBarcode_15_0628_pm\err_pair'):
    #     path = os.sep.join(['comparisonData\deletedBarcode_15_0628_pm\err_pair', name])
    #     print(len(os.listdir(path)))
    #     if len(os.listdir(path)) < 2:
    #         print(path)
