#  Copyright (C) 2023
#  ABM, Moscow
#
#  UNPUBLISHED PROPRIETARY MATERIAL.
#  ALL RIGHTS RESERVED.
#
#  Authors: Mike Orlov <m.orlov@abm-jsc.ru>
from dataclasses import dataclass

from entity_read import sql
from entity_read.entity import Entity
from entity_read.sql.atoms import Selectable
from .expression import Expression


@dataclass(frozen=True, kw_only=True, repr=False)
class Literal(Expression):
    body: dict[str, Expression] | list['Literal | str | float | int | bool | None'] | str | float | int | bool | None

    def eval(self, entity_type: type[Entity], variables: dict[str, Selectable]) -> sql.atoms.literal.Literal:
        body = self.body
        if body is None:
            type_ = None
        elif isinstance(body, bool):
            type_ = bool
        elif isinstance(body, int):
            type_ = int
        elif isinstance(body, float):
            type_ = float
        elif isinstance(body, str):
            type_ = str
        elif isinstance(body, list):
            type_ = list
            body = [v.eval(entity_type, variables).value if isinstance(v, Literal) else v for v in body]
        else:
            raise TypeError(f"Unsupported literal type: {type(body)}")
        return sql.atoms.literal.Literal(type_=type_, value=body)

    def shortcut(self) -> str:
        return self._shortcut(self.body)

    @classmethod
    def _shortcut(cls, body) -> str:
        if body is None:
            return 'null'
        elif isinstance(body, bool):
            return str(body).upper()
        elif isinstance(body, int | float):
            return str(body)
        elif isinstance(body, str):
            return f"'{body}'"
        elif isinstance(body, list):
            return f"[{','.join([cls._shortcut(val) for val in body])}]"
        else:
            raise TypeError(f"Unsupported literal type: {type(body)}")
