"""
TODO
"""

import curses
import _curses
import time

from .user_defined import UserDefined
from .widgets.builtin_widgets import TitleBarWidget, StatusBarWidget, BackgroundWidget
from .fmt import FmtString
from . import renderer
from .color import color

version = "0.0.1"


class TUI(UserDefined):
    """
    TODO
    """

    def run(self):
        """TODO"""
        self.__pre_setup()
        self.setup()  # User defined

        while self.__is_running:
            curses.wrapper(self.__error_handling_loop)

        self.cleanup()  # User defined

    def __pre_setup(self):
        """TODO"""
        self.__is_running = True
        self.__cursor_visible = False
        self.__wait = True
        self.__clear = False
        self.__framerate = 5

        self.__title_bar = TitleBarWidget()
        self.__status_bar = StatusBarWidget()
        self.__background = BackgroundWidget()

        self.origin_x = 0
        self.origin_y = 0

    def __error_handling_loop(self, stdscr):
        """TODO"""
        try:
            self.__execution_loop(stdscr)
        except _curses.error:
            event = stdscr.getch()
            if event == curses.KEY_RESIZE:
                self.window_resized()  # User defined
            else:
                raise

    def __execution_loop(self, stdscr):
        """TODO"""
        curses.curs_set(self.__cursor_visible)
        curses.start_color()
        curses.use_default_colors()

        self.stdscr = stdscr

        self.__draw_builtin_widgets()
        self.draw()  # User defined

        if self.__clear:
            self.stdscr.clear()
            self.__clear = False
            self.draw()
            self.__draw_builtin_widgets()

        self.stdscr.refresh()

        if self.__wait:
            self.stdscr.nodelay(0)
            key = stdscr.getkey()
            self.key_pressed(key)  # User defined

        else:
            self.stdscr.nodelay(1)
            try:
                key = stdscr.getkey()
                self.key_pressed(key)  # User defined
            except _curses.error:
                time.sleep(1 / self.__framerate)

        self.stdscr.refresh()

    ###########################
    """ User UI controllers """
    ###########################

    def hide_cursor(self):
        """TODO"""
        self.__cursor_visible = False

    def show_cursor(self):
        """TODO"""
        self.__cursor_visible = True

    def wait_for_input(self):
        """TODO"""
        self.__wait = True

    def no_wait_for_input(self):
        """TODO"""
        self.__wait = False

    def framerate(self, framerate):
        """Set the framerate
        --------------------
        :param: framerate
            :type: float or int
        """
        self.__framerate = framerate

    def exit(self):
        """Exit the program safely
        --------------------------
        """
        self.__is_running = False

    def clear(self):
        """TODO"""
        self.__clear = True

    def get_width(self):
        """Return the width of the screen
        ---------------------------------
        """
        width = self.stdscr.getmaxyx()[1]
        return width

    def get_height(self, relative=True):
        """Return the height of the screen
        ----------------------------------
        :param: relative
            :type: bool
            :default: True

            If relative is True, do not include the title bar or status bar
            as part of the 'height' of the screen if they are enabled.

            If relative is False, return the actual total height of the screen.
        """
        height = self.stdscr.getmaxyx()[0]
        if relative:
            if self.__title_bar.is_enabled():
                height -= 1
            if self.__status_bar.is_enabled():
                height -= 1
        return height

    def write(self, y=None, x=None, text='', fg=-1, bg=-1, style=0, relative=True, wrap=False):
        """TODO"""
        if relative:
            y_pos = self.origin_y + y
            x_pos = self.origin_x + x

        if isinstance(text, FmtString):
            for index, (_text, _color) in enumerate(text):
                if index == 0:
                    renderer.write(self.stdscr, y=y_pos, x=x_pos, text=_text, colors=_color)
                else:
                    renderer.write(self.stdscr, text=_text, colors=_color)
        else:
            renderer.write(self.stdscr, y_pos, x_pos, text, fg, bg, style, wrap)

    #######################
    """ Builtin Widgets """
    #######################

    def __draw_builtin_widgets(self):
        """TODO"""
        self.__background.draw(self.stdscr)
        self.__title_bar.draw(self.stdscr)
        self.__status_bar.draw(self.stdscr)

    def enable_title_bar(self, title:str, fg=-1, bg=-1, style=0, justification:str = "center"):
        """TODO"""
        self.__title_bar.enable()
        self.__title_bar.set_title(title=title, fg=fg, bg=bg, style=style)
        self.__title_bar.set_justification(justification)
        self.origin_y += 1
        return self.__title_bar

    def disable_title_bar(self):
        """TODO"""
        self.__title_bar.disable()
        self.origin_y -= 1
        self.clear()

    def hide_title_bar(self):
        """TODO"""
        self.__title_bar.disable()
        self.origin_y -= 1
        self.clear()

    def show_title_bar(self):
        """TODO"""
        self.__title_bar.enable()
        self.origin_y += 1
        self.clear()

    def toggle_title_bar(self):
        """TODO"""
        if self.__title_bar.is_enabled():
            self.__title_bar.disable()
        else:
            self.__title_bar.enable()
        self.clear()

    def enable_status_bar(self, text:str, fg=-1, bg=-1, style=0, justification="left", pad_char=" "):
        """TODO"""
        self.__status_bar.enable()
        self.__status_bar.set_title(title=text, fg=fg, bg=bg, style=style)
        self.__status_bar.set_justification(justification)
        return self.__status_bar

    def disable_status_bar(self):
        """TODO"""
        self.__status_bar.disable()
        self.clear()

    def show_status_bar(self):
        """TODO"""
        self.__status_bar.enable()
        self.clear()

    def hide_status_bar(self):
        """TODO"""
        self.__status_bar.disable()
        self.clear()

    def toggle_status_bar(self):
        """TODO"""
        if self.__status_bar.is_enabled():
            self.__status_bar.disable()
        else:
            self.__status_bar.enable()
        self.clear()

    def enable_background(self, ch=' ', fg=-1, bg=-1, style=0):
        """TODO"""
        self.__background.enable()
        self.__background.set_colors(fg=fg, bg=bg, style=style)
        self.__background.set_ch(ch)
        return self.__background

    def disable_background(self):
        """TODO"""
        self.__background.disable()
        self.clear()

    def hide_background(self):
        """TODO"""
        self.__background.disable()
        self.clear()

    def show_background(self):
        """TODO"""
        self.__background.enable()
        self.clear()

    def toggle_background(self):
        """TODO"""
        if self.__background.is_enabled():
            self.__background.disable()
        else:
            self.__background.enable()
        self.clear()
