from github3 import (login, GitHub)
from github_settings import (username, password, token)
from itertools import islice

#gh = login(username, password=password)
gh = login(token=token)

# set up an anonymous user to see what can be done without authn
anon = GitHub()

#user = gh.user('rdhyee-GITenberg')
user = gh.user()
# <User [sigmavirus24:Ian Cordasco]>

print(user.name)
# Ian Cordasco
print(user.login)
# sigmavirus24
print(user.followers)
# 4

for f in gh.iter_followers():
    print(str(f))

kennethreitz = gh.user('kennethreitz')
# <User [kennethreitz:Kenneth Reitz]>

print(kennethreitz.name)
print(kennethreitz.login)
print(kennethreitz.followers)

# let's grab just a subset of the followers
followers = [str(f) for f in islice(gh.iter_followers('kennethreitz'), 100)]

"""
Explanation: Goals
hello world of github3
End of explanation
"""


# let's use a token instead
# create a gist https://github3py.readthedocs.org/en/master/examples/gist.html#creating-a-gist-after-authenticating

files = {
    'spam.txt' : {
        'content': 'What... is the air-speed velocity of an unladen swallow?'
        }
    }
gist = gh.create_gist('Answer this to cross the bridge', files, public=False)
# gist == <Gist [gist-id]>
print(gist.html_url)


# delete gist?

gist.delete()

"""
Explanation: creating and deleting a gist
End of explanation
"""


# need to login with username, password

gh = login(username, password)

def authorization_description_already_exists(e):
    """
    Given an exception e when trying to create a token, is the exception the result of a duplicate description
    """
    if (e.code == 422 and 
        e.message == u'Validation Failed' and 
        (u'already_exists', u'description') in [(error['code'], error['field']) for error in e.errors]):
        return True
    else:
        return False
    
try:
    token = gh.authorize(username, password, scopes=('public_repo'), note='test token 2016.03.17')
except Exception as e:
    if authorization_description_already_exists(e):
        print ("duplicate key description")
    else:
        raise e


gh.authorization?

for auth in gh.iter_authorizations():
    print (auth.id, auth.name)

"""
Explanation: authorizations
End of explanation
"""


# adapted from 
# https://github.com/sigmavirus24/github3.py/blob/38de787e465bffc63da73d23dc51f50d86dc903d/github3/repos/repo.py#L1781-L1793

from github3.repos.release import Release

def release_from_tag(repo, tag_name):
    """Get a release by tag name.
    release_from_tag() returns a release with specified tag
    while release() returns a release with specified release id
    :param str tag_name: (required) name of tag
    :returns: :class:`Release <github3.repos.release.Release>`
    """
    url = repo._build_url('releases', 'tags', tag_name,
                          base_url=repo._api)
    json = repo._json(repo._get(url), 200)
    return Release(json, repo) if json else None



from itertools import islice

# instantiate repo

(repo_owner, repo_name) = ('GITenberg', 'Adventures-of-Huckleberry-Finn_76')

repo = gh.repository(repo_owner, repo_name)
repo_anon = anon.repository(repo_owner, repo_name)

# can use either authenticated repo, or anonymous access repo_anon
# loop through releases

for (i, release) in enumerate(islice(repo_anon.iter_releases(),3)):
    print (i, release.id, release.tag_name)
    
print "\n"

for (i, release) in enumerate(islice(repo.iter_releases(),3)):
    print (i, release.id, release.tag_name)

release = release_from_tag(repo, '0.0.50')
(release.id, release.tag_name)

for asset in release.iter_assets():
    # pick out some of the attributes of Asset
    # https://github.com/sigmavirus24/github3.py/blob/0.9.3/github3/repos/release.py#L145-L164
    
    print (asset.id, asset.name, asset.content_type, asset.download_url, asset.download_count)

"""
Explanation: releases
Goal: can we read off list of files from a given release
Example:  https://github.com/GITenberg/Adventures-of-Huckleberry-Finn_76/releases/tag/0.0.50
Since we're currently using github3.py/repo.py at 0.9.3, which doesn't have Repository.release_from_tag , we borrow Repository.release_from_tag in v 1.0.0a4
End of explanation
"""


# a function which given a repo and tag, returns which of epub, pdf, mobi are available

from github3 import (login, GitHub)
from github3.repos.release import Release

# a token can generated at https://github.com/settings/tokens -- no private access needed
from github_settings import GITHUB_PUBLIC_TOKEN

# release_from_tag adapted from 
# https://github.com/sigmavirus24/github3.py/blob/38de787e465bffc63da73d23dc51f50d86dc903d/github3/repos/repo.py#L1781-L1793

def release_from_tag(repo, tag_name):
    """Get a release by tag name.
    release_from_tag() returns a release with specified tag
    while release() returns a release with specified release id
    :param str tag_name: (required) name of tag
    :returns: :class:`Release <github3.repos.release.Release>`
    """
    url = repo._build_url('releases', 'tags', tag_name,
                          base_url=repo._api)
    json = repo._json(repo._get(url), 200)
    return Release(json, repo) if json else None


def ebooks_in_github_release(repo_owner, repo_name, tag, token=None):
    """
    returns a list of (book_type, book_name) for a given GitHub release (specified by 
    owner, name, tag).  token is a GitHub authorization token -- useful for accessing
    higher rate limit in the GitHub API
    """
    
    # epub, mobi, pdf, html, text
    # map mimetype to file extension
    EBOOK_FORMATS = {'application/epub+zip':'epub',
                 'application/x-mobipocket-ebook': 'mobi',
                 'application/pdf': 'pdf',
                 'text/plain': 'text',
                 'text/html':'html'}
    
    if token is not None:
        gh = login(token=token)
    else:
        # anonymous access
        gh = GitHub()
        
    repo = gh.repository(repo_owner, repo_name)
    release = release_from_tag(repo, tag)
    
    return [(EBOOK_FORMATS.get(asset.content_type), asset.name) 
            for asset in release.iter_assets() 
            if EBOOK_FORMATS.get(asset.content_type) is not None]
 

# test out ebooks_in_github_release
(repo_owner, repo_name) = ('GITenberg', 'Adventures-of-Huckleberry-Finn_76')
ebooks_in_github_release(repo_owner, repo_name, '0.0.50', token=GITHUB_PUBLIC_TOKEN) 

# https://github.com/GITenberg/Adventures-of-Huckleberry-Finn_76/raw/master/metadata.yaml

from urlparse import urlparse

url = "https://github.com/GITenberg/Adventures-of-Huckleberry-Finn_76/raw/master/metadata.yaml"
url_path = urlparse(url).path.split("/")
(repo_owner, repo_name) = (url_path[1], url_path[2])
(repo_owner, repo_name) 

"""
Explanation: consolidating code for releases
End of explanation
"""


master_branch = repo.branch('master')
master_branch.commit.sha

master_tree = repo.tree(master_branch.commit.sha)
for hash_ in master_tree.tree:
    print (hash_.path, hash_.type)

def asciidoc_in_repo_root(repo, branch ='master'):
    """return list of asciidocs in the root of repo"""
    repo_branch = repo.branch(branch)
    tree = repo.tree(repo_branch.commit.sha)
    return [hash_.path 
            for hash_ in tree.tree
            if hash_.path.endswith('.asciidoc')]


asciidoc_in_repo_root(repo)    

"""
Explanation: looking for .asciidoc files in a given repo
End of explanation
"""


try:
    repo_data = {
    'name': 'TEST REPO',
    'description': 'can I create a repo using github3.py?',
    'homepage': '',
    'private': False,
    'has_issues': True,
    'has_wiki': True
    }

    if repo_data.get('name'):
        r = gh.create_repo(repo_data.pop('name'), **repo_data)

    if r:
        print("Created {0} successfully.".format(r.name))
        
except Exception as e:
    
    print (e)

"""
Explanation: create a repos
GitHub Examples — github3.py 0.9.3 documentation
and code: github3.py/github.py at 0.9.3 · sigmavirus24/github3.py
End of explanation
"""


# once we have a repo, we can instantiate it
repo = gh.repository('rdhyee-GITenberg', 'TEST-REPO')
repo

"""
Explanation: Now that I have an empty repo, how to do the equivalent of the following?
echo "# TEST-REPO" &gt;&gt; README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/rdhyee-GITenberg/TEST-REPO.git
git push -u origin master
End of explanation
"""


# now have r -- a repo

# let's read off key parameters
# latest commit

# borrow code from https://github.com/sigmavirus24/github3.py/blob/d3552f77778c5f570cdd7efa5c80c0b88b8d9ad7/tests/integration/test_repos_repo.py#L239

data = {
    'path': 'README.md',
    'message': 'first pass',
    'content': b'Hello world',
    'branch': 'master'
}

created_file = repo.create_file(**data)
created_file

# create a tag?

import arrow

commit = created_file['commit']
commit.sha

user = gh.user()

tag_data =  {
    'tag': '0.0.1',
    'message': 'tag 0.0.1',
    'sha': commit.sha,
    'obj_type': 'commit',
    'tagger': {
        'name': user.name,
        'email': user.email,
        'date': arrow.utcnow().isoformat()
    },
    'lightweight': False
}

tag = repo.create_tag(**tag_data)
tag  

# get list of current tags

list(repo.iter_tags())

# directory_contents (in v 1+)
# [github3.py/test_repos_repo.py at d3552f77778c5f570cdd7efa5c80c0b88b8d9ad7 · sigmavirus24/github3.py](https://github.com/sigmavirus24/github3.py/blob/d3552f77778c5f570cdd7efa5c80c0b88b8d9ad7/tests/integration/test_repos_repo.py#L475-L486)

# 
repo.contents("")

# grab content
content = repo.contents("README.md", ref='master')

new_content = content.decoded.decode('utf-8') + u"\n" + u"line 2"

data = {
    'message': 'second pass',
    'content': new_content.encode('utf-8'),
}

commit = content.update(**data)
commit

# tag again

tag_data =  {
    'tag': '0.0.2',
    'message': 'tag 0.0.2',
    'sha': commit.sha,
    'obj_type': 'commit',
    'tagger': {
        'name': user.name,
        'email': user.email,
        'date': arrow.utcnow().isoformat()
    },
    'lightweight': False
}

tag = repo.create_tag(**tag_data)
tag

"""
Explanation: challenges of using the GitHub API to do many things / simplification
python - How to create a commit and push into repo with GitHub API v3? - Stack Overflow
But there is a File CRUD API: repo.create_file() in github3.py/repo.py at 0.9.3
End of explanation
"""


