import web
import config
from decorators import i18n
from model import User
from userdecorators import authenticated, has_permissions
import ldapauth

class LoginView:
    @i18n
    def getform(self):
        form = web.form.Form(
            web.form.Textbox('username', description=_('Username')),
            web.form.Password('password', description=_('Password')),
            web.form.Button('submit', type='submit', value=_('Login')))
        return form

    @i18n
    def GET(self):
        self.form = self.getform()
        getdata = web.input()
        if 'next' in getdata:
            web.ctx.session.go_next = getdata.next
        return web.ctx.normal_render.user.login(self.form)

    @i18n
    def POST(self):
        self.form = self.getform()
        self.form.username.note = ''
        self.form.password.note
        if not self.form.validates():
            return web.ctx.normal_render.user.login(self.form)

        # First check in ldap, next in db
        if config.LDAP:
            # creates user if it doesn't exists
            user = ldapauth.auth(self.form.username, self.form.password)
            if user:
                web.ctx.session.loggedin = True
                web.ctx.session.username = user.name
                raise web.seeother(web.ctx.session.get('go_next', '/'))

        # Check if user doesn't exist
        query = web.ctx.orm.query(User).filter(User.name == web.input().username)
        if not query.count():
            self.form.username.note = _('User doesn\'t exist')
            return web.ctx.normal_render.user.login(self.form)

        # Check if password is valid
        user = query.one()

        if not user.is_active():
            self.form.username.note = _('User is not active yet')
            return web.ctx.normal_render.user.login(self.form)

        if not user.auth(web.input().password):
            self.form.password.note = _('Invalid password')
            return web.ctx.normal_render.user.login(self.form)

        web.ctx.session.loggedin = True
        web.ctx.session.username = user.name
        raise web.seeother(web.ctx.session.get('go_next', '/'))

class LogoutView:
    @authenticated
    def GET(self):
        web.ctx.session.pop('loggedin', '')
        web.ctx.session.pop('username', '')
        raise web.seeother('/')

class ConfirmEmailView:
    def GET(self, username, temp_token):
        query = web.ctx.orm.query(User).filter(User.name == username)
        if not query.count():
            web.ctx.notify(_('Confirmation email: Invalid user'), 'notification')
            raise web.seeother('/')

        user = query.one()
        if user.is_active():
            web.ctx.notify(_('Confirmation email: User %s already active') % username, 'notification')
            raise web.seeother('/')
        
        if not user.validate_temp_token(temp_token):
            web.ctx.notify(_('Confirmation email: invalid token %s') % temp_token, 'notification')
            raise web.seeother('/')
        
        web.ctx.notify(_('Confirmation email: user %s activated successfully') % username,
            'notification')
        web.ctx.session.loggedin = True
        web.ctx.session.username = username
        raise web.seeother('/')

class RecoverPasswordView:
    '''
    Shows a form that will let the user receive an email for recovering his password
    '''
    @i18n
    def getform(self):
        form = web.form.Form(
            web.form.Textbox('username', description=_('Username or email')),
            web.form.Button('submit', type='submit', value=_('Recover pasword')))
        return form

    def GET(self):
        return web.ctx.render.user.sendrecoveremail(self.getform())

    @i18n
    def POST(self):
        self.form = self.getform()
        self.form.username.note = ''
        if not self.form.validates():
            return web.ctx.render.user.sendrecoveremail(self.form)

        # Check if user doesn't exist
        query = web.ctx.orm.query(User).filter(User.name == web.input().username)
        if not query.count():
            query = web.ctx.orm.query(User).filter(User.email == web.input().username)
            if not query.count():
                self.form.username.note = _('User doesn\'t exist')
                return web.ctx.render.user.sendrecoveremail(self.form)
            user = query.one()
        user = query.one()
        user.send_recover_password_mail()
        web.ctx.notify(_('Password recovery email sent to %s') % web.input().username,
            'notification')
        raise web.seeother('/')

class ChangePasswordView:
    '''
    Once the user has received the password recovery email, this form actually lets him change
    his password
    '''
    @i18n
    def getform(self):
        pass_regexp = web.form.regexp(r".{7,}", 'Must have more than 7 characters')

        form = web.form.Form(
            web.form.Password('password', pass_regexp, description=_('New Password')),
            web.form.Password('password2', pass_regexp, description=_('Repeat New Password')),
            web.form.Button('submit', type='submit', value=_('Change password')),
            validators = [
                web.form.Validator(_('Passwords did\'t match'),
                    lambda i: i.password == i.password2)])
        return form

    @i18n
    def GET(self, username=None, temp_token=None):
        self.form = self.getform()
        query = web.ctx.orm.query(User).filter(User.name == username)
        if not query.count():
            web.ctx.notify(_('Password recovery: Invalid user'), 'notification')
            raise web.seeother('/')

        user = query.one()
        if not user.is_active():
            web.ctx.notify(_('Password recovery: User %s is not active') % username, 'notification')
            raise web.seeother('/')

        if not user.validate_temp_token(temp_token):
            web.ctx.notify(_('Password recovery: invalid token %s') % temp_token, 'notification')
            raise web.seeother('/')

        web.ctx.session.loggedin = True
        web.ctx.session.username = username
        return web.ctx.render.user.changepassword(self.form)

    @i18n
    @authenticated
    def POST(self, username, temp_token):
        self.form = self.getform()
        if not self.form.validates():
            return web.ctx.render.user.changepassword(self.form)
        user = web.ctx.orm.query(User).filter(User.name == web.ctx.session.username).one()
        user.set_password(web.input().password)
        web.ctx.orm.add(user)
        web.ctx.notify(_('Password changed for user %s') % user.name, 'notification')
        web.seeother('/')

class AuthenticatedChangePasswordView:
    '''
    Change password when user is logged in.
    '''
    @i18n
    def getform(self):
        pass_regexp = web.form.regexp(r".{7,}", 'Must have more than 7 characters')

        form = web.form.Form(
            web.form.Password('password', pass_regexp, description=_('New Password')),
            web.form.Password('password2', pass_regexp, description=_('Repeat New Password')),
            web.form.Button('submit', type='submit', value=_('Change password')),
            validators = [
                web.form.Validator(_('Passwords did\'t match'),
                    lambda i: i.password == i.password2)])
        return form

    @i18n
    @authenticated
    def GET(self):
        self.form = self.getform()
        return web.ctx.render.user.changepassword(self.form)

    @i18n
    @authenticated
    def POST(self, username, temp_token):
        self.form = self.getform()
        if not self.form.validates():
            return web.ctx.render.user.changepassword(self.form)
        user = web.ctx.orm.query(User).filter(User.name == web.ctx.session.username).one()
        user.set_password(web.input().password)
        web.ctx.orm.add(user)
        web.ctx.notify(_('Password changed for user %s') % user.name, 'notification')
        web.seeother('/')

class PreferencesView:
    @i18n
    @authenticated
    def GET(self):
        return web.ctx.render.user.preferences()

class ProfileView:
    @authenticated
    @i18n
    def GET(self, username):
        if username != web.ctx.session.username:
            current_user = web.ctx.orm.query(User).filter(User.name == web.ctx.session.username).one()
            if not current_user.super_user:
                web.ctx.notify(_('Not enough permissions'), 'notification')
            raise web.seeother('/')
        try:
            user = web.ctx.orm.query(User).filter(User.name == username).one()
        except:
            web.ctx.notify(_('Invalid username'), 'notification')
            raise web.seeother('/')
        return web.ctx.render.user.view(user)

class ProfileEditView:
    @i18n
    @authenticated
    def GET(self):
        raise web.seeother('/')

