from tools.slack_posting import setPresence, sendIM, getIMChannels, postMsg
from tools.classes import SlackMessage, Conversation
from tools.database_tools import isValidUser
from markov import gen_sentence, gen_model
import tools.settings as settings

def getModel():
    global model
    return model

def reboot():
    import os
    import sys
    python = sys.executable
    os.execl(python, python, * sys.argv)

def isMessage(event_string):
    possibleErrors = ["message_", "pin_", "reaction_", "file_", "bot_"]
    return (('"type": "message"' in event_string)
        and (not (any([error in event_string for error in possibleErrors]))))

def plainText(slackMessage):
    import plaintext
    return plaintext.interpret(slackMessage)

def mapAlias(slackMessage):
    with open('data/alias.dict') as f:
        aliasDict = pickle.load(f)

    command = slackMessage.message.split()[0].replace(";", "")

    try:
        newCommand = aliasDict[command]
        return SlackMessage(slackMessage.message.replace(command, newCommand), slackMessage.user, slackMessage.channel)
    except:
        return slackMessage

def control(slackMessage):
    import plugins

    try:
        command = slackMessage.message.split(" ")[0][1:]
        return getattr(plugins, command)(slackMessage)
    except AttributeError:
        return "That is not a valid command!"
    except UnicodeEncodeError:
        return ">unicode"

    # #For debugging
    # command = slackMessage.message.split(" ")[0][1:]
    # return getattr(plugins, command)(slackMessage)

if __name__ == "__main__":
    from slacksocket import SlackSocket

    if True:
        import random
        import pickle

        slackToken = settings.getSlackToken()
        debugChannel = settings.getDebugChannel()

        shenanigansState = settings.getShenanigansSetting()
        mimicState = settings.getMimicSetting()

        debugMode = False
        convoMode = False

        currentConvo = None

        lastCommand = None

        model = gen_model()

        with open('data/alias.dict') as f:
            aliasDict = pickle.load(f)

        imChannels = getIMChannels()

    try:
        s = SlackSocket(slackToken)
    except:
        import sys
        import tools.shenanigans
        if shenanigansState:
            tools.shenanigans.enable()
            tools.shenanigans.reboot()
        else:
            print "That token was invalid!"
            sys.exit(2)

    setPresence('auto')

    s.send_msg("I'm combat ready!", debugChannel)

    for event in s.events():

        eventString = str(event.json)

        if (eventString == '{}'):
            reboot()

        if (debugMode):
            s.send_msg(eventString, debugChannel)
            print(eventString)

        if shenanigansState and('_left' in eventString):
            import json
            import tools.shenanigans
            eventParsed = json.loads(eventString)
            channel = eventParsed['channel'].strip()
            s.send_msg(tools.shenanigans.rejoin(channel), debugChannel)

        if isMessage(eventString):

            try:
                import json
                eventParsed = json.loads(eventString)
                slackMessage = SlackMessage(eventParsed['text'].strip(), eventParsed['user'].strip(), eventParsed['channel'].strip())
                # postMsg(eventString, debugChannel)
            except KeyError:
                import time
                import os, os.path

                timestr = time.strftime("%Y%m%d-%H%M%S")
                s.send_msg("I encountered an error! The time is: " + timestr, debugChannel)
                s.send_msg(eventString, debugChannel)
                errorFilePath = os.path.join(os.getcwd(), "errors", timestr + ".txt")
                with open(errorFilePath, "w") as errorFile:
                    errorFile.write(eventString)
            else:
                if mimicState:
                    from tools.mimic import mimicMessage
                    mimicResponse = mimicMessage(slackMessage)
                    if mimicResponse:
                        s.send_msg(mimicResponse, slackMessage.channel)
                        continue

                if convoMode:
                    result = currentConvo.checkResponse(slackMessage)
                    if result:
                        convoMode, response = False, result
                    else:
                        response = ""

                elif slackMessage.isCommand():
                    if (slackMessage.message == ';'):
                        if (lastCommand):
                            s.send_msg("Repeating the last command: `{}` by user: `{}` in channel: `{}`.".format(lastCommand.message, lastCommand.user, lastCommand.channel), slackMessage.channel)
                            response = control(mapAlias(SlackMessage(lastCommand.message, slackMessage.user, slackMessage.channel)))
                        else:
                            response = "There is no valid last command to repeat!"
                    else:
                        lastCommand = slackMessage
                        response = control(mapAlias(slackMessage))

                elif isValidUser(slackMessage.channel):
                    response = gen_sentence(model)

                else:
                    response = plainText(slackMessage)
                    if response == ".1.2.1.":
                        postMsg("tagged", debugChannel)
                        response = gen_sentence(model)

                if isinstance(response, Conversation):
                    convoMode = True
                    currentConvo = response
                    response = currentConvo.initialResponse

                if response:
                    try:
                        s.send_msg(response, slackMessage.channel)
                    except TypeError:
                        sendIM(response, slackMessage.channel)