import os
from ctypes import Structure, POINTER, c_int, c_float, c_void_p, c_char, \
    c_char_p, c_double
from .dll import DLL
from .stdinc import Uint8, Uint32, Sint16
from .render import SDL_Renderer
from .surface import SDL_Surface

# NOTE: This module is currently missing wrappers for the image filtering
# functions in SDL2_imageFilter.h. However, because we have Pillow on Python
# this isn't really a pressing concern. Time permitting, these functions may
# be wrapped at a later date for the sake of completeness.

__all__ = [
    # Structs
    "FPSManager",
    
    # Defines
    "FPS_UPPER_LIMIT", "FPS_LOWER_LIMIT", "FPS_DEFAULT",
    "SDL2_GFXPRIMITIVES_MAJOR", "SDL2_GFXPRIMITIVES_MAJOR",
    "SDL2_GFXPRIMITIVES_MICRO", "SMOOTHING_OFF", "SMOOTHING_ON",

    # Functions
    "SDL_initFramerate", "SDL_getFramerate",
    "SDL_setFramerate", "SDL_getFramecount", "SDL_framerateDelay",
    "pixelColor", "pixelRGBA", "hlineColor",
    "hlineRGBA", "vlineColor", "vlineRGBA", "rectangleColor",
    "rectangleRGBA", "roundedRectangleColor", "roundedRectangleRGBA",
    "boxColor", "boxRGBA", "roundedBoxColor", "roundedBoxRGBA",
    "lineColor", "lineRGBA", "aalineColor", "aalineRGBA",
    "thickLineColor", "thickLineRGBA", "circleColor", "circleRGBA",
    "arcColor", "arcRGBA", "aacircleColor", "aacircleRGBA",
    "filledCircleColor", "filledCircleRGBA", "ellipseColor",
    "ellipseRGBA", "aaellipseColor", "aaellipseRGBA",
    "filledEllipseColor", "filledEllipseRGBA", "pieColor", "pieRGBA",
    "filledPieColor", "filledPieRGBA", "trigonColor", "trigonRGBA",
    "aatrigonColor", "aatrigonRGBA", "filledTrigonColor",
    "filledTrigonRGBA", "polygonColor", "polygonRGBA", "aapolygonColor",
    "aapolygonRGBA", "filledPolygonColor", "filledPolygonRGBA",
    "texturedPolygon", "bezierColor", "bezierRGBA",
    "gfxPrimitivesSetFont", "gfxPrimitivesSetFontRotation",
    "characterColor", "characterRGBA", "stringColor", "stringRGBA",
    "rotozoomSurface", "rotozoomSurfaceXY", "rotozoomSurfaceSize",
    "rotozoomSurfaceSizeXY", "zoomSurface", "zoomSurfaceSize", "shrinkSurface",
    "rotateSurface90Degrees",

    # Python Functions
    "get_dll_file"
]


try:
    dll = DLL("SDL2_gfx", ["SDL2_gfx", "SDL2_gfx-1.0"],
              os.getenv("PYSDL2_DLL_PATH"))
except RuntimeError as exc:
    raise ImportError(exc)


def get_dll_file():
    """Gets the file name of the loaded SDL2_gfx library."""
    return dll.libfile

_bind = dll.bind_function


FPS_UPPER_LIMIT = 200
FPS_LOWER_LIMIT = 1
FPS_DEFAULT = 30


class FPSManager(Structure):
    _fields_ = [("framecount", Uint32),
                ("rateticks", c_float),
                ("baseticks", Uint32),
                ("lastticks", Uint32),
                ("rate", Uint32)
                ]

SDL_initFramerate = _bind("SDL_initFramerate", [POINTER(FPSManager)])
SDL_setFramerate = _bind("SDL_setFramerate", [POINTER(FPSManager), Uint32], c_int)
SDL_getFramerate = _bind("SDL_getFramerate", [POINTER(FPSManager)], c_int)
SDL_getFramecount = _bind("SDL_getFramecount", [POINTER(FPSManager)], Uint32)
SDL_framerateDelay = _bind("SDL_framerateDelay", [POINTER(FPSManager)], Uint32)

SDL2_GFXPRIMITIVES_MAJOR = 1
SDL2_GFXPRIMITIVES_MINOR = 0
SDL2_GFXPRIMITIVES_MICRO = 4

pixelColor = _bind("pixelColor", [POINTER(SDL_Renderer), Sint16, Sint16, Uint32], c_int)
pixelRGBA = _bind("pixelRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
hlineColor = _bind("hlineColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint32], c_int)
hlineRGBA = _bind("hlineRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
vlineColor = _bind("vlineColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint32], c_int)
vlineRGBA = _bind("vlineRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
rectangleColor = _bind("rectangleColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
rectangleRGBA = _bind("rectangleRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
roundedRectangleColor = _bind("roundedRectangleColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
roundedRectangleRGBA = _bind("roundedRectangleRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
boxColor = _bind("boxColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
boxRGBA = _bind("boxRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
roundedBoxColor = _bind("roundedBoxColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
roundedBoxRGBA = _bind("roundedBoxRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
lineColor = _bind("lineColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
lineRGBA = _bind("lineRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
aalineColor = _bind("aalineColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
aalineRGBA = _bind("aalineRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
thickLineColor = _bind("thickLineColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint32], c_int)
thickLineRGBA = _bind("thickLineRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8, Uint8], c_int)
circleColor = _bind("circleColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint32], c_int)
circleRGBA = _bind("circleRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
arcColor = _bind("arcColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
arcRGBA = _bind("arcRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
aacircleColor = _bind("aacircleColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint32], c_int)
aacircleRGBA = _bind("aacircleRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
filledCircleColor = _bind("filledCircleColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint32], c_int)
filledCircleRGBA = _bind("filledCircleRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
ellipseColor = _bind("ellipseColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
ellipseRGBA = _bind("ellipseRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
aaellipseColor = _bind("aaellipseColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
aaellipseRGBA = _bind("aaellipseRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
filledEllipseColor = _bind("filledEllipseColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
filledEllipseRGBA = _bind("filledEllipseRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
pieColor = _bind("pieColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
pieRGBA = _bind("pieRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
filledPieColor = _bind("filledPieColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
filledPieRGBA = _bind("filledPieRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
trigonColor = _bind("trigonColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
trigonRGBA = _bind("trigonRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
aatrigonColor = _bind("aatrigonColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
aatrigonRGBA = _bind("aatrigonRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
filledTrigonColor = _bind("filledTrigonColor", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint32], c_int)
filledTrigonRGBA = _bind("filledTrigonRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, Sint16, Sint16, Sint16, Sint16, Uint8, Uint8, Uint8, Uint8], c_int)
polygonColor = _bind("polygonColor", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint32], c_int)
polygonRGBA = _bind("polygonRGBA", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint8, Uint8, Uint8, Uint8], c_int)
aapolygonColor = _bind("aapolygonColor", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint32], c_int)
aapolygonRGBA = _bind("aapolygonRGBA", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint8, Uint8, Uint8, Uint8], c_int)
filledPolygonColor = _bind("filledPolygonColor", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint32], c_int)
filledPolygonRGBA = _bind("filledPolygonRGBA", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, Uint8, Uint8, Uint8, Uint8], c_int)
texturedPolygon = _bind("texturedPolygon", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, POINTER(SDL_Surface), c_int, c_int], c_int)
bezierColor = _bind("bezierColor", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, c_int, Uint32], c_int)
bezierRGBA = _bind("bezierRGBA", [POINTER(SDL_Renderer), POINTER(Sint16), POINTER(Sint16), c_int, c_int, Uint8, Uint8, Uint8, Uint8], c_int)
gfxPrimitivesSetFont = _bind("gfxPrimitivesSetFont", [c_void_p, Uint32, Uint32])
gfxPrimitivesSetFontRotation = _bind("gfxPrimitivesSetFontRotation", [Uint32])
characterColor = _bind("characterColor", [POINTER(SDL_Renderer), Sint16, Sint16, c_char, Uint32], c_int)
characterRGBA = _bind("characterRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, c_char, Uint8, Uint8, Uint8, Uint8], c_int)
stringColor = _bind("stringColor", [POINTER(SDL_Renderer), Sint16, Sint16, c_char_p, Uint32], c_int)
stringRGBA = _bind("stringRGBA", [POINTER(SDL_Renderer), Sint16, Sint16, c_char_p, Uint8, Uint8, Uint8, Uint8], c_int)

SMOOTHING_OFF = 0
SMOOTHING_ON = 1
rotozoomSurface = _bind("rotozoomSurface", [POINTER(SDL_Surface), c_double, c_double, c_int], POINTER(SDL_Surface))
rotozoomSurfaceXY = _bind("rotozoomSurfaceXY", [POINTER(SDL_Surface), c_double, c_double, c_double, c_int], POINTER(SDL_Surface))
rotozoomSurfaceSize = _bind("rotozoomSurfaceSize", [c_int, c_int, c_double, c_double, POINTER(c_int), POINTER(c_int)])
rotozoomSurfaceSizeXY = _bind("rotozoomSurfaceSizeXY", [c_int, c_int, c_double, c_double, c_double, POINTER(c_int), POINTER(c_int)])
zoomSurface = _bind("zoomSurface", [POINTER(SDL_Surface), c_double, c_double, c_int], POINTER(SDL_Surface))
zoomSurfaceSize = _bind("zoomSurfaceSize", [c_int, c_int, c_double, c_double, POINTER(c_int), POINTER(c_int)])
shrinkSurface = _bind("shrinkSurface", [POINTER(SDL_Surface), c_int, c_int], POINTER(SDL_Surface))
rotateSurface90Degrees = _bind("rotateSurface90Degrees", [POINTER(SDL_Surface), c_int], POINTER(SDL_Surface))
