from pepper.framework import *
from pepper import logger

from pepper.language import Utterance
from pepper.language.generation.thoughts_phrasing import phrase_thoughts
from pepper.language.generation.reply import reply_to_question

from .responder import Responder, ResponderType
from pepper.language import UtteranceType

from pepper.knowledge import sentences, animations
from random import choice

import re

from typing import Optional, Union, Tuple, Callable


class BrainResponder(Responder):
    def __init__(self):
        self._log = logger.getChild(self.__class__.__name__)

    @property
    def type(self):
        return ResponderType.Brain

    @property
    def requirements(self):
        return [TextToSpeechComponent, BrainComponent]

    def respond(self, utterance, app):
        # type: (Utterance, Union[TextToSpeechComponent, BrainComponent]) -> Optional[Tuple[float, Callable]]

        try:
            utterance.analyze()

            self._log.debug("TRIPLE: {}".format(utterance.triple))

            if utterance.triple is not None:
                brain_response_statement = []
                brain_response_question = []

                if utterance.type == UtteranceType.QUESTION:
                    brain_response_question = app.brain.query_brain(utterance)
                    reply = reply_to_question(brain_response_question)
                    self._log.info("REPLY to question: {}".format(reply))
                else:
                    brain_response_statement = app.brain.update(utterance, reason_types=True)  # Searches for types in dbpedia
                    reply = phrase_thoughts(brain_response_statement, True, True, True)
                    self._log.info("REPLY to statement: {}".format(reply))

                if (isinstance(reply, str) or isinstance(reply, unicode)) and reply != "":
                    # Return Score and Response
                    # Make sure to not execute the response here, but just to return the response function
                    return 1.0, lambda: app.say(re.sub(r"[\s+_]", " ", reply))
                elif brain_response_statement:
                    # Thank Human for the Data!
                    return 1.0, lambda: app.say("{} {}".format(choice([choice(sentences.THANK), choice(sentences.HAPPY)]),
                                                               choice(sentences.PARSED_KNOWLEDGE)), animations.HAPPY)
                elif brain_response_question:
                    # Apologize to human for not knowing
                    return 1.0, lambda: app.say("{} {}".format(choice(sentences.SORRY),
                                                               choice(sentences.NO_ANSWER)), animations.ASHAMED)

        except Exception as e:
            self._log.error(e)

[((21, 20, 21, 60), 'pepper.logger.getChild', 'logger.getChild', ({(21, 36, 21, 59): 'self.__class__.__name__'}, {}), '(self.__class__.__name__)', False, 'from pepper import logger\n'), ((45, 28, 45, 70), 'pepper.language.generation.reply.reply_to_question', 'reply_to_question', ({(45, 46, 45, 69): 'brain_response_question'}, {}), '(brain_response_question)', False, 'from pepper.language.generation.reply import reply_to_question\n'), ((49, 28, 49, 87), 'pepper.language.generation.thoughts_phrasing.phrase_thoughts', 'phrase_thoughts', ({(49, 44, 49, 68): 'brain_response_statement', (49, 70, 49, 74): 'True', (49, 76, 49, 80): 'True', (49, 82, 49, 86): 'True'}, {}), '(brain_response_statement, True, True, True)', False, 'from pepper.language.generation.thoughts_phrasing import phrase_thoughts\n'), ((55, 48, 55, 77), 're.sub', 're.sub', ({(55, 55, 55, 64): '"""[\\\\s+_]"""', (55, 66, 55, 69): '""" """', (55, 71, 55, 76): 'reply'}, {}), "('[\\\\s+_]', ' ', reply)", False, 'import re\n'), ((59, 63, 59, 97), 'random.choice', 'choice', ({(59, 70, 59, 96): 'sentences.PARSED_KNOWLEDGE'}, {}), '(sentences.PARSED_KNOWLEDGE)', False, 'from random import choice\n'), ((62, 63, 62, 86), 'random.choice', 'choice', ({(62, 70, 62, 85): 'sentences.SORRY'}, {}), '(sentences.SORRY)', False, 'from random import choice\n'), ((63, 63, 63, 90), 'random.choice', 'choice', ({(63, 70, 63, 89): 'sentences.NO_ANSWER'}, {}), '(sentences.NO_ANSWER)', False, 'from random import choice\n'), ((58, 71, 58, 94), 'random.choice', 'choice', ({(58, 78, 58, 93): 'sentences.THANK'}, {}), '(sentences.THANK)', False, 'from random import choice\n'), ((58, 96, 58, 119), 'random.choice', 'choice', ({(58, 103, 58, 118): 'sentences.HAPPY'}, {}), '(sentences.HAPPY)', False, 'from random import choice\n')]