import trac.core

import trac.ticket.api
import trac.wiki.api
import trac.versioncontrol.api

import socket
import fedmsg

# If fedmsg was already initialized, let's not re-do that.
if not getattr(getattr(fedmsg, '__local', None), '__context', None):
    hostname = socket.gethostname().split('.', 1)[0]
    fedmsg.init(name="trac." + hostname)


def env2dict(env):
    """ Utility method to format the trac environment for fedmsg. """
    return dict(
        base_url=env.base_url,
        project_name=env.project_name,
        project_description=env.project_description,
        project_url=env.project_url,
        project_icon=env.project_icon,
    )


def wikipage2dict(page):
    attrs = ['name', 'version', 'time', 'author', 'text', 'comment']
    return dict([(attr, getattr(page, attr)) for attr in attrs])


class FedmsgPlugin(trac.core.Component):
    """ The trac fedmsg plugin.

    This plugin simply listens for trac events and
    rebroadcasts them to a fedmsg message bus.
    """
    trac.core.implements(
        trac.ticket.api.ITicketChangeListener,
        trac.wiki.api.IWikiChangeListener,
        trac.versioncontrol.api.IRepositoryChangeListener,
    )

    def publish(self, topic, **msg):
        """ Inner workhorse method.  Publish arguments to fedmsg. """
        msg['instance'] = env2dict(self.env)
        fedmsg.publish(modname='trac', topic=topic, msg=msg)

    def ticket_created(self, ticket):
        """Called when a ticket is created."""
        self.publish(topic='ticket.new', ticket=ticket.values)

    def ticket_changed(self, ticket, comment, author, old_values):
        """Called when a ticket is modified.

        `old_values` is a dictionary containing the previous values of the
        fields that have changed.
        """
        self.publish(
            topic='ticket.update',
            ticket=ticket.values,
            comment=comment,
            author=author,
            old_values=old_values,
        )

    def ticket_deleted(self, ticket):
        """Called when a ticket is deleted."""
        self.publish(topic='ticket.delete', ticket=ticket.values)

    def wiki_page_added(self, page):
        """Called whenever a new Wiki page is added."""
        self.publish(topic='wiki.page.new', page=wikipage2dict(page))

    def wiki_page_changed(self, page, version, t, comment, author, ipnr):
        """Called when a page has been modified."""
        self.publish(
            topic='wiki.page.update',
            page=wikipage2dict(page),
            version=version,
            t=t,
            comment=comment,
            author=author,
            #ipnr=ipnr,  # Don't broadcast IP addresses.  Poor form.
        )

    def wiki_page_deleted(self, page):
        """Called when a page has been deleted."""
        self.publish(topic='wiki.page.delete', page=wikipage2dict(page))

    def wiki_page_version_deleted(self, page):
        """Called when a version of a page has been deleted."""
        self.publish(topic='wiki.page.version.delete',
                     page=wikipage2dict(page))

    def wiki_page_renamed(self, page, old_name):
        """Called when a page has been renamed."""
        self.publish(
            topic='wiki.page.rename',
            page=wikipage2dict(page),
            old_name=old_name
        )

    def changeset_added(self, repos, changeset):
        """Called after a changeset has been added to a repository."""
        self.publish(
            topic='changeset.new',
            repos=[repo.name for repo in repos],
            changeset=changeset.get_properties(),
        )

    def changeset_modified(self, repos, changeset, old_changeset):
        """Called after a changeset has been modified in a repository.

        The `old_changeset` argument contains the metadata of the changeset
        prior to the modification. It is `None` if the old metadata cannot
        be retrieved.
        """
        self.publish(
            topic='changeset.update',
            repos=[repo.name for repo in repos],
            changeset=changeset.get_properties(),
            old_changeset=old_changeset.get_properties(),
        )

@@ -58,39 +58,8 @@
 .api
-%0Aimport trac.versioncontrol.api
 %0A%0Aim
@@ -1083,67 +1083,8 @@
 er,%0A
-        trac.versioncontrol.api.IRepositoryChangeListener,%0A
     
@@ -3218,843 +3218,4 @@
   )%0A
-%0A    def changeset_added(self, repos, changeset):%0A        %22%22%22Called after a changeset has been added to a repository.%22%22%22%0A        self.publish(%0A            topic='changeset.new',%0A            repos=%5Brepo.name for repo in repos%5D,%0A            changeset=changeset.get_properties(),%0A        )%0A%0A    def changeset_modified(self, repos, changeset, old_changeset):%0A        %22%22%22Called after a changeset has been modified in a repository.%0A%0A        The %60old_changeset%60 argument contains the metadata of the changeset%0A        prior to the modification. It is %60None%60 if the old metadata cannot%0A        be retrieved.%0A        %22%22%22%0A        self.publish(%0A            topic='changeset.update',%0A            repos=%5Brepo.name for repo in repos%5D,%0A            changeset=changeset.get_properties(),%0A            old_changeset=old_changeset.get_properties(),%0A        )%0A

Remove trac.versioncontrol code. Use git hook instead.