import collections
from ..error import Error
from ..language import ast


def is_input_type(type):
    named_type = get_named_type(type)
    return isinstance(named_type, (
        GraphQLScalarType,
        GraphQLEnumType,
        GraphQLInputObjectType,
    ))


def is_composite_type(type):
    named_type = get_named_type(type)
    return isinstance(named_type, (
        GraphQLObjectType,
        GraphQLInterfaceType,
        GraphQLUnionType,
    ))


def is_leaf_type(type):
    named_type = get_named_type(type)
    return isinstance(named_type, (
        GraphQLScalarType,
        GraphQLEnumType,
    ))


def get_named_type(type):
    unmodified_type = type
    while isinstance(unmodified_type, (GraphQLList, GraphQLNonNull)):
        unmodified_type = unmodified_type.of_type
    return unmodified_type


def get_nullable_type(type):
    if isinstance(type, GraphQLNonNull):
        return type.of_type
    return type


class GraphQLType(object):
    def __str__(self):
        return self.name

    def is_same_type(self, other):
        return self.__class__ is other.__class__ and self.name == other.name


class GraphQLScalarType(GraphQLType):
    """Scalar Type Definition

    The leaf values of any request and input values to arguments are