from repoze.bfg.configuration import Configurator
from repoze.bfg.url import route_url
from repoze.bfg.threadlocal import get_current_request
from repoze.bfg.exceptions import NotFound
from repoze.bfg.view import append_slash_notfound_view
from repoze.bfg.renderers import render

from repoze.bfg.jinja2.bindings import renderer_factory as jinja2_renderer

from paste.httpserver import serve

from weberror.evalexception import EvalException

class Namespace(object):
    pass

class Groundhog(object):
    def __init__(self, package):
        self.package = package
        self.g = Namespace()
        self.config = Configurator()
        self.config.begin()
        self.config.add_renderer('groundhog', self.renderer_factory)
        self.config.add_renderer('.html', jinja2_renderer)
        self.config.set_renderer_globals_factory(self.renderer_globals_factory)
        self.config.add_view(append_slash_notfound_view, context=NotFound)
        self.config.add_static_view('static', '%s:static' % self.package)

    def renderer_factory(self, name):
        def render_(value, system):
            request = system.get('request')
            if request is not None:
                request.response_content_type = 'text/html'
            return value
        return render_

    def renderer_globals_factory(self, system):
        return {'g':self.g, 'app':self}

    def mapply(self, func):
        def mapplied(request):
            return func(**request.matchdict)
        return mapplied

    def route(self, pattern, methods=('GET', 'HEAD')):
        def decorator(func):
            endpoint = func.__name__
            self.config.add_route(endpoint, pattern)
            for method in methods:
                view = self.mapply(func)
                self.config.add_view(view, route_name=endpoint,
                                     request_method=method,
                                     renderer='groundhog')
            return func
        return decorator

    def run(self, host=None, port=8080, debug=False):
        self.config.end()
        app = self.config.make_wsgi_app()
        if debug:
            app = EvalException(app)
        serve(app, host, port)

    def url_for(self, endpoint, *arg, **options):
        if not isinstance(endpoint, basestring):
            endpoint = endpoint.__name__
        request = self.request
        return route_url(endpoint, request, *arg, **options)

    @property
    def request(self):
        return get_current_request()

    def render_template(self, name, **kw):
        request = self.request
        return render('%s:templates/%s' % (self.package, name),
                      request=request, **kw)

# application

app = Groundhog(__name__)

app.g.foo = 1

@app.route('/')
def aview():
    return ('<html><a href="%s">foo 1<a/></html>' %
            app.url_for('foo', id='1', _anchor='fudge'))

@app.route('/foo/:id')
def foo(id=None):
    return '<html>%s</html>' % id

@app.route('/slashending/')
def slashending():
    return 'ends in a slash'

@app.route('/exception')
def exc():
    raise RuntimeError('exception view')

@app.route('/templated')
def templated():
    return app.render_template('template.html', project='groundhog')

@app.route('/zpt_templated')
def zpt_templated():
    return app.render_template('template.pt', project='groundhog')

if __name__ == '__main__':
    app.run(debug=True)
    

