#!/usr/bin/env python
# Copyright (C) 2010 Samuel Abels.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2, as
# published by the Free Software Foundation.
#
# This program 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
import sys
import os
import logging
from optparse import OptionParser
from Exscript import __version__
from Exscript.util import pidutil, daemonize
from Exscriptd.Config import Config, default_config_dir
from Exscriptd.Dispatcher import Dispatcher

parser = OptionParser(usage = '%prog [options] [start|stop|restart]',
                      version = __version__)
parser.add_option('--config-dir',
                  dest    = 'config_dir',
                  default = default_config_dir,
                  metavar = 'FILE',
                  help    = '''
The XML config file for the Exscript daemon.
'''.strip())
parser.add_option('--pidfile',
                  dest    = 'pidfile',
                  metavar = 'FILE',
                  help    = '''
The file used for tracking the process id of the daemon.
'''.strip())
parser.add_option('--verbose',
                  dest    = 'verbose',
                  action  = 'store_true',
                  default = False,
                  help    = 'Show the conversation with the router')

# Parse options.
options, args = parser.parse_args(sys.argv)
args.pop(0)

try:
    action = args.pop(0)
except IndexError:
    parser.error('action argument not specified')

if not options.config_dir:
    parser.error('required option --config-dir not set')

# Make sure that the daemon is not already running.
if not options.pidfile:
    options.pidfile = os.path.join(options.config_dir, 'exscript.pid')

if action == 'stop':
    if not pidutil.isalive(options.pidfile):
        parser.error('no running daemon found')
    pidutil.kill(options.pidfile)
    print "exscriptd stopped."
    sys.exit(0)
if action == 'start' and pidutil.isalive(options.pidfile):
    parser.error('daemon is already running')
if action == 'restart':
    pidutil.kill(options.pidfile)
    print "exscriptd stopped."

daemonize.daemonize()

logger = logging.getLogger('exscript')
logger.setLevel(logging.INFO)

# Catch output that is written to stdout, and redirect it to
# Python's logging.
class LoggingIO(object):
    def __init__(self, logger, channel = logging.INFO):
        self.logger  = logger
        self.channel = channel

    def write(self, data):
        data = data.rstrip()
        if data:
            self.logger.log(self.channel, data)

    def flush(self):
        pass

sys.stdout = LoggingIO(logger)
sys.stderr = LoggingIO(logger, logging.ERROR)

# Read the config.
config = Config(options.config_dir)
logger.info('config read')
if not os.path.isdir(config.get_logdir()):
    os.makedirs(config.get_logdir())
logfile = os.path.join(config.get_logdir(), 'exscriptd.log')

# Set up logfile rotation.
handler = logging.handlers.RotatingFileHandler(logfile,
                                               maxBytes    = 2000000,
                                               backupCount = 10)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
logging.info('exscriptd daemonized')

# Init.
order_db = config.get_order_db()
logger.info('order db initialized')
queues = config.get_queues()
logger.info('queues initialized')
dispatcher = Dispatcher(order_db, queues, logger, config.get_logdir())
logger.info('dispatcher initialized')

daemon = config.get_daemon(dispatcher)
logger.info('daemon initialized')
services = config.get_services(dispatcher)
logger.info('services initialized')

if not services:
    dir = os.path.join(options.config_dir, 'services')
    msg = 'error: %s contains no enabled services\n' % dir
    sys.stderr.write(msg)
    sys.exit(1)

logger.info('config is ok, starting daemon')

pidutil.write(options.pidfile)
logger.info('starting daemon ' + repr(daemon.name))
daemon.run()
pidutil.remove(options.pidfile)
