import graphene
from api.graphene_wagtail import GenericStreamFieldType
from api.utils import get_object
from graphene import relay
from graphene_django import DjangoObjectType
from notes.models import InstrumentBookmark

from .models import BasicKnowledge, InstrumentCategory, InstrumentType


class InstrumentCategoryNode(DjangoObjectType):
    types = graphene.List("basicknowledge.queries.InstrumentTypeNode")

    class Meta:
        model = InstrumentCategory
        interfaces = (relay.Node,)
        only_fields = ["name", "foreground", "background", "id"]

    @staticmethod
    def resolve_types(root: InstrumentCategory, info, **kwargs):
        return (
            root.instrument_types.filter(instruments__isnull=False)
            .order_by("name")
            .distinct()
        )


class InstrumentTypeNode(DjangoObjectType):
    type = graphene.String(required=True)
    category = graphene.Field(InstrumentCategoryNode)

    class Meta:
        model = InstrumentType
        interfaces = (relay.Node,)
        only_fields = ["name", "category", "type", "id"]

    @staticmethod
    def resolve_type(root: InstrumentType, info, **kwargs):
        return root.type


class InstrumentNode(DjangoObjectType):
    bookmarks = graphene.List("notes.schema.InstrumentBookmarkNode")
    type = graphene.Field(InstrumentTypeNode)
    contents = GenericStreamFieldType()
    language = graphene.String()
    highlights = graphene.List(
        graphene.NonNull("notes.schema.HighlightNode"), required=True
    )
    path = graphene.String(required=True)

    class Meta:
        model = BasicKnowledge
        filter_fields = ["slug"]
        interfaces = (relay.Node,)
        only_fields = [
            "slug",
            "title",
            "intro",
            "contents",
        ]

    @staticmethod
    def resolve_type(root: BasicKnowledge, info, **kwargs):
        return root.new_type

    def resolve_bookmarks(self, info, **kwargs):
        return InstrumentBookmark.objects.filter(
            user=info.context.user, instrument=self
        )

    def resolve_language(self, info, **kwargs):
        return self.locale.language_code

    @staticmethod
    def resolve_highlights(root: BasicKnowledge, info, **kwargs):
        return root.highlights.filter(user=info.context.user)

    @staticmethod
    def resolve_path(root: BasicKnowledge, info, **kwargs):
        return root.route


class InstrumentQuery(object):
    instrument = graphene.Field(
        InstrumentNode, slug=graphene.String(), id=graphene.ID()
    )
    instruments = graphene.List(InstrumentNode)
    instrument_types = graphene.List(InstrumentTypeNode)
    instrument_categories = graphene.List(InstrumentCategoryNode)

    def resolve_instrument(self, info, **kwargs):
        slug = kwargs.get("slug")
        instrument_id = kwargs.get("id")

        if instrument_id is not None:
            return get_object(BasicKnowledge, instrument_id)
        if slug is not None:
            return BasicKnowledge.objects.get(slug=slug)
        return None

    def resolve_instruments(self, info, **kwargs):
        return BasicKnowledge.objects.all().order_by("title").live()

    def resolve_instrument_types(self, info, **kwargs):
        return (
            InstrumentType.objects.filter(instruments__isnull=False)
            .order_by("name")
            .distinct()
        )

    def resolve_instrument_categories(self, info, **kwargs):
        return InstrumentCategory.objects.all().order_by("name")
