# distutils: language = c++
# distutils: sources = sdlterm/src/sdlterm.cc
# distutils: include_dirs = /usr/include/SDL sdlterm/src
# distutils: libraries = SDL SDL_ttf
# distutils: define_macros = _GNU_SOURCE=1 _REENTRANT
# distutils: extra_compile_args = --std=c++11
# cython: language_level=3

from libcpp cimport bool


cdef extern from "sdlterm.h":
    cdef struct Event_key:
        char *keyname
        Py_UNICODE unicode
        int mod

    cdef struct Event_mouse:
        int x, y
        int relx, rely
        int button

    cdef struct Event:
        # enum
        int QUIT
        int RESIZE
        int KEYPRESS
        int MOUSEDOWN
        int MOUSEUP
        int MOUSEMOVE
        int MOUSEHOVER
        int MOUSEWHEEL

        int type
        Event_key key
        Event_mouse mouse

    cdef cppclass Terminal:
        Terminal() except +

        void select_font(char *fname_regular, char *fname_bold, int ptsize) except +
        void resize(int pxwidth, int pxheight) except +

        void erase()
        void putch(int x, int y, Py_UNICODE ch)
        void commit()

        int prepare_attr(int fg, int bg, int style)
        void set_attr(int value)

        void show_cursor(int x, int y)
        void hide_cursor()

        bool wait_event(Event event, int timeout) except +

        int get_width()
        int get_height()


cdef class SDLTerminal:
    cdef Terminal *thisptr      # hold a C++ instance which we're wrapping
    cdef Event event

    def __cinit__(self):
        self.thisptr = new Terminal()
    def __dealloc__(self):
        del self.thisptr

    def select_font(self, bytes fname_regular, bytes fname_bold, int ptsize):
        self.thisptr.select_font(fname_regular, fname_bold, ptsize)
    def resize(self, width, height):
        self.thisptr.resize(width, height)

    def erase(self):
        self.thisptr.erase()
    def putch(self, x, y, ch):
        self.thisptr.putch(x, y, ch)
    def commit(self):
        self.thisptr.commit()

    def prepare_attr(self, fg, bg, style):
        return self.thisptr.prepare_attr(fg, bg, style)
    def set_attr(self, value):
        self.thisptr.set_attr(value)

    def show_cursor(self, x, y):
        self.thisptr.show_cursor(x, y)
    def hide_cursor(self):
        self.thisptr.hide_cursor()

    def wait_event(self, timeout=None):
        if not self.thisptr.wait_event(self.event, timeout or 0):
            # timeout
            return None
        event = self.event
        if event.type == event.MOUSEHOVER:
            return ('mousehover', 0, event.mouse.x, event.mouse.y)
        if event.type == event.MOUSEMOVE:
            return ('mousemove', 0, event.mouse.x, event.mouse.y, event.mouse.relx, event.mouse.rely)
        if event.type == event.MOUSEDOWN:
            return ('mousedown', event.mouse.button, event.mouse.x, event.mouse.y)
        if event.type == event.MOUSEUP:
            return ('mouseup', event.mouse.button, event.mouse.x, event.mouse.y)
        if event.type == event.MOUSEWHEEL:
            return ('mousewheel', event.mouse.button, event.mouse.x, event.mouse.y)
        if event.type == event.KEYPRESS:
            keyname = event.key.keyname
            if keyname:
                keyname = keyname.decode()
            else:
                keyname = None
            char = event.key.unicode
            if char == '\x00':
                char = None
            mod = event.key.mod
            return ('keypress', keyname, char, mod)
        if event.type == event.RESIZE:
            return ('resize',)
        if event.type == event.QUIT:
            return ('quit',)
        return ('unknown',)

    property width:
        def __get__(self): return self.thisptr.get_width()
    property height:
        def __get__(self): return self.thisptr.get_height()

