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

from dynamic_types.create import create_type

from entity_read.entity import Entity


class AbstractView(abc.ABC, Entity):
    entity_type: type[Entity] = None

    def __class_getitem__(cls, subject: Any) -> type:
        return cls.__cached_produce_view(subject)

    @classmethod
    @functools.cache
    def __cached_produce_view(cls, subject: Any) -> type:
        print(f'{cls}._produce_view({subject})')
        result = cls._produce_view(subject)
        print(f'{cls}._produce_view({subject}) -> {result}')
        return result

    @classmethod
    @abc.abstractmethod
    def _produce_view(cls, subject: Any) -> type:
        pass

    @classmethod
    def _produce_child_dataclass(cls, class_name: str, field_name_to_field: dict[str, Field]) -> type['AbstractView']:
        # TODO: use create_dataclass here, cons: requires signature expand
        new_type: type = create_type(class_name, [cls], field_name_to_field)
        field_name_to_type = {n: f.type for n, f in field_name_to_field.items() if isinstance(f, Field)}
        new_type.__annotations__ = field_name_to_type
        # noinspection PyTypeChecker
        new_dataclass = dataclass(new_type)
        return new_dataclass
