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

from entity_read.sql.atoms.node import Node
from entity_read.sql.context import SqlContext
from .abstract import Selectable
from .column import Column


@dataclass(kw_only=True, frozen=True, slots=True)
class Function(Selectable, abc.ABC):
    args: tuple[Selectable, ...]
    code: ClassVar[str]
    keep_subquery: ClassVar[bool] = False

    def requires(self) -> list[Column]:
        return list(itertools.chain(*[arg.requires() for arg in self.args if isinstance(arg, Node)]))
    
    def get_name(self) -> str:
        return f'{self.code}({",".join([arg.get_name() for arg in self.args])})'

    def to_sql(self, context: SqlContext, key_to_expression: dict = None) -> str:
        return "(" + self._to_sql([arg.to_sql(context, key_to_expression) for arg in self.args]) + ")"

    @abc.abstractmethod
    def _to_sql(self, args_sql: list[str]) -> str:
        ...
