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, 'pepper.logger.getChild', 'logger.getChild', (['self.__class__.__name__'], {}), False, 'from pepper import logger\n'), (45, 'pepper.language.generation.reply.reply_to_question', 'reply_to_question', (['brain_response_question'], {}), False, 'from pepper.language.generation.reply import reply_to_question\n'), (49, 'pepper.language.generation.thoughts_phrasing.phrase_thoughts', 'phrase_thoughts', (['brain_response_statement', '(True)', '(True)', '(True)'], {}), False, 'from pepper.language.generation.thoughts_phrasing import phrase_thoughts\n'), (55, 're.sub', 're.sub', (['"""[\\\\s+_]"""', '""" """', 'reply'], {}), False, 'import re\n'), (59, 'random.choice', 'choice', (['sentences.PARSED_KNOWLEDGE'], {}), False, 'from random import choice\n'), (62, 'random.choice', 'choice', (['sentences.SORRY'], {}), False, 'from random import choice\n'), (63, 'random.choice', 'choice', (['sentences.NO_ANSWER'], {}), False, 'from random import choice\n'), (58, 'random.choice', 'choice', (['sentences.THANK'], {}), False, 'from random import choice\n'), (58, 'random.choice', 'choice', (['sentences.HAPPY'], {}), False, 'from random import choice\n')]