import coopgame.pygamehelpers as help
from typing import Iterable, Tuple
import pygame_widgets
from pygame_widgets.slider import Slider
from pygame_widgets.textbox import TextBox
from dataclasses import dataclass, field
import pygame
import logging
from cooptools.colors import Color
import cooptools.typeProviders as tp

logger = logging.getLogger(__name__)

@dataclass(slots=True)
class TheSlider:
    surf: pygame.Surface
    dims: Tuple[int, int]
    pos: Tuple[int, int]
    font_size: int = field(default=10)
    bounds: Tuple[int, int] = field(init=False, default=None)
    label: str = field(default=None)
    slider: Slider = field(init=False, default=None)
    txt: TextBox = field(init=False, default=None)
    lbl: TextBox = field(init=False, default=None)
    __cache_bounds: Tuple[int, int] = field(init=False, default=None)
    __label_slider_y_off: int = field(default=30)

    def __post_init__(self):
        self.lbl = TextBox(self.surf, self.pos[0] + 10, self.pos[1], 50, 20, fontSize=self.font_size)
        self.txt = TextBox(self.surf, self.pos[0] + 10, self.pos[1] + self.__label_slider_y_off, 20, 20, fontSize=self.font_size)

        self.txt.disable()
        self.lbl.disable()

    def __resolve_bounds(self):
        if self.bounds is None:
            raise Exception(f"Bounds have not been set. Call the set_bounds method after init")

        return (tp.resolve(self.bounds[0]), tp.resolve(self.bounds[1]))

    def __build_slider(self):
        txt_strt = self.txt.getX() + self.txt.getWidth()
        txt_strt_w_buffer = txt_strt + 10

        kwargs = {
            "win": self.surf,
            "x": txt_strt_w_buffer,
            "y": self.pos[1] + self.__label_slider_y_off,
            "width": self.dims[0] - txt_strt_w_buffer - 10,
            "height": self.dims[1],
            "min": self.__cache_bounds[0],
            "max": self.__cache_bounds[1],
            "step": 1,
        }

        if self.slider is not None:
            kwargs["initial"] = self.Value

        return Slider(**kwargs)

    def update(self):

        if ((cur_bnds:= self.__resolve_bounds()) != self.__cache_bounds) or self.__cache_bounds is None:
            self.__cache_bounds = cur_bnds
            self.slider = self.__build_slider()

        self.surf.fill((255, 255, 255))
        self.txt.setText(str(self.slider.getValue()))
        self.lbl.setText(str(self.label) if self.label is not None else "")

    def set_bounds(self, bounds: Tuple[tp.IntProvider, tp.IntProvider]):
        self.bounds = bounds

    @property
    def Value(self) -> int:
        return int(self.slider.getValue())