from __future__ import unicode_literals

from db import Base
from hashlib import sha1
from sqlalchemy import Column, Integer, Unicode, ForeignKey, Boolean, DateTime, Table
from sqlalchemy.orm import relation, backref
from gettext import gettext as _
import string
from random import Random
import datetime
import config
import web

metadata = Base.metadata

class User(Base):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(60), unique=True)
    password = Column(Unicode(128))
    email = Column(Unicode(256))
    super_user = Column(Boolean)
    creation_date = Column(DateTime())
    # state can be either active or inactive
    state = Column(Unicode(30))
    # Unicode used for password recovery and for activating the user
    temp_token = Column(Unicode(50))
    temp_token_valid_until = Column(DateTime(50))

    user_organizative_unit = Table('user_organizative_unit', metadata,
        Column('user_id', Integer, ForeignKey('user.id')),
        Column('organizative_unit_id', Integer, ForeignKey('organizative_unit.id'))
    )
    organizative_units = relation('OrganizativeUnit', secondary=user_organizative_unit)


    def __init__(self, name=u'', password='', email=u''):
        self.name = name
        if password:
            self.set_password(password)
        self.email = email
        self.super_user = False
        self.state = u'inactive'
        self.creation_date = datetime.datetime.now()
        self.generate_temp_token()

    def generate_temp_token(self):
        '''
        Generates a new temporal token valid for 48 hours
        '''
        self.temp_token_valid_until = datetime.timedelta(days = 2)+datetime.datetime.now()
        self.temp_token = ''.join(Random().sample(string.letters + string.digits, 50))

    def send_activation_mail(self):
        title = _('Welcome to %s, %s') % (config.sitename, self.name)
        text = _("""
Welcome to %s, %s!

You can activate you account using the URL below:
%suser/confirmemail/%s/%s

If you didn't request the creation of this user, you should ignore this email.

Thanks for joining us,
%s
            """) % (config.sitename, self.name, config.siteurl, self.name, self.temp_token, config.sitename)
        print text
        try:
            web.sendmail(config.system_email, self.email, title, text)
        except:
            print " ** CAN'T SEND EMAIL ** "

    def send_recover_password_mail(self):
        self.generate_temp_token()
        title = _('Reset password for %s, %s') %  (config.sitename, self.name)
        text = _("""
To recover your password in %s for the user %s, use the following URL:

%suser/recoverpassword/%s/%s

If you didn't request the recovery of your password, you should ignore this email.

Regards,
%s
            """) % (config.sitename, self.name, config.siteurl, self.name, self.temp_token, config.sitename)
        print text
        web.sendmail(config.system_email, self.email, title, text)

    def validate_temp_token(self, token):
        '''
        Returns whether the given token is valid or not
        '''
        now = datetime.datetime.now()
        if now >= self.temp_token_valid_until:
            return False

        if self.temp_token != token:
            return False

        self.temp_token_valid_until = datetime.datetime.min # this invalidates the temp token
        self.temp_token = ''
        self.state = u'active'
        return True

    def set_password(self, password):
        self.password = unicode(sha1(password).hexdigest())

    def auth(self, password):
        return self.state == u'active' and self.password == sha1(password).hexdigest()

    def is_super_user(self):
        return self.super_user

    def is_active(self):
        return self.state == u'active'

    def __repr__(self):
        return self.name

    @classmethod
    def current(self):
        '''
        Returns current user. If there's no user logged in, returns anonymous user.
        '''
        import web
        if not web.ctx.session.has_key('loggedin'):
            return web.ctx.orm.query(User).filter(User.name == u'anonymous').first()

        username = web.ctx.session.get('username', '')
        user_object = web.ctx.orm.query(User).filter(User.name == username).first()
        if user_object is None:
            return web.ctx.orm.query(User).filter(User.name == u'anonymous').first()

        return user_object

    #################
    # dbadmin stuff #
    #################

    @classmethod
    def fields(self):
        return ('name', 'email', 'super_user', 'state')


class Role(Base):
    __tablename__ = 'role'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(60), unique=True)

    user_role = Table('user_role', metadata,
        Column('user_id', Integer, ForeignKey('user.id')),
        Column('role_id', Integer, ForeignKey('role.id'))
    )
    users = relation('User', secondary=user_role, backref='roles')

    def __init__(self, name=u'', users=None):
        self.name = name
        if users is None: users = []
        self.users = users

    def __repr__(self):
        return self.name

    @classmethod
    def fields(self):
        return ('name', )


class Action(Base):
    __tablename__ = 'action'
    permissions = Table('permissions', metadata,
        Column('role_id', Integer, ForeignKey('role.id')),
        Column('action_id', Integer, ForeignKey('action.id'))
    )

    id = Column(Integer, primary_key=True)
    name = Column(Unicode(120), unique=True)
    roles = relation('Role', secondary=permissions, backref='actions')

    def __init__(self, name=u'', roles=None):
        self.name = name
        if roles is None: roles = []
        self.roles = roles

    def __repr__(self):
        return self.name

    @classmethod
    def fields(self):
        return ('name', )
