# -*- coding: utf-8 -*-
"""
Created on Fri Feb 23 11:04:48 2024

@author: ym
"""
import numpy as np
import cv2
from scipy.spatial.distance import cdist
# from trackers.utils import matching

# TracksDict
def readDict(boxes, TracksDict):
    feats = []
    for i in range(boxes.shape[0]):   
        tid, fid, bid = int(boxes[i, 4]), int(boxes[i, 7]), int(boxes[i, 8])
        
        trackdict = TracksDict[f"frame_{fid}"]
        if "feats" in trackdict:
            feat = trackdict["feats"][bid]
            feats.append(feat)
        
        if "boxes" in trackdict:
            box = trackdict["boxes"][bid]
            assert (box[:4].astype(int) == boxes[i, :4].astype(int)).all(), f"Please check: frame_{fid}"
        
        if "imgs" in trackdict:
            img = trackdict["imgs"][bid]
            cv2.imwrite(f'./data/imgs/{tid}_{fid}_{bid}.png', img)
    
    return np.asarray(feats, dtype=np.float32)



def track_equal_track(atrack, btrack):
    # boxes: [x, y, w, h, track_id, score, cls, frame_index, box_index]
    #         0  1  2  3       4      5     6        7          8
    aboxes = atrack.boxes
    bboxes = btrack.boxes
    
    afeat = atrack.features
    bfeat = btrack.features
    
    # afeat = readDict(aboxes, TracksDict)
    # bfeat = readDict(bboxes, TracksDict)

    
    ''' 1. 判断轨迹在时序上是否有交集 '''
    afids = aboxes[:, 7].astype(np.int_)
    bfids = bboxes[:, 7].astype(np.int_)
    # 帧索引交集
    interfid = set(afids).intersection(set(bfids))
    
    # 或者直接判断帧索引是否有交集，返回 Ture or False
    # interfid = set(afids).isdisjoint(set(bfids))
    
    if len(interfid):
        return False
    
    ''' 2. 轨迹特征相似度判断'''
    feat = np.concatenate((afeat, bfeat), axis=0)
    
    emb_simil = 1 - np.maximum(0.0, cdist(feat, feat, 'cosine'))
    emb_ = 1 - np.maximum(0.0, cdist(np.mean(afeat, axis=0)[None, :], np.mean(bfeat, axis=0)[None, :], 'cosine'))/2
    
    if emb_[0, 0]<0.66:
        return False
    
    ''' 3. 轨迹空间iou'''
    alabel = np.array([0] * afids.size, dtype=np.int_)
    blabel = np.array([1] * bfids.size, dtype=np.int_)
    
    label = np.concatenate((alabel, blabel), axis=0)
    fids = np.concatenate((afids, bfids), axis=0)
    indices = np.argsort(fids)
    idx_pair = []
    for i in range(len(indices)-1):
        idx1, idx2 = indices[i], indices[i+1]
        if label[idx1] != label[idx2] and fids[idx2] - fids[idx1] <= 3:
            if label[idx1] == 0:
                a_idx = idx1
                b_idx = idx2-alabel.size
            else:
                a_idx = idx2
                b_idx = idx1-alabel.size 
            
            idx_pair.append((a_idx, b_idx))
    
    ious = []
    embs = []
    for a, b in idx_pair:
        abox, bbox = aboxes[a, :], bboxes[b, :]
        
        af, bf = afeat[a, :], bfeat[b, :]
        
        emb_ab = 1 - np.maximum(0.0, cdist(af[None, :], bf[None, :], 'cosine'))
        
        
        xa1, ya1 = abox[0] - abox[2]/2, abox[1] - abox[3]/2 
        xa2, ya2 = abox[0] + abox[2]/2, abox[1] + abox[3]/2
        
        xb1, yb1 = bbox[0] - bbox[2]/2, bbox[1] - bbox[3]/2
        xb2, yb2 = bbox[0] + bbox[2]/2, bbox[1] + bbox[3]/2 
        
        
        inter = (np.minimum(xb2, xa2) - np.maximum(xb1, xa1)).clip(0) * \
                     (np.minimum(yb2, ya2) - np.maximum(yb1, ya1)).clip(0)
                     
        # Union Area
        box1_area = abox[2] * abox[3]
        box2_area = bbox[2] * bbox[3]
        union = box1_area + box2_area - inter + 1e-6

        ious.append(inter/union)
        embs.append(emb_ab[0, 0])
    
    ''' 4. 和同一手部关联，如何将该代码和 iou 部分相融合,需进一步完善'''   
    # ahands = np.array(atrack.Hands)
    # bhands = np.array(btrack.Hands)
    # ahids = ahands[:, 0]
    # bhids = bhands[:, 0]
    # interhid = set(ahids).intersection(set(bhids))
    # for hid in interhid:
    #     aidx = ahands[:, 0] == hid
    #     bidx = bhands[:, 0] == hid
        
    #     ahfids = ahids[aidx, 1]
    #     bhfids = bhids[bidx, 1]
    
    
    

    cont = False if len(interfid) else True    # fid 无交集
    cont1 = all(emb > 0.5 for emb in embs)
    cont2 = all(iou > 0.5 for iou in ious)
    # cont = cont and cont2 and cont3
    
    cont = cont and cont1 and cont2

    
    return cont



def track_equal_str(atrack, btrack):
    if atrack == btrack:
        return True
    else:
        return False


def merge_track(Residual):
    out_list = []
    alist = [t for t in Residual]
    while alist:
        atrack = alist[0]
        cur_list = []
        cur_list.append(atrack)
        alist.pop(0)
        
        blist = [b for b in alist]
        alist = []
        for btrack in blist:
            if track_equal_str(atrack, btrack):
                cur_list.append(btrack)
            else:
                alist.append(btrack)
                
        out_list.append(cur_list)
    return out_list
    
def main():
    Residual = ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'b', 'c', 'd']
    out_list = merge_track(Residual)
    
    print(Residual)
    print(out_list)

if __name__ == "__main__": 
    
    main()




# =============================================================================
# for i, atrack in enumerate(input_list):
#     cur_list = []
#     cur_list.append(atrack)
#     del input_list[i]
#     
#     for j, btrack in enumerate(input_list):
#         if track_equal(atrack, btrack):
#             cur_list.append(btrack)
#             del input_list[j]
#     
#     out_list.append(cur_list)
# =============================================================================














   
