# To use this plugin, you need to set up the Giphy API key for this bot in
# ~/.giphy_config

from __future__ import absolute_import
from __future__ import print_function
from six.moves.configparser import SafeConfigParser
import requests
import logging
import sys
import os
import re

GIPHY_TRANSLATE_API = 'http://api.giphy.com/v1/gifs/translate'

if not os.path.exists(os.environ['HOME'] + '/.giphy_config'):
    print('Giphy bot config file not found, please set up it in ~/.giphy_config'
          '\n\nUsing format:\n\n[giphy-config]\nkey=<giphy API key here>\n\n')
    sys.exit(1)


class GiphyHandler(object):
    '''
    This plugin posts a GIF in response to the keywords provided by the user.
    Images are provided by Giphy, through the public API.
    The bot looks for messages starting with "@giphy" or @mention of the bot
    and responds with a message with the GIF based on provided keywords.
    It also responds to private messages.
    '''
    def usage(self):
        return '''
            This plugin allows users to post GIFs provided by Giphy.
            Users should preface keywords with "@giphy" or the Giphy-bot @mention.
            The bot responds also to private messages.
            '''

    def triage_message(self, message, client):
        # To prevent infinite loop in private message, bot will detect
        # if the sender name is the bot name it will return false.
        if message['type'] == 'private':
            return client.full_name != message['sender_full_name']

        # Return True if we want to (possibly) response to this message.
        original_content = message['content']
        is_giphy_called = (original_content.startswith('@giphy ') or
                           message['is_mentioned'])

        return is_giphy_called

    def handle_message(self, message, client, state_handler):
        bot_response = get_bot_giphy_response(message, client)

        if message['type'] == 'private':
            client.send_message(dict(
                type='private',
                to=message['sender_email'],
                content=bot_response,
            ))
        else:
            client.send_message(dict(
                type='stream',
                to=message['display_recipient'],
                subject=message['subject'],
                content=bot_response,
            ))


class GiphyNoResultException(Exception):
    pass


def get_giphy_api_key_from_config():
    config = SafeConfigParser()
    with open(os.environ['HOME'] + '/.giphy_config', 'r') as config_file:
        config.readfp(config_file)
    return config.get("giphy-config", "key")


def get_url_gif_giphy(keyword, api_key):
    # Return a URL for a Giphy GIF based on keywords given.
    # In case of error, e.g. failure to fetch a GIF URL, it will
    # return a number.
    query = {'s': keyword,
             'api_key': api_key}
    try:
        data = requests.get(GIPHY_TRANSLATE_API, params=query)
    except requests.exceptions.ConnectionError as e:  # Usually triggered by bad connection.
        logging.warning(e)
        raise

    search_status = data.json()['meta']['status']
    if search_status != 200 or not data.ok:
        raise requests.exceptions.ConnectionError

    try:
        gif_url = data.json()['data']['images']['original']['url']
    except (TypeError, KeyError):  # Usually triggered by no result in Giphy.
        raise GiphyNoResultException()

    return gif_url


def get_bot_giphy_response(message, client):
    # Handle the message that called through mention.
    if message['is_mentioned']:
        bot_mention = r'^@(\*\*{0}\*\*\s|{0}\s)(?=.*)'.format(client.full_name)
        start_with_mention = re.compile(bot_mention).match(message['content'])
        if start_with_mention:
            keyword = message['content'][len(start_with_mention.group()):]
        else:
            return 'Please mention me first, then type the keyword.'
    # Handle the message that called through the specified keyword.
    elif message['content'].startswith('@giphy '):
        keyword = message['content'][len('@giphy '):]
    # Handle the private message.
    elif message['type'] == 'private':
        keyword = message['content']

    # Each exception has a specific reply should "gif_url" return a number.
    # The bot will post the appropriate message for the error.
    try:
        gif_url = get_url_gif_giphy(keyword, get_giphy_api_key_from_config())
    except requests.exceptions.ConnectionError:
        return ('Uh oh, sorry :slightly_frowning_face:, I '
                'cannot process your request right now. But, '
                'let\'s try again later! :grin:')
    except GiphyNoResultException:
        return ('Sorry, I don\'t have a GIF for "%s"! '
                ':astonished:' % (keyword))
    return ('[Click to enlarge](%s)'
            '[](/static/images/interactive-bot/giphy/powered-by-giphy.png)'
            % (gif_url))

handler_class = GiphyHandler