import enum
import typing as ta

from ... import check
from ... import dataclasses as dc
from ... import lang


##


class QueryMode(enum.Enum):
    QUERY = enum.auto()
    EXEC = enum.auto()

    @classmethod
    def of(
            cls,
            o: ta.Union[str, 'QueryMode', None],
            default: ta.Optional['QueryMode'] = None,
    ) -> 'QueryMode':
        if o is None:
            return check.not_none(check.isinstance(default, cls))
        elif isinstance(o, str):
            return cls[o.upper()]  # noqa
        elif isinstance(o, cls):
            return o
        else:
            raise TypeError(o)


##


class Queryable(lang.Sealed, lang.Abstract):
    pass


@ta.final
@dc.dataclass(frozen=True)
class Query(Queryable, lang.Final):
    mode: QueryMode
    text: str
    args: ta.Sequence[ta.Any]
