import asyncio
import logging
from random import randint

from rio import Text, Component, TextStyle, i_know_what_im_doing


class Ticker(Component):
    @i_know_what_im_doing
    def __init__(self, texts: list[str], refresh_interval: float, style: TextStyle, tick_in_order: bool, **kwargs) -> None:
        super().__init__()
        if refresh_interval <= 0:
            raise ValueError("refresh_interval must be greater than zero")
        self.kwargs = kwargs
        self.kwargs.pop("text", None)
        self.kwargs.pop("style", None)

        self.texts = texts
        self.refresh_interval = refresh_interval
        self.style = style
        self._tick_in_order = tick_in_order
        self._last_text = -1
        self._task = asyncio.get_event_loop().create_task(self._set_next_text())

    def stop_ticking(self) -> None:
        self._task.cancel()

    def start_ticking(self) -> None:
        if not self._task.cancelled():
            self._task.cancel()

        self._task = asyncio.get_event_loop().create_task(self._set_next_text())

    def set_new_texts(self, new_texts: list[str]) -> None:
        self.stop_ticking()
        self._last_text = -1
        self.texts = new_texts
        self.start_ticking()

    def add_text(self, text: str) -> None:
        self.texts.append(text)

    def build(self) -> Component:
        try:
            self.kwargs["text"] = self.texts[self._last_text]
            return Text(**self.kwargs, style=self.style)
        except Exception as e:
            logging.error(e)
            logging.error("Ticker stopped due to an exception")
            self.stop_ticking()

    async def _set_next_text(self) -> None:
        while True:
            if self._tick_in_order:
                self._last_text += 1
                if self._last_text >= len(self.texts):
                    self._last_text = 0
            else:
                self._last_text = randint(0, len(self.texts) - 1)
            await self.force_refresh()
            await asyncio.sleep(self.refresh_interval)
