#!/usr/bin/env python
__requires__ = 'BazBase'

import os, sys
from os.path import *

# -- START USER EDIT SECTION
# -- Users must edit this section --
code_dir = dirname(abspath(__file__))       # (Required) The base directory of the TG app code.
PROJECTNAME = 'xibalba'
root_class_name = PROJECTNAME+'.controllers.Root' # (Required) The fully qualified Root class name.
project_module_name = PROJECTNAME+'.config'      # (Required) The config module name. Replace
# PROJECTNAME with your project's name (e.g. wiki20).
log_dir = join(code_dir,'log')

__import__(PROJECTNAME) # Make sure its requirements get satisfied

# -- END USER EDIT SECTION

# We do this here, not before the user stuff, in case importing PROJECTNAME
# is important
import pkg_resources
pkg_resources.require("flup")

try:
    sys.stdout = open(join(log_dir, 'flup-stdout.log'),'a')
    sys.stderr = open(join(log_dir, 'flup-stderr.log'),'a')

    import time
    starttime = time.time()

    from flup.server.fcgi import WSGIServer

    class RestartingServer(WSGIServer):
        """A variant on WSGIServer that exits if we've been modified, to
        allow Apache to restart us."""

        def _mainloopPeriodic(self):
            WSGIServer._mainloopPeriodic(self)

            mod = getmtime(__file__)
            if mod > starttime:
                self._keepGoing = False
    
    from logging import FileHandler
    import logging.handlers
    import commands
    class UnbufferedFileHandler(FileHandler):
        def emit(self, *args, **kw):
            FileHandler.emit(self, *args, **kw)
            self.flush()
            commands.getoutput('fs flush '+self.baseFilename)
    logging.handlers.UnbufferedFileHandler = UnbufferedFileHandler

    import turbogears
    import cherrypy

    print >> sys.stdout, "starting with basename %s" % basename(__file__)

    class VirtualPathFilter(object):
        def on_start_resource(self):
            infix = '/'+basename(__file__)

            path = cherrypy.request.path
            cherrypy.request.path = path.replace(infix,'',1)

            path = cherrypy.request.object_path
            cherrypy.request.object_path = path.replace(infix,'',1)

            path = cherrypy.request.wsgi_environ['SCRIPT_NAME']
            cherrypy.request.wsgi_environ['SCRIPT_NAME'] = path.replace(
                turbogears.config.get('server.webpath')+infix,'',1)

    def tg_init():
        """ Checks for the required data and initializes the application. """

        global code_dir
        global root_class_name
        global project_module_name
        last_mark = 0

        # Input checks
        if not code_dir or not isdir(code_dir):
            raise ValueError("""The code directory setting is missing.
                                The fastcgi code will be unable to find
                                the TG code without this setting.""")

        if not root_class_name:
            raise ValueError("""The fully qualified root class name must
                                be provided.""")

        last_mark = root_class_name.rfind('.')

        if (last_mark < 1) or (last_mark + 1) == len(root_class_name):
            raise ValueError("""The user-defined class name is invalid.
                                Please make sure to include a fully
                                qualified class name for the root_class
                                value (e.g. wiki20.controllers.Root).""")


        print >> sys.stdout, "code dir: %s, log_dir: %s" % (code_dir, log_dir)

        sys.path.append(code_dir)

        if exists(join(code_dir, "setup.py")):
            print >> sys.stdout, "About to update config from %s" % join(code_dir, "dev.cfg")
            turbogears.update_config(configfile=join(code_dir, "dev.cfg"),modulename=project_module_name)
        else:
            print >> sys.stdout, "About to update config from %s" % join(code_dir, "prod.cfg")
            turbogears.update_config(configfile=join(code_dir, "prod.cfg"),modulename=project_module_name)
        # This is my convention, totally separate from the
        # TurboGears/Cherrypy autoreload functionality
        turbogears.config.update({'restart.file':abspath(__file__)})

        # Parse out the root class information for Cherrypy Root class.
        package_name = root_class_name[:last_mark]
        class_name = root_class_name[last_mark+1:]
        print >> sys.stdout, "from %s import %s as Root" % (package_name,
                                                            class_name)
        exec('from %s import %s as Root' % (package_name, class_name))
        Root._cp_filters = [VirtualPathFilter()]
        cherrypy.root = Root()

    # Main section -

    # Initialize the application, then start the server.
    print >> sys.stdout, "Before tg_init()"
    tg_init()
    
    print >> sys.stdout, "Before cherrypy.server.start()"
    sys.stdout.flush()
    cherrypy.server.start(initOnly=True, serverClass=None)
    print >> sys.stdout, "After cherrypy.server.start()"
    sys.stdout.flush()

    print >> sys.stdout, "before import cherrypy/wsgiapp"
    from cherrypy._cpwsgi import wsgiApp
    print >> sys.stdout, "Before wsgiserver(application=wsgiapp).run()"
    sys.stdout.flush()
    server = RestartingServer(wsgiApp)
except Exception,e:
    from traceback import format_exception
    import pwd,socket
    tup = sys.exc_info()
    def errApp(environ, start_response):
        start_response('500 Flup Error', [('Content-Type', 'text/plain')],
                       sys.exc_info())

        for l in format_exception(*tup):
            yield l
        whoami = pwd.getpwuid(os.getuid())[0]
        hostname = socket.gethostname()
        yield "To restart: touch %s\n" % (abspath(__file__))
    errserver = RestartingServer(errApp)
    errserver.run()
    print >> sys.stdout, "Error server exiting, probably due to modification."
    sys.stdout.flush()
else:
    server.run()
    print >> sys.stdout, "WSGIServer exiting, probably due to modification."
    sys.stdout.flush()
