# -*- coding: utf-8 -*-
"""WSGI middleware initialization for the Monkey application."""

import tempfile
import warnings

import tg
from repoze.retry import Retry
import MySQLdb
import sqlalchemy.exc

from bazjunk.middleware.email import EmailErrors
from bazjunk.middleware.mako import CatchMakoErrors
from bazjunk.middleware.raw import PrintRawErrors
from bazjunk.middleware.cgitb import CgitbMiddleware
from bazjunk.middleware.rewrite import UnrewriteMiddleware
from bazjunk.middleware.environ import SaveEnviron
from bazjunk.middleware.profiler import OptionalProfileMiddleware
from bazki.turbogears import wrap_app, render_html_error
from bazki import util

from monkey.config.app_cfg import base_config
from monkey.config.environment import load_environment


__all__ = ['make_app']

# Use base_config to setup the necessary PasteDeploy application factory. 
# make_base_app will wrap the TG2 app with all the middleware it needs. 
make_base_app = base_config.setup_tg_wsgi_app(load_environment)


def make_app(global_conf, full_stack=True, **app_conf):
    """
    Set Monkey up with the settings found in the PasteDeploy configuration
    file used.
    
    :param global_conf: The global settings for Monkey (those
        defined under the ``[DEFAULT]`` section).
    :type global_conf: dict
    :param full_stack: Should the whole TG2 stack be set up?
    :type full_stack: str or bool
    :return: The Monkey application with all the relevant middleware
        loaded.
    
    This is the PasteDeploy factory for the Monkey application.
    
    ``app_conf`` contains all the application-specific settings (those defined
    under ``[app:main]``.
    
   
    """

    # This probably shouldn't properly be here, but it works as well here
    # as anywhere.
    warnings.showwarning = util.showwarning
    util.filterwarnings()

    # Turn off full_stack when debugging because default debug middleware
    # breaks with fastcgi, and we want mako errors handled specially
    app = make_base_app(global_conf, full_stack=False, 
                        wrap_app=lambda a:wrap_app(a,base_config),
                        **app_conf)
    
    # Retry failed transactions.
    app = Retry(app, tries=3, retryable=(MySQLdb.OperationalError,
                                         sqlalchemy.exc.OperationalError))

    # This tempfile actually gets cleaned up by the middleware at __del__ time.
    app = OptionalProfileMiddleware(
        app,
        log_filename=tempfile.mkstemp('.bazki.profile')[1],
        discard_first_request=True,
        flush_at_shutdown=True,
        path='/profile')

    # Take the effects of our mod_rewrite rules, if we're running under Apache
    app = UnrewriteMiddleware(app, {'dispatch.fcgi':'',
                                    'dispatch.cgi':'dev'})


    # Send email on errors.
    app = EmailErrors(app, from_addr=global_conf['error_email_from'],
                      to_addr=global_conf['email_to'],
                      subject_prefix=global_conf['error_subject_prefix'],
                      smtp_server=global_conf['smtp_server'])
    # Handle mako errors specially
    # (bazki.auth disables these first two for non-omnicients by only setting
    #  'bazjunk.catch_errors' to true in the wsgi environ for omniscients.)
    app = CatchMakoErrors(app)
    # And TeXFailedErrors
    from bazki.latex import TeXFailedError
    app = PrintRawErrors(app, TeXFailedError)
    # And handle other errors with cgitb for omniscients or an html page
    # for others.
    app = CgitbMiddleware(app, gen_html=render_html_error)
    
    return app
