
from client import Player
from reference import convert_reference, convert_url
from time import sleep
from blessed import Terminal


class UI:

    __player: Player
    __verse: str
    __in_game: bool
    __game_over: bool
    __term: Terminal
    __buffer: str

    def __init__(self, playername: str, host: str='localhost', port: int=7788):
        self.__player = Player(playername, self)
        self.__player.join_game(host, port)
        self.__verse = ""
        self.__in_game = False
        self.__game_over = False
        self.__term = Terminal()
        self.__buffer = ""

    def get_line(self):
        with self.__term.cbreak():
            val = self.__term.inkey(timeout=0)
            if not val:
                return None
            if val.is_sequence:
                if val.name == 'KEY_ENTER':
                    line = self.__buffer
                    self.__buffer = ""
                    print()
                    return line
                elif val.name == 'KEY_BACKSPACE':
                    self.__buffer = self.__buffer[:-1]
                    print(f'\r{self.__term.clear_eol}{self.__buffer}', end='', flush=True)
            else:
                self.__buffer += val
                print(val, end='', flush=True)
        return None

    def __reset(self):
        self.__buffer = ""
        print()

    def loop(self):
        while not self.__game_over:
            self.__player.update()
            if text := self.get_line():
                if self.__in_game: self.__guess_ref(text)
                elif text == 'Start Game': self.__start_game()
            sleep(0.1)

    def __guess_ref(self, text: str):
        try:
            url, possible = convert_reference(text)
        except Exception:
            print(
                "An Unknown Error Occurred.\n"
                "Please Check Your Reference and Try Again."
            )
        else:
            if url:
                try: ref = convert_url(url)
                except Exception: ref = url.upper().replace('/','.').strip('.')
                print(f"Your input was interpreted as: {ref}")
                self.__player.guess_reference(url)
                return
            elif possible:
                print(
                    "Sorry, that reference could not be found.\n"
                    "Did you mean one of these:"
                )
                for i in possible:
                    print(i)
            else:
                print(
                    "Sorry, that reference could not be found.\n"
                    "Please Check Your Reference and Try Again."
                )
        print(self.__verse)

    def __start_game(self, difficulty: int = 1):
        self.__player.start_game()
        self.__player.new_round(difficulty)

    def player_joined(self, name: str):
        if name == self.__player.name: print(f"* {name} Joined the Game *")
        else: print(f"{name} Joined the Game")

    def new_verse(self, text: str):
        self.__reset()
        self.__in_game = True
        self.__verse = text
        print(self.__verse)

    def guess_incorrect(self):
        print("That guess was incorrect.")
        print(self.__verse)

    def guess_partial_correct(self, url):
        try: ref = convert_url(url)
        except Exception: ref = url.upper().replace('/','.').strip('.')
        print(f"That guess was partially correct: {ref}")
        print(self.__verse)

    def guess_correct(self):
        print("That guess was correct!")

    def verse_guessed(self, points: int, url: str, player: str):
        try: ref = convert_url(url)
        except Exception: ref = url.upper().replace('/','.').strip('.')
        print(
            f"\nThe verse has been guessed by {player}.\n"
            f"The reference is {ref}.\n"
            f"You have been awarded {points} points for your guess."
        )

    def game_over(self, players: list[str], scores: list[int]):
        self.__game_over = True
        print("\n--- THANKS FOR PLAYING! ---")
        for player, score in zip(players, scores):
            if player == self.__player.name:
                print(f"  * {player}: {score} *")
            else:
                print(f"    {player}: {score}")
