from ctypes import CFUNCTYPE, POINTER, Structure, c_char, c_double, c_int

from define import NAXIS

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 WcsStruct(Structure):
  _pack_ = 16

  def __init__(self):
    self.lng = 0
    self.lat = 0
    self.equinox = 0.0

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),
]

WcsStruct._fields_ = [
  ("lng", c_int),
  ("lat", c_int),
  ("lng", c_double),
]

# WcsStruct._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
# ]