# -*- coding: utf-8 -*-
"""
    sphinx.web.userdb
    ~~~~~~~~~~~~~~~~~

    A module that provides pythonic access to the `docusers` file
    that stores users and their passwords so that they can gain access
    to the administration system.

    :copyright: 2007-2008 by Armin Ronacher.
    :license: BSD.
"""

from os import path
from hashlib import sha1
from random import choice, randrange


def gen_password(length=8, add_numbers=True, mix_case=True,
                 add_special_char=True):
    """
    Generate a pronounceable password.
    """
    if length <= 0:
        raise ValueError('requested password of length <= 0')
    consonants = 'bcdfghjklmnprstvwz'
    vowels = 'aeiou'
    if mix_case:
        consonants = consonants * 2 + consonants.upper()
        vowels = vowels * 2 + vowels.upper()
    pw =  ''.join([choice(consonants) +
                   choice(vowels) +
                   choice(consonants + vowels) for _
                   in xrange(length // 3 + 1)])[:length]
    if add_numbers:
        n = length // 3
        if n > 0:
            pw = pw[:-n]
            for _ in xrange(n):
                pw += choice('0123456789')
    if add_special_char:
        tmp = randrange(0, len(pw))
        l1 = pw[:tmp]
        l2 = pw[tmp:]
        if max(len(l1), len(l2)) == len(l1):
            l1 = l1[:-1]
        else:
            l2 = l2[:-1]
        return l1 + choice('#$&%?!') + l2
    return pw


class UserDatabase(object):

    def __init__(self, filename):
        self.filename = filename
        self.users = {}
        self.privileges = {}
        if path.exists(filename):
            f = open(filename)
            try:
                for line in f:
                    line = line.strip()
                    if line and line[0] != '#':
                        parts = line.split(':')
                        self.users[parts[0]] = parts[1]
                        self.privileges.setdefault(parts[0], set()).update(
                            x for x in parts[2].split(',') if x)
            finally:
                f.close()

    def set_password(self, user, password):
        """Encode the password for a user (also adds users)."""
        self.users[user] = sha1('%s|%s' % (user, password)).hexdigest()

    def add_user(self, user):
        """Add a new user and return the generated password."""
        pw = gen_password(8, add_special_char=False)
        self.set_password(user, pw)
        self.privileges[user].clear()
        return pw

    def check_password(self, user, password):
        return user in self.users and \
            self.users[user] == sha1('%s|%s' % (user, password)).hexdigest()

    def save(self):
        f = open(self.filename, 'w')
        try:
            for username, password in self.users.iteritems():
                privileges = ','.join(self.privileges.get(username, ()))
                f.write('%s:%s:%s\n' % (username, password, privileges))
        finally:
            f.close()
