import os
import pydicom as dicomio
import numpy as np
import argparse
import json

from do_elastix import do_elastix
from matched_pairs import matched_pairs

def elastix_processing(args):
    # 创建工作目录
    save_root = os.path.join(args.job_data_root, 'output/elastix')
    if not os.path.exists(save_root):
        os.makedirs(save_root)

    # 根据patientid筛选可以进行配准的uid
    dcm_root = os.path.join(args.job_data_root, 'output/tmp')
    uids = [uid for uid in os.listdir(dcm_root) if 'rpns' not in uid]
    patient_infos = {}
    for uid in uids:
        dcms = os.listdir(os.path.join(dcm_root, uid))
        dcm_meta = dicomio.read_file(os.path.join(dcm_root, uid, dcms[0]), force=True)
        patientid = dcm_meta.get('PatientID', '')
        acq_time = dcm_meta.get('AcquisitionDateTime', '')
        if patientid:
            if patientid not in patient_infos.keys():
                patient_infos[patientid] = [[],[]]
                patient_infos[patientid][0].append(os.path.join(dcm_root, uid))
                patient_infos[patientid][1].append(acq_time)
            else:
                patient_infos[patientid][0].append(os.path.join(dcm_root, uid))
                patient_infos[patientid][1].append(acq_time)

    ## 删除不符合要求的patient
    for key in list(patient_infos.keys()):
        if len(patient_infos[key][0]) < 2:
            del patient_infos[key]
    
    ## 根据拍摄时间进行排序
    for key in list(patient_infos.keys()):
        temp = []
        time_list = patient_infos[key][1]
        sort_idx = np.argsort(time_list)
        for idx in sort_idx:
            temp.append([patient_infos[key][0][idx], time_list[idx]])
        patient_infos[key] = temp
    
    # 开始处理每一个病人数据
    for key in list(patient_infos.keys()):
        uids = patient_infos[key]
        for start_id in range(len(uids) - 1):
            fixed_path, fixed_time = uids[start_id]
            moving_path, moving_time = uids[start_id + 1]
            save_path = os.path.join(save_root, 'pid-{}_elastix_step-{}'.format(key, start_id + 1))
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            
            # 解析json文件得到target_points
            target_path = os.path.join(args.job_data_root, 'output/eval/eval_file_details')
            fixed_json_path = os.path.join(target_path, fixed_path.split('/')[-1] + '.json')
            json_info = json.load(open(fixed_json_path, 'r'))
            points = json_info['annotationSessions'][0]['annotationSet']
            point_list = []
            for point in points:
                left_point, right_point = point['coordinates'][0], point['coordinates'][1]
                center_point = [(left_point['x'] + right_point['x']) / 2.0,
                                (left_point['y'] + right_point['y']) / 2.0,
                                (left_point['z'] + right_point['z']) / 2.0]
                point_list.append(center_point)
            
            target_point_path = os.path.join(save_path, 'target_points.txt')
            with open(target_point_path, 'w+') as file:
                file.write('point')
                file.write('\n')
                file.write(str(len(point_list)))
                file.write('\n')
                for info in point_list:
                    file.write(str(round(info[0], 6)))
                    file.write(' ')
                    file.write(str(round(info[1], 6)))
                    file.write(' ')
                    file.write(str(round(info[2], 6)))
                    file.write('\n')
            
            # 开始配准，从moving到fixed, 并且可以将fixed上的target_points映射到moving上。
            do_elastix(fixed_path=fixed_path, 
                       moving_path=moving_path,
                       affine_param=args.elastix_params_affine,
                       bspline_param=args.elastix_param_bspline,
                       save_path=save_path,  
                       target_points=target_point_path)

            if os.path.exists(os.path.join(save_path, 'outputpoints.txt')):
                print('Finished elastix, and obtain in outputpoints-{}'.format(os.path.join(save_path,'outputpoints.txt')))

            # 开始匹配, 返回字典 key：matched， missing， new
            moving_json_path = os.path.join(target_path, moving_path.split('/')[-1] + '.json')
            match_results = matched_pairs(fixed_json_path, moving_json_path, save_path)

            match_results['info'] = [fixed_path.split('/')[-1], fixed_time, moving_path.split('/')[-1], moving_time]
            with open(os.path.join(save_path, 'match_results.json'), 'w+') as file:
                json.dump(match_results, file, indent=4)

    print('Finished all work !!!')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='elastix processing')
    parser.add_argument('--job_data_root', default='/data/job_715/job_data_preprocess', type=str, help='model')
    parser.add_argument('--elastix_params_affine', default='/shared/lung_cancer_registration/my_elastix_params/configuration_pulmonary_registration_param_parameters_Affine.txt', type=str)
    parser.add_argument('--elastix_param_bspline', default='/shared/lung_cancer_registration/my_elastix_params/configuration_pulmonary_registration_param_parameters_Bspline.txt', type=str)
    args = parser.parse_args()

    elastix_processing(args)

