
import os
import string

from itsdangerous import URLSafeTimedSerializer, SignatureExpired, BadData

from .events import EventFactory


event = EventFactory()


def sign_payload(email, payload, secret, salt):
    serializer = URLSafeTimedSerializer(secret)

    return serializer.dumps([email, payload], salt=salt)


def verify_payload(encoded_payload, secret, salt, signer_email, max_age):
    serializer = URLSafeTimedSerializer(secret)
    context = event.Context(email=signer_email)

    try:
        email, payload = serializer.loads(
            encoded_payload, salt=salt, max_age=max_age)

    except SignatureExpired:
        raise event.BrokenRequest(
            'PAYLOAD_VERIFIED_AS_EXPIRED', context=context)

    except BadData:
        raise event.BrokenRequest(
            'PAYLOAD_VERIFIED_AS_BROKEN', context=context)

    else:
        if email != signer_email:
            raise event.BrokenRequest(
                'PAYLOAD_VERIFIED_AS_BROKEN_MISMATCHING_EMAILS',
                context=context)

    return payload


def create_secret(length=64, with_punctuation=True):
    """Generate a secret stored on each User's Account.

    The values generated by this function resulted in 100% score on
    http://www.passwordmeter.com/.

    """
    chars = (
        string.ascii_uppercase +
        # introduce digits twice to boost the probability of its
        # occurrence in the secret
        string.digits + string.digits +
        string.ascii_lowercase)
    if with_punctuation:
        chars += string.punctuation

    chars_len = len(chars)
    secret = ''

    for i in range(length):
        secret += chars[ord(os.urandom(1)) % chars_len]

    return secret
