#!/usr/bin/env python

import os
import re
import web
import db
from clientjob.model import Job
import config
import datetime
import utils
from pluginmanager.pluginmanager import PluginManager

from user.views import get_user


PLUGIN_PATH = re.compile(r'/plugin/(?P<plugin>[^/]*).*')

urls = (
    '/navigator/computer/([^/]+)/edit/',         'navigator.navigator.NavigatorComputerEdit',
    '/navigator/computer/([^/]+)/del/',          'navigator.navigator.NavigatorComputerDel',
    '/navigator/computer/(.*)/',                 'navigator.navigator.NavigatorComputer',
    '/navigator/ou/([^/]+)/computer/add/',       'navigator.navigator.NavigatorComputerAdd',
    '/navigator/ou/add/',                        'navigator.navigator.NavigatorOrganizativeUnitAdd',
    '/navigator/ou/([^/]+)/add/',                'navigator.navigator.NavigatorOrganizativeUnitAdd',
    '/navigator/ou/([^/]+)/edit/',               'navigator.navigator.NavigatorOrganizativeUnitEdit',
    '/navigator/ou/([^/]+)/del/',                'navigator.navigator.NavigatorOrganizativeUnitDel',
    '/navigator/ou/(.*)/',                       'navigator.navigator.NavigatorOrganizativeUnit',
    '/navigator/',                               'navigator.navigator.NavigatorOrganizativeUnit',
    '/plugin/(.*)',                              'pluginmanager.pluginview.PluginView',
    '/pluginmanager/',                           'pluginmanager.listview.ListView',
    '/pluginmanager/enable/(\w+)/',              'pluginmanager.enableview.EnableView',
    '/pluginmanager/disable/(\w+)/',             'pluginmanager.disableview.DisableView',
    '/pluginmanager/uninstall/(\w+)/',           'pluginmanager.uninstallview.UninstallView',
    '/pluginmanager/options/(\w+)/',             'pluginmanager.options.Options',
    '/panel/',                                   'panel.panel.Panel',
    '/user/',                                    'user.views.Models',
    '/user/(users|roles)/',                      'user.views.ViewModel',
    '/user/(users|roles)/add/',                  'user.views.ItemAdd',
    '/user/(users|roles)/edit/(\w+)/',           'user.views.ItemEdit',
    '/user/(users|roles)/del/(\w+)/',            'user.views.ItemDel',
    #'/user/register/',                           'user.createuserview.CreateUserView',
    '/user/login/',                              'user.login.LoginView',
    '/user/logout/',                             'user.login.LogoutView',
    '/user/confirmemail/(\w+)/(.*)/',            'user.login.ConfirmEmailView',
    '/user/recoverpassword/',                    'user.login.RecoverPasswordView',
    '/user/recoverpassword/(\w+)/(.*)/',         'user.login.ChangePasswordView',
    '/user/changepassword/',        'user.login.AuthenticatedChangePasswordView',
    '/user/preferences/',                        'user.login.PreferencesView',
    '/user/view/(.*)',                           'user.login.ProfileView',
    #'/user/editdetails/',                        'user.login.EditDetailsView',
    #'/user/view/(.*)/',                          'user.login.UserView',
    '/dbadmin/$',                                'dbadmin.dbadmin.Admin',
    '/dbadmin/(?P<model>\w+)/$',                 'dbadmin.dbadmin.View',
    '/dbadmin/(?P<model>\w+)/add/$',             'dbadmin.dbadmin.Add',
    '/dbadmin/(?P<model>\w+)/edit/(?P<id>.*)/$', 'dbadmin.dbadmin.Edit',
    '/dbadmin/(?P<model>\w+)/del/(?P<id>.*)/$',  'dbadmin.dbadmin.Del',
    '/jobs/(?P<parent_id>.*)/$',                 'clientjob.jobview.JobView',
    '/jobs/',                                    'clientjob.jobview.JobView',
     '/',                                        'navigator.navigator.NavigatorOrganizativeUnit',
)

pmanager = PluginManager()
app = web.application(urls, globals())

# session with reloader
if web.config.get('_session') is None:
    store = web.session.DiskStore('sessions')
    session = web.session.Session(app, store)
    web.config._session = session
else:
    session = web.config._session

def session_hook():
    web.ctx.session = session
    lang = web.input().get('lang', '')
    if lang:
        session.lang = lang
    elif session.get('lang', ''):
        lang = session.lang
    else:
        langs = map(str.strip,
                web.ctx.environ.get('HTTP_ACCEPT_LANGUAGE',
                    'en').split(','))
        lang = [i for i in langs if i in config.langs]
        lang = lang[0] if lang else config.langs[0]
    if not lang in config.langs:
        lang = config.langs[0]
    session.lang = lang

    gtx = utils.get_gettext(lang)
    web.ctx.gettext = gtx.gettext
    web.ctx.ngettext = gtx.ngettext
    # plugin translations
    match = PLUGIN_PATH.match(web.ctx.path)
    if match:
        plugin_name = match.group('plugin')
        plugin_locale_dir = os.path.join(config.pluginsdir, plugin_name, 'i18n')
        gtx = utils.get_gettext(lang, plugin_locale_dir)
        web.ctx.plugin_gettext = gtx.gettext
        web.ctx.plugin_ngettext = gtx.ngettext
    else:
        web.ctx.plugin_gettext = web.ctx.gettext
        web.ctx.plugin_ngettext = web.ctx.ngettext
    # templates
    context = {'static': '/static',
               'org': 'opengnsys',
               '_': web.ctx.gettext,
               '_p': web.ctx.plugin_gettext,
               'get_user': get_user,
               'storage': web.storage,
               'getattr': getattr,
               'session': session,
               'get_notifications' : get_notifications,
               'actions_panel' : None}
    normal_render = web.template.render('templates', globals=context)
    context['render'] = normal_render
    render = web.template.render('templates', base='layout',
                            globals=context)
    web.ctx.render = render
    web.ctx.normal_render = normal_render
    web.ctx.notify = add_notification
    web.ctx.plugin_manager = pmanager
    web.ctx.context = context


# Sqlalchemy processor
def load_sqla(handler):
    def commit(orm):
        try:
            orm.commit()
        except Exception, e:
            orm.rollback()
            web.ctx.notify(unicode(e), "error")


    web.ctx.orm = utils.adquire_thread_orm()
    try:
        to_ret = handler()
    except web.HTTPError:
        commit(web.ctx.orm)
        raise
    except:
        web.ctx.orm.rollback()
        raise
    commit(web.ctx.orm)
    return to_ret

def protect_pages(handler):
    '''
    Protects all pages except PUBLC_PATHS
    '''
    public = False
    for pathre in config.PUBLIC_PATHS:
        if re.match(pathre, web.ctx.path):
            public = True
            break
    if public or web.ctx.session.has_key('loggedin'):
        return handler()
    else:
        raise web.seeother('/user/login?next=%s' % web.ctx.path)

def get_notifications():
    return web.ctx.session.pop('notifications', [])

def add_notification(text, type_var):
    new_notification = web.storage(text=text, type=type_var, date=datetime.datetime.now())
    notifications = web.ctx.session.get('notifications', [])
    notifications.append(new_notification)
    web.ctx.session['notifications'] = notifications

app.add_processor(web.loadhook(session_hook))
app.add_processor(load_sqla)
app.add_processor(web.loadhook(utils.init_actions))
app.add_processor(web.unloadhook(utils.reset_actions))
app.add_processor(protect_pages)


def notfound():
    if web.ctx.path.endswith("/"):
        return web.notfound(web.ctx.render.notfound())
    else:
        raise web.seeother(web.ctx.path + '/')

def internalerror():
    if web.ctx.path.endswith("/"):
        return web.internalerror(web.ctx.render.internalerror())
    else:
        raise web.seeother(web.ctx.path + '/')

app.notfound = notfound
app.internalerror = internalerror


if __name__ == '__main__':
    #app.run(Log)
    app.run()
