import json

import graphene
from django.conf import settings
from graphene import relay

# class SpellCheckPartNode(graphene.ObjectType):
#     sentence = graphene.String()
#     offset = graphene.Int()
#     length = graphene.Int()
#     affected = graphene.String()
#     corrected = graphene.String()
from api.utils import get_object
from assignments.models import Assignment
from spellcheck.client import TaskbaseClient


def sentence_offset_to_snake_case(result):
    result['sentence_offset'] = result['sentenceOffset']
    return result


class SpellCheckStepNode(graphene.ObjectType):
    # id = graphene.String()
    # part = graphene.Field(SpellCheckPartNode)
    sentence = graphene.String()
    offset = graphene.Int()
    sentence_offset = graphene.Int()
    length = graphene.Int()
    affected = graphene.String()
    corrected = graphene.String()


class SpellCheck(relay.ClientIDMutation):
    class Input:
        text = graphene.String(required=True)
        assignment = graphene.ID(required=True)

    results = graphene.List(SpellCheckStepNode)
    correct = graphene.Boolean()

    @classmethod
    def mutate_and_get_payload(cls, root, info, **kwargs):
        user = info.context.user
        text = kwargs.get('text')
        assignment_id = kwargs.get('assignment')

        assignment = get_object(Assignment, assignment_id)

        client = TaskbaseClient(settings.TASKBASE_USER, settings.TASKBASE_PASSWORD, settings.TASKBASE_BASEURL)

        if assignment.taskbase_id is None or assignment.taskbase_id == '':
            # we need to use another user (with more privileges) here, because why not
            superclient = TaskbaseClient(settings.TASKBASE_SUPERUSER, settings.TASKBASE_SUPERPASSWORD,
                                         settings.TASKBASE_BASEURL)
            superclient.register_assignment(assignment)

        data = json.loads(client.spellcheck(assignment.taskbase_id, text))

        # the property is called sentenceOffset, but graphene expects the property to be called sentence_offset.
        # we convert it manually here. fixme: is there a better way to declare this in the SpellCheckStepNode?
        transformed_results = list(map(lambda x: x['part'], data['steps']))
        return cls(correct=data['correct'] == 'CORRECT', results=[
            sentence_offset_to_snake_case(result) for result in transformed_results
        ])


class SpellCheckMutations:
    spell_check = SpellCheck.Field()
