#!/usr/bin/env python

r"""
Exports issues from a list of repositories to individual CSV files.
Uses basic authentication (GitHub username + password) to retrieve issues
from a repository that username has access to. Supports GitHub API v3.
"""
import argparse
import csv
import getpass
import requests

auth = None
states = 'all'


def write_issues(response, csv_out):
    r"""
    Parses JSON response and writes to CSV.
    """
    print(response)
    if response.status_code != 200:
        raise Exception(response.status_code)
    for issue in response.json():
        if 'pull_request' not in issue:
            labels = ', '.join([l['name'] for l in issue['labels']])

            # Below lines to overcome "TypeError: 'NoneType' object has
            # no attribute '__getitem__'"

            close_date = issue.get('closed_at')
            if close_date:
                close_date = issue.get('closed_at').split('T')[0]

            assignee_resp = issue.get('assignees', 'Not Assigned')
            if assignee_resp:
                owners = ','.join([assignee_login['login'] for
                                   assignee_login in assignee_resp])
            else:
                owners = "Not Assigned"

            milestone_resp = issue.get('milestone', 'Not Assigned')
            if milestone_resp:
                milestone_resp = milestone_resp['title'].encode('utf-8')

            # Change the following line to write out additional fields
            csv_out.writerow([labels.encode('utf-8'),
                              issue.get('title').encode('utf-8'),
                              issue.get('state').encode('utf-8'),
                              issue.get('created_at').split('T')[0],
                              close_date,
                              issue.get('html_url').encode('utf-8'),
                              issue.get('user').get('login').encode('utf-8'),
                              owners, milestone_resp])


def get_issues_from_github_to_csv(name, response):
    r"""
    Requests issues from GitHub API and writes to CSV file.
    Description of argument(s):
    name  Name of the GitHub repository
    response  GitHub repository response
    """
    print(name)
    print(states)

    # Multiple requests are required if response is paged
    if 'link' in response.headers:
        pages = {rel[6:-1]: url[url.index('<') + 1:-1] for url, rel in
                 (link.split(';') for link in
                  response.headers['link'].split(','))}
        while 'last' in pages and 'next' in pages:
            pages = {rel[6:-1]: url[url.index('<') + 1:-1] for url, rel in
                     (link.split(';') for link in
                      response.headers['link'].split(','))}
            response = requests.get(pages['next'], auth=auth)
            write_issues(response, csv_out)
            if pages['next'] == pages['last']:
                break


parser = argparse.ArgumentParser(description="Write GitHub repository issues "
                                             "to CSV file.")

parser.add_argument('username', nargs='?', help="GitHub user name, "
                    "formatted as 'username'")

parser.add_argument('repositories', nargs='+', help="Repository names, "
                    "formatted as 'basereponame/repo'")

parser.add_argument('--all', action='store_true', help="Returns both open "
                    "and closed issues.")

args = parser.parse_args()

if args.all:
    state = 'all'

username = args.username

password = getpass.getpass("Enter your GitHub Password:")

auth = (username, password)

# To set the csv filename
csvfilename = ""
for repository in args.repositories:
    csvfilename_temp = '{}'.format(repository.replace('/', '-'))
    csvfilename = csvfilename + csvfilename_temp
csvfilename = csvfilename + '-issues.csv'
with open(csvfilename, 'w') as csvfileout:
    csv_out = csv.writer(csvfileout)
    csv_out.writerow(['Labels', 'Title', 'State', 'Open Date',
                      'Close Date', 'URL', 'Author', 'Assignees',
                      'Milestone'])
    for repository in args.repositories:
        l_url = 'https://api.github.com/repos/{}/issues?state={}'
        l_url = l_url.format(repository, states)
        response = requests.get(l_url, auth=auth)
        write_issues(response, csv_out)
        get_issues_from_github_to_csv(repository, response)
csvfileout.close()