from ctypes import POINTER, c_double, c_int, c_uint, c_ulong, cdll
import sys
import os
script_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(script_dir)
from cuda_init import *
from flag_obj import FlagObj
from pic_struct_init import PicStructInit
from plist import PlistVars
from prefs import Prefs
from process.analyse import analyse_py
from process.back import back_esitmate_py
from structs.pic_struct import PicStruct
from structs.filter import filter_init
import cupy as cp
import traceback



def Detect_Source(image_data, prefs_file_path=None):
    script_dir = os.path.dirname(os.path.abspath(__file__))
    lib: CDLL = cdll.LoadLibrary(os.path.join(script_dir,"libcuda2.so"))
    # Load Prefs
    prefs = Prefs(prefs_file_path)
    # Load FlagObj
    flag_obj = FlagObj()
    plist_vars = PlistVars()
    try:
        
        image_data = cp.array(image_data)
        # 打印GPU内存使用情况
        # mem_pool = cp.get_default_memory_pool()
        # print(f"Before processing, used GPU memory: {mem_pool.used_bytes()} bytes")

        # PicStruct
        field: PicStruct = PicStructInit(image_data, prefs)
        init_device(image_data, field, lib)

        # 背景估计
        back_esitmate_py(field, lib, prefs)
        cp.cuda.runtime.deviceSynchronize()
        
        # 初始化检测
        lib.init_detection()

        # 使用filter
        filter = filter_init()
        lib.cudaFilter.argtypes = [POINTER(c_float), c_uint]
        lib.cudaFilter(filter.conv[0], filter.convw)

        # 检测过程
        numValidObj = c_ulong(0)
        numValidPix = c_ulong(0)
        lib.run_detection.argtypes = [c_float, c_float, c_int, POINTER(c_ulong), POINTER(c_ulong)]
        lib.run_detection(field.dthresh, field.thresh, prefs.ext_minarea, byref(numValidObj), byref(numValidPix))

        # # 去混叠
        lib.init_deblend.argtypes = [c_float, c_int, c_ulong, c_ulong]
        lib.init_deblend(field.dthresh, prefs.deblend_nthresh, numValidObj, numValidPix)
        lib.parcel_out.argtypes = [c_float, c_int, c_int, c_ulong, c_ulong, c_double]
        lib.parcel_out.restype = c_int
        detected_num = lib.parcel_out(field.dthresh, prefs.deblend_nthresh,
                                    prefs.deb_maxarea, numValidObj, numValidPix,
                                    prefs.deblend_mincount)

        # # detected_num = lib.parcel_out(field.dthresh, prefs.deblend_nthresh, prefs.deb_maxarea, numValidObj, numValidPix, prefs.deblend_mincount)

        # # 清理去混叠
        lib.clear_deblend(prefs.deblend_nthresh)

        # # # 分析
        result,num = analyse_py(detected_num, field, lib, prefs, flag_obj, plist_vars)
        
        return result, num
    
    except cp.cuda.memory.OutOfMemoryError as e:
        print(f"GPU memory error: {e}")
        traceback.print_exc()
    except cp.cuda.runtime.CUDARuntimeError as e:
        print(f"CUDA runtime error: {e}")
        traceback.print_exc()
    except Exception as e:
        print(f"General error during processing: {e}")
        traceback.print_exc()

