from typing import Type, NamedTuple, Tuple, Any

import colander as col
from pyrsistent import pvector
from pyrsistent.typing import PVector

from . import nodes
from ..combinator.combinator import Combinator


SchemaType = col.SchemaType


class TypeExtension(NamedTuple):
    typ: Type
    schema: Tuple[Type[SchemaType], PVector[Any]]

    def __and__(self, other) -> Combinator:
        return Combinator() & self & other

    def __add__(self, other) -> 'TypeExtension':
        return self._replace(
            schema=(self.schema[0], self.schema[1].append(nodes.SchemaNode(other)))
        )


class SubscriptableSchemaTypeM(type):
    """ A metaclass for schemas that allow specifying types
    for which they are defined during type construction composition.

    The *M suffix in the name stands for "Meta" to indicate that
    this class should be used only as a metaclass.
    """
    def __getitem__(cls: Type[SchemaType], item: Type) -> TypeExtension:
        # ``cls`` is a schema type here
        return TypeExtension(
            typ=item,
            schema=(cls, pvector()),
        )

    def __repr__(self) -> str:
        return f'{self.__name__}'

    __str__ = __repr__
