from typing import Callable, Optional, Sequence

import sqlalchemy as sa
from sqlalchemy.schema import CreateTable
from sqlalchemy.sql.elements import ColumnClause
from sqlalchemy.sql.visitors import TraversibleType


class ColumnMeta(TraversibleType):
    def __getattr__(cls, name: str):  # noqa: B902
        return cls(name)  # pylint: disable=no-value-for-parameter


class Object:
    """
    Object is used as a placeholder parameter to indicate the actual stored object
    being passed as a parameter to the UDF.
    """

    def __init__(self, reader: Callable):
        """
        Initialize the object and specify the reader to be
        used for loading the object into memory.
        """
        self.reader = reader


class Column(ColumnClause, metaclass=ColumnMeta):  # pylint: disable=abstract-method
    inherit_cache: Optional[bool] = True

    def __init__(self, text: str) -> None:
        self.name = text
        super().__init__(text)

    def glob(self, glob_str):
        return self.op("GLOB")(glob_str)


def create_udf_table(
    execute: Callable, name: str, custom_columns: Sequence["sa.Column"] = ()
) -> "sa.Table":
    """Create a temporary table for storing custom signals generated by a UDF."""
    tbl = sa.Table(
        name,
        sa.MetaData(),
        sa.Column("id", sa.Integer, primary_key=True),
        *custom_columns,
        prefixes=["TEMPORARY"],
    )
    q = CreateTable(
        tbl,
        if_not_exists=True,
    )
    execute(q)
    return tbl


C = Column
