from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from . import github
import json
import os
import requests
import six.moves.configparser
import urllib.request, urllib.error, urllib.parse

class IssueHandler(object):
    '''
    This plugin facilitates sending issues to github, when
    an item is prefixed with '@issue' or '@bug'

    It will also write items to the issues stream, as well
    as reporting it to github
    '''

    URL = 'https://api.github.com/repos/{}/{}/issues'
    CHARACTER_LIMIT = 70
    CONFIG_FILE = '~/.github-issue-bot/github-issue-bot.conf'
    REPO_NAME = ''
    REPO_OWNER = ''

    def __init__(self):
        # gets token from config file
        # Token at CONFIG_FILE address
        config = six.moves.configparser.ConfigParser()
        config.read([os.path.expanduser(self.CONFIG_FILE)])

        self.REPO_NAME = config.get('github', 'github_repo')
        self.REPO_OWNER = config.get('github', 'github_repo_owner')

    def usage(self):
        return '''
            This plugin will allow users to flag messages
            as being issues with Zulip by using te prefix '@issue'

            Before running this, make sure to create a stream
            called "issues" that your API user can send to.

            Also, make sure that the credentials of the github bot have
            been typed in correctly, that there is a personal access token
            with access to public repositories ONLY,
            and that the repository name is entered correctly.

            Check ~/.github-issue-bot/github-issue-bot.conf, and make sure there are
            github_repo   (The name of the repo to post to)
            github_repo_owner   (The owner of the repo to post to)
            github_username   (The username of the github bot)
            github_token    (The personal access token for the github bot)
            '''

    def triage_message(self, message, client):
        # return True if we want to (possibly) respond to this message
        original_content = message['content']
        # This next line of code is defensive, as we
        # never want to get into an infinite loop of posting follow
        # ups for own follow ups!
        if message['display_recipient'] == 'issue':
            return False
        is_issue = original_content.startswith('@issue')
        return is_issue

    def handle_message(self, message, client, state_handler):

        original_content = message['content']
        original_sender = message['sender_email']

        new_content = original_content.replace('@issue', 'by {}:'.format(original_sender,))
        # gets the repo url
        url_new = self.URL.format(self.REPO_OWNER, self.REPO_NAME)

        # signs into github using the provided username and password
        session = github.auth()

        # Gets rid of the @issue in the issue title
        issue_title = message['content'].replace('@issue', '').strip()
        issue_content = ''
        new_issue_title = ''
        for part_of_title in issue_title.split():
            if len(new_issue_title) < self.CHARACTER_LIMIT:
                new_issue_title += '{} '.format(part_of_title)
            else:
                issue_content += '{} '.format(part_of_title)

        new_issue_title = new_issue_title.strip()
        issue_content = issue_content.strip()
        new_issue_title += '...'

        # Creates the issue json, that is transmitted to the github api servers
        issue = {
                 'title': new_issue_title,
                 'body': '{} **Sent by [{}](https://chat.zulip.org/#) from zulip**'.format(issue_content, original_sender),
                 'assignee': '',
                 'milestone': 'none',
                 'labels': [''],
                }
        # Sends the HTTP post request
        r = session.post(url_new, json.dumps(issue))

        if r.ok:
            # sends the message onto the 'issues' stream so it can be seen by zulip users
            client.send_message(dict(
                type='stream',
                to='issues',
                subject=message['sender_email'],
                # Adds a check mark so that the user can verify if it has been sent
                content='{} :heavy_check_mark:'.format(new_content),
            ))
            return
            # This means that the issue has not been sent
            # sends the message onto the 'issues' stream so it can be seen by zulip users
            client.send_message(dict(
                type='stream',
                to='issues',
                subject=message['sender_email'],
                # Adds a cross so that the user can see that it has failed, and provides a link to a
                # google search that can (hopefully) direct them to the error
                content='{} :x: Code: [{}](https://www.google.com/search?q=Github HTTP {} Error {})'
                        .format(new_content, r.status_code, r.status_code, r.content),
            ))

handler_class = IssueHandler