#! /usr/bin/env python
# -*- coding: utf-8 -*-

# gracie
# Part of Gracie, an OpenID provider
#
# Copyright © 2007 Ben Finney <ben+python@benfinney.id.au>
# This is free software; you may copy, modify and/or distribute this work
# under the terms of the GNU General Public License, version 2 or later.
# No warranty expressed or implied. See the file LICENSE for details.

""" Application behaviour for Gracie
"""

import optparse
import logging

from gracie.server import become_daemon
from gracie import version
from gracie.server import GracieServer
from gracie.httpserver import default_host, default_port, default_root_url


class OptionParser(optparse.OptionParser):
    """ Commandline option parser for this application """

    def __init__(self):
        """ Set up a new instance """
        optparse.OptionParser.__init__(self)

        self.version = version.version_full
        self.init_options()

    def init_options(self):
        """ Set up options """

        self.add_option('-V', '--version',
            action='version',
            help="Report version of program and exit",
        )
        self.add_option('--log-level',
            action='store', type='string', default="WARN",
            dest='loglevel', metavar='LEVEL',
            help="Set logging verbosity level to LEVEL"
                 " (default %default)",
        )
        self.add_option('--data-dir',
            action='store', type='string', default="/var/lib/gracie",
            dest='datadir', metavar='DIR',
            help="Store server runtime data in directory DIR"
                 " (default %default)",
        )
        self.add_option('--host',
            action='store', type='string', default=default_host,
            dest='host', metavar='HOST',
            help="Listen on address HOST; can be name or address"
                 " (default %default)",
        )
        self.add_option('--port',
            action='store', type='int', default=default_port,
            dest='port', metavar='PORT',
            help="Listen on TCP port PORT"
                 " (default %default)",
        )
        self.add_option('--root-url',
            action='store', type='string', default=default_root_url,
            dest='root_url', metavar='URL',
            help="Set root URL of the server to URL"
                 " (default %default)",
        )


class Gracie(object):
    """ Behaviour for Gracie application """

    def __init__(self, argv):
        """ Set up a new instance """
        self._process_commandline(argv)
        self._init_logging()

    def _process_commandline(self, argv):
        """ Process command line to this application """
        option_parser = OptionParser()
        (opts, args) = option_parser.parse_args(argv[1:])
        (min_args, max_args) = (0, 0)
        len_args = len(args)
        if not (min_args <= len_args <= max_args):
            message = (
                "Wrong number of arguments"
                " (%(len_args)d): %(args)r"
                ) % vars()
            option_parser.error(message)
        (self.opts, self.args) = (opts, args)

    def _init_logging(self):
        """ Initialise the logging system """
        level = getattr(logging, self.opts.loglevel, None)
        format =  "%(asctime)s %(name)s: %(levelname)s: %(message)s"
        time_format = "%F %T"
        logging.basicConfig(
            level = level,
            format = format, datefmt = time_format,
        )

    def _get_socket_params(self):
        """ Determine the server socket parameters """
        params = (self.opts.host, self.opts.port)
        return params

    def main(self):
        """ Run the Gracie application """
        socket_params = self._get_socket_params()
        self.server = GracieServer(socket_params, self.opts)

        become_daemon()
        self.server.serve_forever()


def __main__(argv=None):
    """ Mainline code for this program """

    from sys import argv as sys_argv
    if argv is None:
        argv = sys_argv

    app = Gracie(argv)
    exitcode = None
    try:
        app.main()
    except SystemExit, e:
        exitcode = e.code

    return exitcode

if __name__ == "__main__":      #pragma: nocover
    import sys
    exitcode = __main__(argv=sys.argv)
    sys.exit(exitcode)
