from ctypes import *

from define import *

class TheFilter(Structure):
  pass

# ?? FILE ????????
class FILE(Structure):
    _fields_ = []

class key_struct(Structure):
  pass

class cat_struct(Structure):
  pass

class struct_tab(Structure):
  pass

class wcs_struct(Structure):
  _pack_ = 16

class wcsprm(Structure):
  _pack_ = 16

class linprm(Structure):
  _pack_ = 16

class celprm(Structure):
  _pack_ = 16

class prjprm(Structure):
  _pack_ = 16

class tnxaxisstruct(Structure):
  _pack_ = 16

class polystruct(Structure):
  _pack_ = 16

class structassoc(Structure):
  pass

structassoc._fields_ = [
  ('list', POINTER(c_float)),  # Pointer to array of floats
  ('nobj', c_int),
  ('ncol', c_int),
  ('ndata', c_int),
  ('hash', POINTER(c_int)),    # Pointer to array of ints
  ('data', POINTER(c_float)),  # Pointer to array of floats
  ('radius', c_float),
]

tnxaxisstruct._fields_ = [
  ('type', c_int),
  ('xorder', c_int),
  ('yorder', c_int),
  ('xterms', c_int),
  ('ncoeff', c_int),
  ('xrange', c_double),
  ('yrange', c_double),
  ('xmaxmin', c_double),
  ('ymaxmin', c_double),
  ('coeff', POINTER(c_double)),  # Pointer to array of doubles
  ('xbasis', POINTER(c_double)), # Pointer to array of doubles
  ('ybasis', POINTER(c_double)), # Pointer to array of doubles
]

polystruct._fields_ = [
  ('basis', POINTER(c_double)),  # Pointer to array of doubles
  ('coeff', POINTER(c_double)),  # Pointer to array of doubles
  ('ncoeff', c_int),
  ('group', POINTER(c_int)),     # Pointer to array of ints
  ('ndim', c_int),
  ('degree', POINTER(c_int)),    # Pointer to array of ints
  ('ngroup', c_int),
]

prjprm._fields_ = [
  ('flag', c_int),
  ('n', c_int),
  ('r0', c_double),
  ('p', c_double * 200),  # Fixed-size array of doubles
  ('w', c_double * 10),   # Fixed-size array of doubles
  ('tnx_latcor', POINTER(tnxaxisstruct)),  # Pointer to tnxaxisstruct
  ('tnx_lngcor', POINTER(tnxaxisstruct)),  # Pointer to tnxaxisstruct
  ('inv_x', POINTER(polystruct)),          # Pointer to polystruct
  ('inv_y', POINTER(polystruct))           # Pointer to polystruct
]

celprm._fields_ = [
  ('flag', c_int),
  ('ref', c_double * 4),  # Fixed-size array of doubles
  ('euler', c_double * 5),  # Fixed-size array of doubles
  ('prjfwd', CFUNCTYPE(
    c_int,  # Function pointer for prjfwd
    c_double,
    c_double,
    POINTER(prjprm),
    POINTER(c_double),
    POINTER(c_double))),
  ('prjrev', CFUNCTYPE(
    c_int,  # Function pointer for prjrev
    c_double,
    c_double,
    POINTER(prjprm),
    POINTER(c_double),
    POINTER(c_double)))
]

linprm._fields_ = [
  ('flag', c_int),
  ('naxis', c_int),
  ('crpix', POINTER(c_double)),  # Pointer to array
  ('pc', POINTER(c_double)),     # Pointer to array
  ('cdelt', POINTER(c_double)),  # Pointer to array
  ('piximg', POINTER(c_double)), # Intermediate pointer
  ('imgpix', POINTER(c_double)), # Intermediate pointer
]

wcsprm._fields_ = [
  ('flag', c_int),
  ('pcode', c_char * 4),
  ('lngtyp', c_char * 5),
  ('lattyp', c_char * 5),
  ('lng', c_int),
  ('lat', c_int),
  ('cubeface', c_int),
]

wcs_struct._fields_ = [
  ('naxis', c_int),
  ('naxisn', c_int * NAXIS),
  ('ctype', c_char * 9 * NAXIS),
  ('cunit', c_char * 32 * NAXIS),
  ('crval', c_double * NAXIS),
  ('cdelt', c_double * NAXIS),
  ('crpix', c_double * NAXIS),
  ('crder', c_double * NAXIS),
  ('csyer', c_double * NAXIS),
  ('cd', c_double * (NAXIS * NAXIS)),
  ('projp', POINTER(c_double)),  # Pointer to array
  ('nprojp', c_int),
  ('longpole', c_double),
  ('latpole', c_double),
  ('wcsmin', c_double * NAXIS),
  ('wcsmax', c_double * NAXIS),
  ('wcsscale', c_double * NAXIS),
  ('wcsscalepos', c_double * NAXIS),
  ('wcsmaxradius', c_double),
  ('outmin', c_int * NAXIS),
  ('outmax', c_int * NAXIS),
  ('lat', c_int),
  ('lng', c_int),
  ('r0', c_double),
  ('lindet', c_double),
  ('chirality', c_int),
  ('pixscale', c_double),
  ('ap2000', c_double),
  ('dp2000', c_double),
  ('ap1950', c_double),
  ('dp1950', c_double),
  ('obsdate', c_double),
  ('equinox', c_double),
  ('epoch', c_double),
  ('radecsys', c_int),  # or an enum type if you have it
  ('celsys', c_int),    # or an enum type if you have it
  ('celsysmat', c_double * 4),
  ('celsysconvflag', c_int),
  ('wcsprm', POINTER(wcsprm)),  # Placeholder for pointer
  ('lin', POINTER(linprm)),     # Placeholder for pointer
  ('cel', POINTER(celprm)),     # Placeholder for pointer
  ('prj', POINTER(prjprm)),     # Placeholder for pointer
  ('tnx_latcor', POINTER(tnxaxisstruct)),  # Placeholder for pointer
  ('tnx_lngcor', POINTER(tnxaxisstruct)),  # Placeholder for pointer
  ('inv_x', POINTER(polystruct)),   # Placeholder for pointer
  ('inv_y', POINTER(polystruct))    # Placeholder for pointer
]

key_struct._fields_ = [
  ("name", c_char * 80),
  ("comment", c_char * 80),
  ("ptr", c_void_p),
  ("htype", c_int), # enum
  ("ttype", c_int), # enum
  ("printf", c_char * 80),
  ("unit", c_char * 80),
  ("voucd", c_char * 80),
  ("vounit", c_char * 80),
  ("naxis", c_int),
  ("naxisn", POINTER(c_int)),
  ("nobj", c_int),
  ("nbytes", c_int),
  ("pos", c_long),
  ("prevkey", POINTER(key_struct)),
  ("nextkey", POINTER(key_struct)),
  ("tab", POINTER(struct_tab)),
  ("allocflag", c_int),
]

struct_tab._fields_ = [
  ("bitpix", c_int),
  ("bytepix", c_int),
  ("bitsgn", c_int),
  ("bscale", c_double),
  ("bzero", c_double),
  ("blank", c_int),
  ("blankflag", c_int),
  ("compress_type", c_int), # ?c??enum???0 1 2
  ("compress_buf", c_char_p),
  ("compress_bufptr", c_char_p),
  ("compress_curval", c_int),
  ("compress_checkval", c_int),
  ("compress_checkval", c_size_t),
  ("naxis", c_int),
  ("naxisn", POINTER(c_int)),
  ("tfields", c_int),
  ("pcount", c_int),
  ("gcount", c_int),
  ("tabsize", c_ulonglong), # if not exist unsigned long long, use size_t
  ("xtension", c_char * 82),
  ("extname", c_char * 82),
  ("headbuf", c_char_p),
  ("headbuf", c_int),
  ("bodybuf", c_char_p),
  ("bodypos", c_longlong), # OFF_T
  ("headpos", c_longlong), # OFF_T
  ("cat", POINTER(cat_struct)),
  ("prevtab", POINTER(struct_tab)),
  ("seg", c_int),
  ("nseg", c_int),
  ("key", POINTER(key_struct)),
  ("nkey", c_int),
  ("swapname", c_char * MAX_CHAR),
  ("bodysum", c_uint)
]

cat_struct._fields_ = [
  ("filename", c_char * MAX_CHAR),
  ("file", POINTER(FILE)),
  ("tab", POINTER(struct_tab)),
  ("ntab", c_int),
  ("access_type1", c_int), # enum
]

class PicStruct(Structure):
  _alignment_ = 16

PicStruct._fields_ = [
  ("filename", c_char * MAX_CHAR),
  ("rfilename", c_char_p),
  ("ident", c_char * MAX_CHAR),
  ("rdent", c_char * MAX_CHAR),
  ("cat", POINTER(cat_struct)),
  ("tab", POINTER(struct_tab)),
  ("file", POINTER(FILE)),
  # main image parameters
  ("bitpix", c_int),
  ("bytepix", c_int),
  ("bitsgn", c_int),
  ("width", c_int),
  ("height", c_int),
  ("npix", c_ulonglong), # c_ulonglong or c_size_t
  ("bscale", c_double),
  ("bzero", c_double),
  ("ngamma", c_double),
  ("nlevels", c_int),
  ("pixmin", c_float),
  ("pixmax", c_float),
  ("y", c_int),
  ("ymin", c_int),
  ("ymax", c_int),
  ("yblank", c_int),
  ("strip", POINTER(c_float)),
  ("fstrip", POINTER(c_uint)),
  ("stripheight", c_int),
  ("stripmargin", c_int),
  ("stripstep", c_int),
  ("stripy", c_int),
  ("stripylim", c_int),
  ("stripysclim", c_int),
  # basic astrometric parameters
  ("pixscale", c_double),
  ("epoch", c_double),
  # basic photometric parameters
  ("gain", c_double),
  ("satur_level", c_double),
  # background parameters
  ("back", POINTER(c_float)),
  ("dback", c_int),
  ("backh", c_int),
  ("nbackp", c_int),
  ("nbackx", c_int),
  ("nbacky", c_int),
  ("nbackfx", c_int),
  ("nbackfy", c_int),
  ("backmean", c_float),
  ("backsig", c_float),
  ("sigfac", c_float),
  ("backline", POINTER(c_float)),
  ("dthresh", c_float),
  ("thresh", c_float),
  ("back_type", c_int), # enum
  # astrometric parameters
  ("wcs", POINTER(wcs_struct)),
  ("assoc", POINTER(structassoc)),
  # image interpolation
  ("interp_flag", c_int),
  ("interp_backup", POINTER(c_float)),
  ("weight_thresh", c_float),
  ("interp_ytimeoutbuf", POINTER(c_int)),
  ("interp_xtimeout", c_int),
  ("interp_ytimeout", c_int),
  ("reffield", POINTER(PicStruct)),
  ("mefpos", c_longlong)
]