from ctypes import *

class Display(Structure):
    __fields__ = (
    )

class GameObject(Structure):
    __fields__ = (
)

class Model(Structure):
    __fields__ = (
)

class TextureCache(Structure):
    __fields__ = (
)

class Animation(Structure):
    __fields__ = (
)

class TextureInfo(Structure):
    __fields__ = (
)

FnKeyEvent = CFUNCTYPE(None, c_int)
FnEvent = CFUNCTYPE(None)
FnWorldUpdate = CFUNCTYPE(c_int, c_int)

class API(object):
    def __init__(self):
        self.lib = CDLL("bin/libDamnedQuest.so")
        self.done = False

    def create(self, width, height):
        fn = self.lib.CreateDisplay
        fn.argtypes = [c_int, c_int]
        fn.restype = POINTER(Display)
        return fn(width, height)

    def handle_events(self, display, key_press, key_release, redraw):
        fn = self.lib.HandleEvents
        fn.argtypes = [POINTER(Display), FnKeyEvent, FnKeyEvent, FnEvent]
        fn.restype = None
        fn(display, FnKeyEvent(key_press), FnKeyEvent(key_release), FnEvent(redraw))

    def game_loop(self, display, world_update, key_press, key_release, redraw):
        fn = self.lib.GameLoop
        fn.argtypes = [POINTER(Display), FnWorldUpdate, FnKeyEvent, FnKeyEvent, FnEvent]
        fn.restype = None
        fn(display, FnWorldUpdate(world_update), FnKeyEvent(key_press), FnKeyEvent(key_release), FnEvent(redraw))

    def clear(self, display):
        fn = self.lib.Clear
        fn.restype = None
        fn.argtypes = [POINTER(Display)]
        fn(display)

    def swap_buffers(self, display):
        fn = self.lib.SwapBuffers
        fn.restype = None
        fn.argtypes = [POINTER(Display)]
        fn(display)

    def update_timer(self, delta):
        fn = self.lib.UpdateTimer
        fn.restype = None
        fn.argtypes = [c_double]
        fn(float(delta))

    def draw_object(self, obj):
        fn = self.lib.DrawObject
        fn.argtypes = [POINTER(GameObject)]
        fn.restype = None
        fn(obj)

    def create_2d_game_object(self, model, width, height):
        fn = self.lib.Create2DGameObject
        fn.argtypes = [POINTER(Model), c_int, c_int]
        fn.restype = POINTER(GameObject)
        return fn(model, width, height)

    def create_texture_cache(self):
        fn = self.lib.CreateTextureCache
        fn.argtypes = []
        fn.restype = POINTER(TextureCache)
        return fn()

    def load_texture(self, cache, name):
        fn = self.lib.LoadTexture
        fn.argtypes = [POINTER(TextureCache), c_char_p]
        fn.restype = POINTER(TextureInfo)
        return fn(cache, name.encode("UTF-8"))

    def create_animation(self, texture, width, height, cols, rows, offset_left, offset_right):
        fn = self.lib.CreateAnimation
        fn.restype = POINTER(Animation)
        fn.argtypes = [POINTER(TextureInfo), c_double, c_double, c_int, c_int, c_int, c_int]

        return fn(texture, width, height, cols, rows, offset_left, offset_right)

    def change_animation(self, obj, name):
        fn = self.lib.SetAnimation
        fn.restype = None
        fn.argtypes = [POINTER(GameObject), c_char_p]
        fn(obj, name.encode("UTF-8"))

    def print_text(self, text, size, x, y, center=True):
        fn = self.lib.PrintText
        fn.restype = None
        fn.argtypes = [c_char_p, c_double, c_int, c_int, c_bool]
        fn(text.encode("UTF-8"), size, x, y, center)

    def create_model(self):
        fn = self.lib.CreateModel
        fn.restype = POINTER(Model)
        fn.argtypes = []
        return fn()

    def add_animation(self, title, model, animation):
        fn = self.lib.AddAnimation
        fn.restype = None
        fn.argtypes = [c_char_p, POINTER(Model), POINTER(Animation)]
        fn(title.encode("UTF-8"), model, animation)
