#!/usr/bin/python
# Copyright 2009 Canonical Ltd.
#
# This file is part of desktopcouch.
#
#  desktopcouch is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License version 3
# as published by the Free Software Foundation.
#
# desktopcouch is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with desktopcouch.  If not, see <http://www.gnu.org/licenses/>.
#
# Authors: Stuart Langridge <stuart.langridge@canonical.com>
#          Tim Cole <tim.cole@canonical.com>

"""CouchDB port advertiser.

A command-line utility which exports a
desktopCouch.getPort method on the bus which returns
that port, so other apps (specifically, the contacts API) can work out
where CouchDB is running so it can be talked to.

Calculates the port number by looking in the CouchDB log.

If CouchDB is not running, then run the script to start it and then
start advertising the port.

This file should be started by D-Bus activation.

"""

import logging
import logging.handlers
from errno import ENOENT

from twisted.internet import glib2reactor
glib2reactor.install()
from twisted.internet import reactor
import dbus.service, gobject, os, errno, time

import desktopcouch
from desktopcouch import local_files
from desktopcouch import replication


class PortAdvertiser(dbus.service.Object):
    "Advertise the discovered port number on the D-Bus Session bus"
    def __init__(self, death):
        bus_name = dbus.service.BusName("org.desktopcouch.CouchDB",
                     bus=dbus.SessionBus())
        self.death = death
        dbus.service.Object.__init__(self, object_path="/", bus_name=bus_name)

    @dbus.service.method(dbus_interface='org.desktopcouch.CouchDB',
                         in_signature='', out_signature='i')
    def getPort(self):
        "Exported method to return the port"
        return int(desktopcouch.find_port())

    @dbus.service.method(dbus_interface='org.desktopcouch.CouchDB',
                         in_signature='', out_signature='')
    def quit(self):
        "Exported method to quit the program"
        self.death()

if __name__ == "__main__":
    import xdg.BaseDirectory
    import gobject
    gobject.set_application_name("desktopcouch service")

    log_directory = os.path.join(xdg.BaseDirectory.xdg_cache_home,
            "desktop-couch/log")
    try:
        os.makedirs(log_directory)
    except:
        pass
    rotating_log = logging.handlers.TimedRotatingFileHandler(
            os.path.join(log_directory, "desktop-couch-replication.log"),
            "midnight", 1, 14)
    rotating_log.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
    rotating_log.setFormatter(formatter)
    logging.getLogger('').addHandler(rotating_log)
    console_log = logging.StreamHandler()
    console_log.setLevel(logging.WARNING)
    console_log.setFormatter(logging.Formatter("%(asctime)s - %(message)s"))
    logging.getLogger('').addHandler(console_log)
    logging.getLogger('').setLevel(logging.DEBUG)


    # Advertise the port
    mainloop = reactor

    portAdvertiser = PortAdvertiser(mainloop.stop)

    replication_runtime = replication.set_up(desktopcouch.find_port)
    try:

        mainloop.run()

    finally:
        if replication_runtime:
            print "Shutting down, but may be a moment to finish replication."
            replication.tear_down(*replication_runtime)

