# -*- coding: utf-8 -*-
"""
Created on Fri Aug 30 17:53:03 2024
    have Deprecated! 

1. 确认在相同CamerType下，track.data 中 CamerID 项数量 = 图像数 = 帧ID数 = 最大帧ID

2. 读取0/1_tracking_output.data 中数据，boxes、feats，len(boxes)=len(feats)
    帧ID约束

3. 优先选择前摄

4. 保存图像数据

5. 一次购物事件类型
    shopEvent: {barcode:
                type: getout, input
                front_traj:[{imgpath: str, 
                             box: arrar(1, 9),
                             feat: array(1, 256)
                           }]
                back_traj: [{imgpath: str, 
                             box: arrar(1, 9),
                             feat: array(1, 256)
                           }]
                }
        
        
        
@author: ym

"""
import numpy as np
import cv2
import os
import sys
import json
import pickle
sys.path.append(r"D:\DetectTracking")
from tracking.utils.read_data import extract_data, read_tracking_output, read_deletedBarcode_file

IMG_FORMAT = ['.bmp', '.jpg', '.jpeg', '.png']

def creat_shopping_event(basepath):
    eventList = []
    
    '''一、构造放入商品事件列表'''
    k = 0
    for filename in os.listdir(basepath):
        # filename = "20240723-155413_6904406215720"
        
        '''filename下为一次购物事件'''
        filepath = os.path.join(basepath, filename)

        '''================ 0. 检查 filename 及 filepath 正确性和有效性 ================'''
        nmlist = filename.split('_')
        if filename.find('2024')<0 or len(nmlist)!=2 or len(nmlist[0])!=15 or len(nmlist[1])<11:
            continue
        if not os.path.isdir(filepath): continue
        print(f"Event name: {filename}")
        
        '''================ 1. 构造事件描述字典，暂定 9 items ==============='''
        event = {}
        event['barcode'] = nmlist[1]
        event['type'] = 'input'
        event['filepath'] = filepath
        event['back_imgpaths'] = []
        event['front_imgpaths'] = []
        event['back_boxes'] = np.empty((0, 9), dtype=np.float64)
        event['front_boxes'] = np.empty((0, 9), dtype=np.float64)
        event['back_feats'] = np.empty((0, 256), dtype=np.float64)
        event['front_feats'] = np.empty((0, 256), dtype=np.float64)
        # event['feats_compose'] = np.empty((0, 256), dtype=np.float64)
        # event['feats_select'] = np.empty((0, 256), dtype=np.float64)
        
        
        '''================= 1. 读取 data 文件 ============================='''
        for dataname in os.listdir(filepath):
            # filename = '1_track.data'
            datapath = os.path.join(filepath, dataname)
            if not os.path.isfile(datapath): continue
            
            CamerType = dataname.split('_')[0]
            ''' 3.1 读取 0/1_track.data 中数据，暂不考虑'''
            # if dataname.find("_track.data")>0:
            #     bboxes, ffeats, trackerboxes, tracker_feat_dict, trackingboxes, tracking_feat_dict = extract_data(datapath)
  
            ''' 3.2 读取 0/1_tracking_output.data 中数据'''
            if dataname.find("_tracking_output.data")>0:
                tracking_output_boxes, tracking_output_feats = read_tracking_output(datapath)
                if len(tracking_output_boxes) != len(tracking_output_feats): continue
                if CamerType == '0':
                    event['back_boxes'] = tracking_output_boxes
                    event['back_feats'] = tracking_output_feats
                elif CamerType == '1':
                    event['front_boxes'] = tracking_output_boxes
                    event['front_feats'] = tracking_output_feats
        
        # '''1.1 事件的特征表征方式选择'''
        # bk_feats = event['back_feats']
        # ft_feats = event['front_feats']
        
        # feats_compose = np.empty((0, 256), dtype=np.float64)
        # if len(ft_feats):
        #     feats_compose = np.concatenate((feats_compose, ft_feats), axis=0)
        # if len(bk_feats):
        #     feats_compose = np.concatenate((feats_compose, bk_feats), axis=0)
        # event['feats_compose'] = feats_compose
        
        # '''3. 构造前摄特征'''
        # if len(ft_feats):
        #     event['feats_select'] = ft_feats
        


        '''================ 2. 读取图像文件地址，并按照帧ID排序 ============='''
        frontImgs, frontFid = [], []
        backImgs, backFid = [], []
        for imgname in os.listdir(filepath):
            name, ext = os.path.splitext(imgname)
            if ext not in IMG_FORMAT or name.find('frameId')<0: continue

            CamerType = name.split('_')[0]
            frameId = int(name.split('_')[3])
            imgpath = os.path.join(filepath, imgname)
            if CamerType == '0':
                backImgs.append(imgpath)
                backFid.append(frameId)
            if CamerType == '1':
                frontImgs.append(imgpath)
                frontFid.append(frameId)
        
        frontIdx = np.argsort(np.array(frontFid))
        backIdx = np.argsort(np.array(backFid))
        
        '''2.1 生成依据帧 ID 排序的前后摄图像地址列表'''
        frontImgs = [frontImgs[i] for i in frontIdx]
        backImgs = [backImgs[i] for i in backIdx]

        '''2.2 将前、后摄图像路径添加至事件字典'''   
        bfid = event['back_boxes'][:, 7].astype(np.int64)
        ffid = event['front_boxes'][:, 7].astype(np.int64)
        if len(bfid) and max(bfid) <= len(backImgs):
            event['back_imgpaths'] = [backImgs[i-1] for i in bfid]
        if len(ffid) and max(ffid) <= len(frontImgs):
            event['front_imgpaths'] = [frontImgs[i-1] for i in ffid]

        
        '''================ 3. 判断当前事件有效性，并添加至事件列表 =========='''
        condt1 = len(event['back_imgpaths'])==0 or len(event['front_imgpaths'])==0
        condt2 = len(event['front_feats'])==0 and len(event['back_feats'])==0
        
        if condt1 or condt2:
            print(f"     Error, condt1: {condt1}, condt2: {condt2}")
            continue

        eventList.append(event)
        
        # k += 1
        # if k==1:
        #     continue
        
    '''一、构造放入商品事件列表，暂不处理'''
    # delepath = os.path.join(basepath, 'deletedBarcode.txt')
    # bcdList = read_deletedBarcode_file(delepath) 
    # for slist in bcdList:
    #     getoutFold = slist['SeqDir'].strip()
    #     getoutPath = os.path.join(basepath, getoutFold)
        
    #     '''取出事件文件夹不存在，跳出循环'''
    #     if not os.path.exists(getoutPath) and not os.path.isdir(getoutPath):
    #         continue
        
    #     ''' 生成取出事件字典 '''
    #     event = {}
    #     event['barcode'] = slist['Deleted'].strip()
    #     event['type'] = 'getout'   
    #     event['basepath'] = getoutPath
    

    return eventList

def get_std_barcodeDict(bcdpath):
    stdBlist = []
    for filename in os.listdir(bcdpath):
        filepath = os.path.join(bcdpath, filename)
        if not os.path.isdir(filepath) or not filename.isdigit(): continue
    
        stdBlist.append(filename)
        
        
    bcdpaths = [(barcode, os.path.join(bcdpath, barcode)) for barcode in stdBlist]
    
    stdBarcodeDict = {}
    for barcode, bpath in bcdpaths:  
        stdBarcodeDict[barcode] = []
        for root, dirs, files in os.walk(bpath):
            
            imgpaths = []
            if "base" in dirs:
                broot = os.path.join(root, "base")
                for imgname in os.listdir(broot):
                    imgpath = os.path.join(broot, imgname)
                    _, ext = os.path.splitext(imgpath)
                    if ext not in IMG_FORMAT: continue
                    imgpaths.append(imgpath)
                
                stdBarcodeDict[barcode].extend(imgpaths)
                break
            
            else:
                for imgname in files:
                    imgpath = os.path.join(root, imgname)
                    _, ext = os.path.splitext(imgpath)
                    if ext not in IMG_FORMAT: continue
                    imgpaths.append(imgpath)
            stdBarcodeDict[barcode].extend(imgpaths)
        
        jsonpath = os.path.join(r'\\192.168.1.28\share\测试_202406\contrast\barcodes', f"{barcode}.pickle")
        with open(jsonpath, 'wb') as f:
           pickle.dump(stdBarcodeDict, f)
         
        print(f"Barcode: {barcode}")
       
       
       
    return stdBarcodeDict 


def one2one_test(filepath):
    
    savepath = r'\\192.168.1.28\share\测试_202406\contrast'
    
    '''获得 Barcode 列表'''
    bcdpath = r'\\192.168.1.28\share\已标注数据备份\对比数据\barcode\barcode_1771'
    stdBarcodeDict = get_std_barcodeDict(bcdpath)
    
    
    eventList = creat_shopping_event(filepath)
    print("=========== eventList have generated! ===========")
    barcodeDict = {}
    for event in eventList:
        '''9 items: barcode, type, filepath, back_imgpaths, front_imgpaths, 
                    back_boxes, front_boxes, back_feats, front_feats
        '''
        
        barcode = event['barcode']
        if barcode not in stdBarcodeDict.keys():
            continue
        
        
        if len(event['feats_select']):
            event_feats = event['feats_select']
        elif len(event['back_feats']):
            event_feats = event['back_feats']
        else:
            continue
        
        std_bcdpath = os.path.join(bcdpath, barcode)
        
              
        
        for root, dirs, files in os.walk(std_bcdpath):
            if "base" in files:
                std_bcdpath = os.path.join(root, "base")
                break
        
        
        
        
        
            
        
        
        
        
        
        
        
        '''保存一次购物事件的轨迹子图'''
        basename = os.path.basename(event['filepath'])
        spath = os.path.join(savepath, basename)
        if not os.path.exists(spath):
            os.makedirs(spath)
        cameras = ('front', 'back')
        for camera in cameras:
            if camera == 'front':
                boxes = event['front_boxes']
                imgpaths = event['front_imgpaths']
            else:
                boxes = event['back_boxes']
                imgpaths = event['back_imgpaths']

            for i, box in enumerate(boxes):
                x1, y1, x2, y2, tid, score, cls, fid, bid = box
                
                imgpath = imgpaths[i]
                image = cv2.imread(imgpath)
                subimg = image[int(y1/2):int(y2/2), int(x1/2):int(x2/2), :]
                
                camerType, timeTamp, _, frameID = os.path.basename(imgpath).split('.')[0].split('_')
                subimgName = f"{camerType}_{tid}_fid({fid}, {frameID}).png"
                subimgPath = os.path.join(spath, subimgName)
                
                cv2.imwrite(subimgPath, subimg)
        print(f"Image saved: {basename}")
            
        
    
    
    
    
        

def main():
    fplist = [r'\\192.168.1.28\share\测试_202406\0723\0723_1',
              r'\\192.168.1.28\share\测试_202406\0723\0723_2',
              # r'\\192.168.1.28\share\测试_202406\0723\0723_3',
              r'\\192.168.1.28\share\测试_202406\0722\0722_01',
              r'\\192.168.1.28\share\测试_202406\0722\0722_02'
            ]
    
    
    
    for filepath in  fplist:
        one2one_test(filepath)
    
    # for filepath in  fplist:
    #     try:
    #         one2one_test(filepath)
            
    #     except Exception as e:
    #         print(f'{filepath}, Error: {e}') 
        
if __name__ == '__main__':
    
    main()