#!/usr/bin/env python
# coding=utf-8

from telegram import ReplyKeyboardRemove, KeyboardButton, ReplyKeyboardMarkup, ParseMode
from telegram.ext import MessageHandler, Filters, Updater, CommandHandler
from emoji import emojize
import logging
import clips

# Enable logging
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                    level=logging.INFO)

logger = logging.getLogger(__name__)


def start(bot, update):
    """
    Sends a welcome message when the command /start is issued.
    """

    clips.Reset()
    clips.Run()

    # Get the initial UI state
    initial_fact = clips.Eval('(find-fact ((?f UI-state)) (eq ?f:state initial))')

    update.message.reply_text(text='Hello {}! 🤖 '.format(update.message.from_user.first_name),
                              reply_markup=ReplyKeyboardRemove())
    update.message.reply_text(initial_fact[0].Slots['display'])


def new(bot, update):
    """
    Starts a new chat with the beer expert when the command /new is issued.
    """

    clips.Reset()
    clips.Run()

    nextUIState(bot, update)


def nextUIState(bot, update):
    """
    Re-creates the dialog window to match the current state in working memory.
    """

    # Get the state-list
    fact_list = clips.Eval('(find-all-facts ((?f state-list)) TRUE)')
    if len(fact_list) == 0:
        return

    current_id = fact_list[0].Slots['current']

    # Get the current UI state
    fact_list = clips.Eval('(find-all-facts ((?f UI-state)) (eq ?f:id %s))' % current_id)
    if len(fact_list) == 0:
        return

    state = fact_list[0].Slots['state']

    if state == 'initial':
        clips.Assert('(next %s)' % current_id)
        clips.Run()
        nextUIState(bot, update)

    elif state == 'final':
        results = fact_list[0].Slots['display']

        keyboard = [[KeyboardButton(text=emojize(":back: Previous", use_aliases=True))],
                    [KeyboardButton(text=emojize(":repeat: Restart", use_aliases=True))],
                    [KeyboardButton(text=emojize(":x: Cancel", use_aliases=True))]]
        reply_markup = ReplyKeyboardMarkup(keyboard)
        update.message.reply_text(text=results,
                                  parse_mode=ParseMode.MARKDOWN,
                                  disable_web_page_preview=True,
                                  reply_markup=reply_markup)

    else:
        question = fact_list[0].Slots['display']
        valid_answers = fact_list[0].Slots['valid-answers']

        keyboard = []
        for answer in valid_answers:
            keyboard.append([KeyboardButton(text=answer)])
        keyboard.append([KeyboardButton(text=emojize(":back: Previous", use_aliases=True))])
        keyboard.append([KeyboardButton(text=emojize(":x: Cancel", use_aliases=True))])
        reply_markup = ReplyKeyboardMarkup(keyboard)
        update.message.reply_text(text=question,
                                  reply_markup=reply_markup)

        dispatcher.add_handler(MessageHandler(Filters.text, handleEvent))


def handleEvent(bot, update):
    """
    Triggers the next state in working memory based on which button
    was pressed and triggers a re-generation of the GUI.
    """

    # Get the state-list
    fact_list = clips.Eval('(find-all-facts ((?f state-list)) TRUE)')
    if len(fact_list) == 0:
        return

    current_id = fact_list[0].Slots['current']

    # Get the current UI state
    fact_list = clips.Eval('(find-all-facts ((?f UI-state)) (eq ?f:id %s))' % current_id)
    if len(fact_list) == 0:
        return

    valid_answers = fact_list[0].Slots['valid-answers']
    relation_asserted = fact_list[0].Slots['relation-asserted']

    if update.message.text in valid_answers:
        clips.Assert('(%s %s)' % (relation_asserted, update.message.text))
        clips.Run()
        nextUIState(bot, update)

    elif update.message.text == emojize(":back: Previous", use_aliases=True):
        clips.Assert('(prev %s)' % current_id)
        clips.Run()
        nextUIState(bot, update)

    elif update.message.text == emojize(":repeat: Restart", use_aliases=True):
        new(bot, update)

    elif update.message.text == emojize(":x: Cancel", use_aliases=True):
        cancel(bot, update)


def cancel(bot, update):
    """
    Ends the chat with the beer expert when the command /cancel is issued.
    """

    update.message.reply_text(text='Bye! I hope we can talk again some day. 👋',
                              reply_markup=ReplyKeyboardRemove())
    clips.Reset()


def unknown(bot, update):
    """
    Sends an error message when an unrecognized command is typed.
    """

    bot.send_message(chat_id=update.message.chat_id,
                     text='Unrecognized command. Say what?')


def error(bot, update, error):
    """
    Log errors caused by updates.
    """

    logger.warning('Update "%s" caused error "%s"', update, error)


if __name__ == '__main__':

    # Load the Beer EXpert system
    clips.Load('./clips/beerex.clp')

    # Create the updater and pass it the bot's token.
    updater = Updater(open('token', 'r').read())

    # Get the dispatcher to register handlers
    dispatcher = updater.dispatcher
    dispatcher.add_handler(CommandHandler('start', start))
    dispatcher.add_handler(CommandHandler('new', new))
    dispatcher.add_handler(CommandHandler('cancel', cancel))
    dispatcher.add_handler(MessageHandler(Filters.command, unknown))

    # Log all errors
    dispatcher.add_error_handler(error)

    # Start the bot
    updater.start_polling()

    # Run the bot until you press Ctrl-C or the process receives SIGINT,
    # SIGTERM or SIGABRT. This should be used most of the time, since
    # start_polling() is non-blocking and will stop the bot gracefully.
    updater.idle()

@@ -1813,16 +1813,48 @@
 splay'%5D%0A
+        clips.SaveFacts(%22facts%22)
 %0A       
@@ -3166,20 +3166,16 @@
 h button
-%0A   
  was pre
@@ -3178,16 +3178,31 @@
  pressed
+.%0A    %22%22%22%0A    #
  and tri
@@ -3234,24 +3234,16 @@
 the GUI.
-%0A    %22%22%22
 %0A%0A    # 
@@ -4464,16 +4464,17 @@
 e day. %F0%9F%91%8B
+%F0%9F%8F%BB
 ',%0A     
@@ -5216,16 +5216,17 @@
 patcher%0A
+%0A
     disp

update BeerEX.bot.py