from prettytable import PrettyTable

from lvglgdb.value import Value, ValueInput
from .lv_utils import resolve_source_name, build_global_field_map


class LVFsDrv(Value):
    """LVGL filesystem driver wrapper"""

    def __init__(self, drv: ValueInput):
        super().__init__(Value.normalize(drv, "lv_fs_drv_t"))

    @property
    def letter(self) -> str:
        return chr(int(self.super_value("letter")))

    # Lazily built address -> name map shared across all instances
    _addr_map = None

    @property
    def driver_name(self) -> str:
        """Infer driver name from lv_global_t field or open_cb source file."""
        if LVFsDrv._addr_map is None:
            m = build_global_field_map("lv_fs_drv_t")
            LVFsDrv._addr_map = {
                addr: name.replace("_fs_drv", "") for addr, name in m.items()
            }
        # Try lv_global_t field match first (no debug info needed)
        name = LVFsDrv._addr_map.get(int(self), None)
        if name:
            return name
        # Fallback: resolve from open_cb source file (needs debug info)
        return resolve_source_name(int(self.open_cb), prefix="lv_fs_") or "unknown"

    @property
    def cache_size(self) -> int:
        return int(self.super_value("cache_size"))

    @property
    def ready_cb(self) -> Value:
        return self.super_value("ready_cb")

    @property
    def open_cb(self) -> Value:
        return self.super_value("open_cb")

    @property
    def close_cb(self) -> Value:
        return self.super_value("close_cb")

    @property
    def read_cb(self) -> Value:
        return self.super_value("read_cb")

    @property
    def write_cb(self) -> Value:
        return self.super_value("write_cb")

    @property
    def seek_cb(self) -> Value:
        return self.super_value("seek_cb")

    @property
    def tell_cb(self) -> Value:
        return self.super_value("tell_cb")

    @property
    def dir_open_cb(self) -> Value:
        return self.super_value("dir_open_cb")

    @property
    def dir_read_cb(self) -> Value:
        return self.super_value("dir_read_cb")

    @property
    def dir_close_cb(self) -> Value:
        return self.super_value("dir_close_cb")

    @property
    def user_data(self) -> Value:
        return self.super_value("user_data")

    @staticmethod
    def _fmt_cb(cb: Value) -> str:
        addr = int(cb)
        if not addr:
            return "-"
        return cb.format_string(symbols=True).replace("\x00", "")

    @staticmethod
    def print_entries(drivers):
        """Print filesystem drivers as a PrettyTable."""
        table = PrettyTable()
        table.field_names = [
            "#",
            "letter",
            "type",
            "cache_size",
            "open_cb",
            "read_cb",
            "write_cb",
            "close_cb",
        ]
        table.align = "l"

        fmt = LVFsDrv._fmt_cb
        for i, drv in enumerate(drivers):
            table.add_row(
                [
                    i,
                    f"{drv.letter}:",
                    drv.driver_name,
                    drv.cache_size,
                    fmt(drv.open_cb),
                    fmt(drv.read_cb),
                    fmt(drv.write_cb),
                    fmt(drv.close_cb),
                ]
            )

        if not table.rows:
            print("No registered filesystem drivers.")
        else:
            print(str(table).replace("\x00", ""))
