#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement

import bisect
import logging
import feedgenerator

from opster import command
from github2.client import Github

def save_feed(filename, title, link, description, items):
    log = logging.getLogger()

    feed = feedgenerator.Atom1Feed(
        title=title,
        link=link,
        description=description,
        language=u'en',
    )

    for dt, fork_repname, commit in items:
        short_commit_message = commit.message.split('\n', 1)[0]
        log.debug(
            u'%s %s %s %s',
            fork_repname,
            commit.committed_date,
            commit.author['login'],
            short_commit_message
        )

        feed.add_item(
            title=fork_repname + ' ' + short_commit_message,
            link=u'http://github.com' + commit.url,
            description=commit.message,
            pubdate=commit.committed_date,
            author_name=commit.author['name'],
            author_email=commit.author['email'],
            author_link=u'http://github.com/' + commit.author['login'],
        )

    with open(filename, 'w') as f:
        feed.write(f, 'utf-8')


@command(usage='%name (username or username/repository) [-o output.xml]')
def main(
        repository_or_username,
        output_filename=('o', '%(username)s-%(repository)s.xml', 'output filename. '
                              'Omit "repository" name to save all projects in one file.'),
        max_feed_length=('l', 100, 'max feed length'),
        ignore=('i', '', 'comma-separated repositories to ignore'),
    ):
    """Utility to build Atom feed for new commits from your projects' forks on the GitHub."""

    logging.basicConfig(
        format='%(asctime)s %(levelname)s %(message)s',
        level=logging.DEBUG,
    )
    log = logging.getLogger()

    gh = Github()

    separate_feeds = ('%(repository)s' in output_filename)

    if '/' in repository_or_username:
        username, repository = repository_or_username.split('/', 1)
        repositories = [repository]
    else:
        username = repository_or_username
        ignored = filter(None, (rep.strip() for rep in ignore.split(',')))
        repositories = [rep.name for rep in gh.repos.list(username) if rep.name not in ignored]

    feed_items = []

    for repository in repositories:
        full_repname = username + '/' + repository
        log.info('Processing %s' % full_repname)

        # first, we need to get the date of the last commit
        commits = gh.commits.list(full_repname, 'master')
        last_commit_date = commits[0].committed_date

        for fork in gh.repos.network(full_repname):
            fork_repname = '%(owner)s/%(name)s' % fork

            if fork_repname != full_repname:
                for branch in gh.repos.branches(fork_repname):
                    log.info('Fetching commits from %s:%s' % (fork_repname, branch))
                    fork_commits = gh.commits.list(fork_repname, branch)

                    for commit in fork_commits:
                        # ignore old commits, commits from myself and commits where author is not the fork owner
                        if commit.committed_date > last_commit_date and \
                                commit.author['login'] != username and \
                                commit.author['login'] == fork['owner']:
                            bisect.insort(feed_items, (commit.committed_date, fork_repname, commit))

        if separate_feeds:
            # save feed for this particular project
            save_feed(
                filename=output_filename % locals(),
                title=u'%s forks' % full_repname,
                link=u'http://github.com/%s' % full_repname,
                description=u'Commits from forks of %s repository at GitHub.' % full_repname,
                items=feed_items[-1:-max_feed_length-1:-1],
            )
            feed_items = []
        else:
            feed_items = feed_items[-max_feed_length:]

    if not separate_feeds:
        # save single feed for all projects
        save_feed(
            filename=output_filename % locals(),
            title=u'%s forks' % username,
            link=u'http://github.com/%s' % username,
            description=u'%s\'s projects forks commits at GitHub.' % username,
            items=feed_items[-1:-max_feed_length-1:-1],
        )


if __name__ == '__main__':
    main()
