from __future__ import unicode_literals
import logging
from .storage import StorageAdapter
from .input import InputAdapter
from .output import OutputAdapter
from . import utils


class ChatBot(object):
    """
    A conversational dialog chat bot.
    """

    def __init__(self, name, **kwargs):
        from .logic import MultiLogicAdapter

        self.name = name
        kwargs['name'] = name
        kwargs['chatbot'] = self

        self.default_session = None

        storage_adapter = kwargs.get('storage_adapter', 'chatterbot.storage.SQLStorageAdapter')

        # These are logic adapters that are required for normal operation
        system_logic_adapters = kwargs.get('system_logic_adapters', (
            'chatterbot.logic.NoKnowledgeAdapter',
        ))

        logic_adapters = kwargs.get('logic_adapters', [
            'chatterbot.logic.BestMatch'
        ])

        input_adapter = kwargs.get('input_adapter', 'chatterbot.input.VariableInputTypeAdapter')

        output_adapter = kwargs.get('output_adapter', 'chatterbot.output.OutputAdapter')

        # Check that each adapter is a valid subclass of it's respective parent
        utils.validate_adapter_class(storage_adapter, StorageAdapter)
        utils.validate_adapter_class(input_adapter, InputAdapter)
        utils.validate_adapter_class(output_adapter, OutputAdapter)

        self.logic = MultiLogicAdapter(**kwargs)
        self.storage = utils.initialize_class(storage_adapter, **kwargs)
        self.input = utils.initialize_class(input_adapter, **kwargs)
        self.output = utils.initialize_class(output_adapter, **kwargs)

        filters = kwargs.get('filters', tuple())
        self.filters = tuple([utils.import_module(F)() for F in filters])

        # Add required system logic adapter
        for system_logic_adapter in system_logic_adapters:
            self.logic.system_adapters.append(
                utils.initialize_class(system_logic_adapter, **kwargs)
            )

        for adapter in logic_adapters:
            self.logic.add_adapter(adapter, **kwargs)

        # Add the chatbot instance to each adapter to share information such as
        # the name, the current conversation, or other adapters
        self.logic.set_chatbot(self)
        self.input.set_chatbot(self)
        self.output.set_chatbot(self)

        preprocessors = kwargs.get(
            'preprocessors', [
                'chatterbot.preprocessors.clean_whitespace'
            ]
        )

        self.preprocessors = []

        for preprocessor in preprocessors:
            self.preprocessors.append(utils.import_module(preprocessor))

        # Use specified trainer or fall back to the default
        trainer = kwargs.get('trainer', 'chatterbot.trainers.Trainer')
        TrainerClass = utils.import_module(trainer)
        self.trainer = TrainerClass(self.storage, **kwargs)
        self.training_data = kwargs.get('training_data')

        self.default_conversation_id = None

        self.logger = kwargs.get('logger', logging.getLogger(__name__))

        # Allow the bot to save input it receives so that it can learn
        self.read_only = kwargs.get('read_only', False)

        if kwargs.get('initialize', True):
            self.initialize()

    def initialize(self):
        """
        Do any work that needs to be done before the responses can be returned.
        """
        self.logic.initialize()

    def get_response(self, input_item, conversation_id=None):
        """
        Return the bot's response based on the input.

        :param input_item: An input value.
        :param conversation_id: The id of a conversation.
        :returns: A response to the input.
        :rtype: Statement
        """
        import chatterbot
        import Database_Connections
        import SpellChecker
        if not conversation_id:
            if not self.default_conversation_id:
                self.default_conversation_id = self.storage.create_conversation()
            conversation_id = self.default_conversation_id
        genereic_words = ['ok', 'okay', 'sure', 'yes', 'no', 'ya','yeah', 'hmm', 'Hello', 'Hi', 'bye']
        input_statement = self.input.process_input_statement(input_item)

        # Preprocess the input statement
        for preprocessor in self.preprocessors:
            input_statement = preprocessor(self, input_statement)


        #input_statement = chatterbot.preprocessors.extract_key_words(self, input_statement)
        #print("Value parsed in statement is : " + input_statement.text)


        statement, response = self.generate_response(input_statement, conversation_id)

        temp = ""
        temp2=""
        #temp=Database_Connections.get_data()


        # Learn that the user's input was a valid response to the chat bot's previous output
        previous_statement = self.storage.get_latest_response(conversation_id)


        if not self.read_only:
            self.learn_response(statement, previous_statement)
            self.storage.add_to_conversation(conversation_id, statement, response)

        validity = SpellChecker.verify_valid_words(input_item)

        if ((len(input_statement.text) < 2) and (input_item not in genereic_words)):
            response.text = "Can you please elaborate"
            return self.output.process_response(response, conversation_id)
        elif (validity == False):
            response.text = "Can you please enter valid words"
            return self.output.process_response(response, conversation_id)

        if(response.text == "UQDB02"):
            db_parameter = SpellChecker.extract_Quoted_words(input_item)
            response.text = Database_Connections.get_Account_From_Party(db_parameter)
            if (response.text == "DNF"):
                response.text = """Sorry!!
We could not find the details that you have requested.
Do you want us to raise a case?"""
            else:
                temp = "Please find your account details: Account Name: "
        elif (response.text == "UQDB03"):
            db_parameter = SpellChecker.extract_Quoted_words(input_item)
            response.text = str(Database_Connections.get_PartyID_From_Accountname(db_parameter))
            if ((response.text == "DNF") or (response.text == "None")):
                response.text = """Sorry!!
We could not find the details that you have requested.
Do you want us to raise a case?"""
            else:
                temp = """We have found your Site details.
Account Number: """
                temp2 = " Please wait for 36 hours before it comes up in the list. "
        elif (response.text == "UQDB04"):
            db_parameter = SpellChecker.extract_Quoted_words(input_item)
            #response.text = str(Database_Connections.get_CMF_Info(db_parameter))
            cmf_names_list = str(Database_Connections.get_CMF_Info(db_parameter))
            print(cmf_names_list)
            dnf ="DNF"
            if (dnf in cmf_names_list):
                response.text = """Sorry!!
We could not find the details that you have requested.
Do you want us to raise a case?"""
            else:
                temp = """Please find the list of Sites Associated with the Account\n"""
                temp2 = "Please let us know your site name for further assistance"
                response.text = cmf_names_list
        elif (response.text == "UQEM01"):
            import SendEmailSMTP
            email_message = "The User is facing issue with the Site. The Site is missing in the list"
            email_subject = "Issue with Site of User"
            SendEmailSMTP.send_Email(email_subject,email_message)
            temp = "We have created the ticket based on your request. You will be notified with the ticket number on your registered email id.\n"
            response.text = ""
        elif (response.text == "UQEM02"):
            import SendEmailSMTP
            email_message = "The User is facing issue with the ordering the catalog. The catalog doesnt seem to be active."
            email_subject = "User not able to place order"
            SendEmailSMTP.send_Email(email_subject, email_message)
            temp = "We have created the ticket based on your request. You will be notified with the ticket number on your registered email id.\n"
            response.text = ""
        elif (response.text == "UQEM03"):
            import SendEmailSMTP
            email_message = "The User requested special access to the application. Please reach out to the user for more information"
            email_subject = "User Requires Special Access to Application"
            SendEmailSMTP.send_Email(email_subject, email_message)
            temp = "We have created the ticket based on your request. You will be notified with the ticket number on your registered email id.\n"
            response.text = ""

        response.text = str(temp)+ response.text +str(temp2)
        # Process the response output with the output adapter
        return self.output.process_response(response, conversation_id)

    def generate_response(self, input_statement, conversation_id):
        """
        Return a response based on a given input statement.
        """
        self.storage.generate_base_query(self, conversation_id)

        # Select a response to the input statement
        response = self.logic.process(input_statement)

        return input_statement, response

    def learn_response(self, statement, previous_statement):
        """
        Learn that the statement provided is a valid response.
        """
        from .conversation import Response

        if previous_statement:
            statement.add_response(
                Response(previous_statement.text)
            )
            self.logger.info('Adding "{}" as a response to "{}"'.format(
                statement.text,
                previous_statement.text
            ))

        # Save the statement after selecting a response
        self.storage.update(statement)


    def set_trainer(self, training_class, **kwargs):
        """
        Set the module used to train the chatbot.

        :param training_class: The training class to use for the chat bot.
        :type training_class: `Trainer`

        :param \**kwargs: Any parameters that should be passed to the training class.
        """
        if 'chatbot' not in kwargs:
            kwargs['chatbot'] = self

        self.trainer = training_class(self.storage, **kwargs)

    @property
    def train(self):
        """
        Proxy method to the chat bot's trainer class.
        """
        return self.trainer.train

