from typing import List, Optional, Set, Tuple
import pygame

from .constants import *
font = pygame.font



class Font(object):

    """
    The font class used to manage pygame's font class easier and to set
    the text's style
    """
    
    __slots__ = ("family", "size", "smooth_char", "__font")

    def __init__(self, family: str = None, px: int = None, smooth_char: bool = True, **styles):
        """The constructor of the Font

        Args:
            family (str, optional): the font family. Can be a `*.ttf`-file(path) or a *downloaded* font name. If None (default) the default system font will be used.
            px (str, optional): the size of the font. If None (default) the constant from pygameGUI.constants.DEFAULT_FONT_SIZE will be used.

        Raises:
            ValueError: If the font family is not known and it isn't a "*.ttf" file
        """
        if family is None:
            self.family = font.get_default_font()
        else:
            if family not in AVAILABLE_SYSTEM_FONTS and family[:-4] == ".ttf":
                print(family not in AVAILABLE_SYSTEM_FONTS)
                raise ValueError("Font-family cannot be used.")

            self.family = family
        
        if px is None:
            self.size = DEFAULT_FONT_SIZE
        else:
            self.size = px

        self.smooth_char = smooth_char

        # intern font object
        if self.family[:-4] == ".ttf":
            self.__font: pygame.font.Font = pygame.font.Font(family, px)
        else:
            self.__font: pygame.font.SysFont = pygame.font.SysFont(family, self.size)

    def get_pygame_font(self) -> pygame.font.Font:
        """
        Returns the pygame font instance

        Returns:
            pygame.font.Font: the pygame.font.Font instance
        """
        return self.__font

    @property
    def underline(self) -> bool:
        """
        Whether the text is underlined or not
        """
        return self.__font.get_underline()

    @underline.setter
    def underline(self, value: bool):
        self.__font.set_underline(value)

    @property
    def italic(self) -> bool:
        """
        Whether the text is italic or not
        """
        return self.__font.get_italic()
    
    @italic.setter
    def italic(self, value: bool):
        return self.__font.set_italic(value)

    @property
    def bold(self) -> bool:
        """
        Whether the text is bold or not
        """
        return self.__font.get_bold()

    @bold.setter
    def bold(self, value: bool):
        return self.__font.set_bold(value)

    @property
    def height(self) -> int:
        """
        Returns font height as int
        """
        return self.__font.get_height()

    def get_text_size(self, text: str) -> Tuple[int, int]:
        """Calculates the the text's width and height

        Args:
            text (str): the text whcih is used for the calculation

        Returns:
            Tuple[int, int]: the width and height of the TEXT
        """
        return self.__font.size(text)

    def get_metrics(self, text: str) -> List[Tuple[int, int, int, int]]:
        """Returns the metrics of the TEXT

        Args:
            text (str): the text which metrics you want to know

        Returns:
            list[tuple[int, int, int, int]]: look at https://www.pygame.org/docs/ref/font.html#pygame.font.Font.metrics
        """
        return self.__font.get_metrics(text)

    @classmethod
    def get_available_fonts(cls) -> Set[str]:
        """Returns all available fonts

        Returns the constant 'AVAILABLE_SYSTEM_FONTS' from constants.

        Returns:
            [set[str]]: a set of all available system fonts
        """
        return AVAILABLE_SYSTEM_FONTS

    
from typing import List, Optional, Set, Tuple
import pygame

from .constants import *
font = pygame.font



class Font(object):

    """
    The font class used to manage pygame's font class easier and to set
    the text's style
    """
    
    __slots__ = ("family", "size", "smooth_char", "__font")

    def __init__(self, family: str = None, px: int = None, smooth_char: bool = True, **styles):
        """The constructor of the Font

        Args:
            family (str, optional): the font family. Can be a `*.ttf`-file(path) or a *downloaded* font name. If None (default) the default system font will be used.
            px (str, optional): the size of the font. If None (default) the constant from pygameGUI.constants.DEFAULT_FONT_SIZE will be used.

        Raises:
            ValueError: If the font family is not known and it isn't a "*.ttf" file
        """
        if family is None:
            self.family = font.get_default_font()
        else:
            if family not in AVAILABLE_SYSTEM_FONTS and family[:-4] == ".ttf":
                print(family not in AVAILABLE_SYSTEM_FONTS)
                raise ValueError("Font-family cannot be used.")

            self.family = family
        
        if px is None:
            self.size = DEFAULT_FONT_SIZE
        else:
            self.size = px

        self.smooth_char = smooth_char

        # intern font object
        if self.family[:-4] == ".ttf":
            self.__font: pygame.font.Font = pygame.font.Font(family, px)
        else:
            self.__font: pygame.font.SysFont = pygame.font.SysFont(family, self.size)

    def get_pygame_font(self) -> pygame.font.Font:
        """
        Returns the pygame font instance

        Returns:
            pygame.font.Font: the pygame.font.Font instance
        """
        return self.__font

    @property
    def underline(self) -> bool:
        """
        Whether the text is underlined or not
        """
        return self.__font.get_underline()

    @underline.setter
    def underline(self, value: bool):
        self.__font.set_underline(value)

    @property
    def italic(self) -> bool:
        """
        Whether the text is italic or not
        """
        return self.__font.get_italic()
    
    @italic.setter
    def italic(self, value: bool):
        return self.__font.set_italic(value)

    @property
    def bold(self) -> bool:
        """
        Whether the text is bold or not
        """
        return self.__font.get_bold()

    @bold.setter
    def bold(self, value: bool):
        return self.__font.set_bold(value)

    @property
    def height(self) -> int:
        """
        Returns font height as int
        """
        return self.__font.get_height()

    def get_text_size(self, text: str) -> Tuple[int, int]:
        """Calculates the the text's width and height

        Args:
            text (str): the text whcih is used for the calculation

        Returns:
            Tuple[int, int]: the width and height of the TEXT
        """
        return self.__font.size(text)

    def get_metrics(self, text: str) -> List[Tuple[int, int, int, int]]:
        """Returns the metrics of the TEXT

        Args:
            text (str): the text which metrics you want to know

        Returns:
            list[tuple[int, int, int, int]]: look at https://www.pygame.org/docs/ref/font.html#pygame.font.Font.metrics
        """
        return self.__font.get_metrics(text)

    @classmethod
    def get_available_fonts(cls) -> Set[str]:
        """Returns all available fonts

        Returns the constant 'AVAILABLE_SYSTEM_FONTS' from constants.

        Returns:
            [set[str]]: a set of all available system fonts
        """
        return AVAILABLE_SYSTEM_FONTS

    
The font class used to manage pygame's font class easier and to set     the text's style The constructor of the Font          Args:             family (str, optional): the font family. Can be a `*.ttf`-file(path) or a *downloaded* font name. If None (default) the default system font will be used.             px (str, optional): the size of the font. If None (default) the constant from pygameGUI.constants.DEFAULT_FONT_SIZE will be used.          Raises:             ValueError: If the font family is not known and it isn't a "*.ttf" file # intern font object Returns the pygame font instance          Returns:             pygame.font.Font: the pygame.font.Font instance Whether the text is underlined or not Whether the text is italic or not Whether the text is bold or not Returns font height as int Calculates the the text's width and height          Args:             text (str): the text whcih is used for the calculation          Returns:             Tuple[int, int]: the width and height of the TEXT Returns the metrics of the TEXT          Args:             text (str): the text which metrics you want to know          Returns:             list[tuple[int, int, int, int]]: look at https://www.pygame.org/docs/ref/font.html#pygame.font.Font.metrics Returns all available fonts          Returns the constant 'AVAILABLE_SYSTEM_FONTS' from constants.          Returns:             [set[str]]: a set of all available system fonts