import prismatui as pr

# //////////////////////////////////////////////////////////////////////////////
class BackendCurses(pr.Backend):
    def __init__(self):
        super().__init__()
        self.curses = __import__("curses")

    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    def set_nodelay(self, boolean: bool) -> None:
        self.stdscr.nodelay(boolean)
        self._nodelay_mode = boolean

    # --------------------------------------------------------------------------
    def sleep(self, ms: int) -> None:
        self.curses.napms(ms)

    # --------------------------------------------------------------------------
    def write_text(self, y: int, x: int, chars: str, attr: int = 0) -> None:
        try: self.stdscr.addstr(y, x, chars, attr)
        except self.curses.error: pass # ignore out of bounds error

    # --------------------------------------------------------------------------
    def get_size(self, update = False) -> tuple[int,int]:
        if update: self.curses.update_lines_cols()
        return self.curses.LINES, self.curses.COLS


    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    def supports_color(self) -> bool:
        try: return self.curses.can_change_color()
        except self.curses.error: return False

    # --------------------------------------------------------------------------
    def init_color(self, i: int, r: int, g: int, b: int) -> None:
        try:
            self.curses.init_color(i, r, g, b)
            self._registered_colors[i] = (r,g,b)
        except self.curses.error: pass

    # --------------------------------------------------------------------------
    def init_pair(self, i: int, fg: int, bg: int) -> None:
        try:
            self.curses.init_pair(i, fg, bg)
            self._registered_cpairs[i] = (fg, bg)
        except self.curses.error: pass

    # --------------------------------------------------------------------------
    def get_color_pair(self, i: int) -> int:
        try: return self.curses.color_pair(i)
        except self.curses.error: return 0


    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    def resize(self, h: int, w: int) -> None:
        try: self.stdscr.resize(h, w)
        except self.curses.error: pass

    # --------------------------------------------------------------------------
    def strong_reset(self) -> None:
        self._end()
        self._start()


    # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    def _start(self) -> None:
        self.stdscr = self.curses.initscr()
        self.curses.noecho()
        self.curses.cbreak()
        self.stdscr.keypad(1)
        self.curses.curs_set(0)

        try: self.curses.start_color()
        except: pass

        for i,(r,g,b) in self._registered_colors.items():
            self.init_color(i, r, g, b)

        for i,(fg,bg) in self._registered_cpairs.items():
            self.init_pair(i, fg, bg)

        self.set_nodelay(self._nodelay_mode)

    # --------------------------------------------------------------------------
    def _end(self) -> None:
        if "stdscr" not in self.__dict__: return
        self.stdscr.keypad(0)
        self.curses.echo()
        self.curses.nocbreak()
        self.curses.endwin()

    # --------------------------------------------------------------------------
    def _refresh(self) -> None:
        return # unnecessary for curses, as stdscr.refresh() gets implicitly called by stdscr.getkey()

    # --------------------------------------------------------------------------
    def _get_key(self) -> int:
        ### exhausting input buffer only makes sense in nodelay mode
        if not self._nodelay_mode:
            return self.stdscr.getch()

        ### exhaust input buffer to avoid laggy "repeated" inputs in nodelay mode
        this_char = pr.ERR
        next_char = self.stdscr.getch()
        while next_char != pr.ERR:
            this_char = next_char
            next_char = self.stdscr.getch()
        return this_char


# //////////////////////////////////////////////////////////////////////////////
