#!/usr/bin/python
import os, json, hashlib, hmac, utils
from bottle import request, redirect, abort

# Hashing

def hash_password(password):
    salt = os.urandom(16)
    pw_hash = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, 100000)
    return salt, pw_hash

def check_password(salt, pw_hash, password):
    return hmac.compare_digest(
        bytes.fromhex(pw_hash),
        hashlib.pbkdf2_hmac("sha256", password.encode(), bytes.fromhex(salt), 100000)
    )

# Helpers

def get_users():
    return utils.safejsonload(os.path.join("db", "users.json"))

def is_user(username):
    return username and username in get_users()

def is_admin(username):
    users = get_users()
    return username and username in users and users[username]["admin"]

def valid_credentials(username, password):
    if not username or not password:
        return False

    users = get_users()
    return users and username in users and check_password(users[username]["salt"], users[username]["hash"], password)

def user_surveys(username):
    users = get_users()
    return users[username]["surveys"] if username and username in users else []

def user_filters(username, survey):
    users = get_users()
    if "filters" in users[username] and survey in users[username]["filters"]:
        return users[username]["filters"][survey] if username and username in users else {}
    else:
        return {}

def has_survey(username, survey):
    public = utils.safejsonload(os.path.join(os.path.join("db", "surveys"), "public.json"))
    return survey in user_surveys(username) or survey in public or is_admin(username)

# Decorators

def require_user(fn):
    """TODO"""
    def check_credentials(**kwargs):
        session = request.environ.get("beaker.session")
        username = session.get("username")
        if username and is_user(username):
            return fn(**kwargs)
        else:
            redirect("/login&previous={}".format(request.url))
    return check_credentials

def require_admin(fn):
    """TODO"""
    def check_admin(**kwargs):
        session = request.environ.get("beaker.session")
        username = session.get("username")
        if username and is_admin(username):
            return fn(**kwargs)
        else:
            abort(403)
    return check_admin
