import time
import pygame
import kivy.uix.widget as _kuw
import kivy.graphics.texture as _ktex
import kivy.graphics as _kgr

_original_blit = pygame.Surface.blit
def _fix_blit(self, source, dest, *a, **k):
    if isinstance(source, pygame.Surface):
        src = pygame.transform.flip(source, False, True)
    else:
        src = source
    return _original_blit(self, src, dest, *a, **k)
pygame.Surface.blit = _fix_blit

_original_convert = pygame.Surface.convert
def _fix_convert(self, *a, **k):
    surf = _original_convert(self, *a, **k)
    try:
        return pygame.transform.flip(surf, False, True)
    except Exception:
        return surf
pygame.Surface.convert = _fix_convert

_original_convert_alpha = pygame.Surface.convert_alpha
def _fix_convert_alpha(self, *a, **k):
    surf = _original_convert_alpha(self, *a, **k)
    try:
        return pygame.transform.flip(surf, False, True)
    except Exception:
        return surf
pygame.Surface.convert_alpha = _fix_convert_alpha

try:
    import pygame.freetype as _ft
    _ft_render = _ft.FreeTypeFont.render
    def _fix_ft_render(self, text, fgcolor=(255,255,255), bgcolor=None):
        res = _ft_render(self, text, fgcolor, bgcolor)
        try:
            surf = res[0]
            rect = res[1]
            surf = pygame.transform.flip(surf, False, True)
            return surf, rect
        except Exception:
            return res
    _ft.FreeTypeFont.render = _fix_ft_render
except Exception:
    pass

try:
    _pf_render = pygame.font.Font.render
    def _fix_pf_render(self, text, antialias, color, background=None):
        surf = _pf_render(self, text, antialias, color, background)
        try:
            return pygame.transform.flip(surf, False, True)
        except Exception:
            return surf
    pygame.font.Font.render = _fix_pf_render
except Exception:
    pass

try:
    import pygame.math as _pm
    _OrigVec = _pm.Vector2
    class _VecFix(_OrigVec):
        def __new__(cls, *a, **k):
            return _OrigVec.__new__(cls, *a, **k)
        @property
        def x(self):
            return _OrigVec.x.fget(self)
        @x.setter
        def x(self, v):
            _OrigVec.x.fset(self, v)
        @property
        def y(self):
            return -_OrigVec.y.fget(self)
        @y.setter
        def y(self, v):
            _OrigVec.y.fset(self, -v)
    _pm.Vector2 = _VecFix
except Exception:
    pass

class PygameSurface:
    def __init__(self, width, height):
        pygame.init()
        self.width = width
        self.height = height
        self.surface = pygame.Surface((width, height))

class PygameWidget(_kuw.Widget):
    def __init__(self, width=640, height=480, **kwargs):
        super().__init__(**kwargs)
        pygame.init()
        self._w = width
        self._h = height
        self.surface = pygame.Surface((width, height))
        try:
            self.texture = _ktex.Texture.create(size=(width, height))
            self.texture.flip_vertical()
        except Exception:
            self.texture = None
        with self.canvas:
            try:
                self.rect = _kgr.Rectangle(texture=self.texture, pos=self.pos, size=(width, height))
            except Exception:
                self.rect = None
        self.bind(pos=self.update_rect, size=self.update_rect)

    def update_rect(self, *args):
        if self.rect is not None:
            self.rect.pos = self.pos
            self.rect.size = self.size

    def update(self):
        try:
            raw_str = pygame.image.tostring(self.surface, 'RGBA')
            if self.texture is not None:
                self.texture.blit_buffer(raw_str, colorfmt='rgba', bufferfmt='ubyte')
                self.texture.flip_vertical()
        except Exception:
            try:
                _s = self.surface.copy()
                _s = pygame.transform.flip(_s, False, True)
                raw_str = pygame.image.tostring(_s, 'RGBA')
                if self.texture is not None:
                    self.texture.blit_buffer(raw_str, colorfmt='rgba', bufferfmt='ubyte')
            except Exception:
                pass