import click
import codecs
import falcon
import logging
import os
import string
from asn1crypto import pem
from asn1crypto.csr import CertificationRequest
from datetime import datetime, timedelta
from time import time
from certidude import mailer, const
from certidude.tokens import TokenManager
from certidude.relational import RelationalMixin
from certidude.decorators import serialize
from certidude.user import User
from certidude import config
from .utils import AuthorityHandler
from .utils.firewall import login_required, authorize_admin

logger = logging.getLogger(__name__)

class TokenResource(AuthorityHandler):
    def __init__(self, authority, manager):
        AuthorityHandler.__init__(self, authority)
        self.manager = manager

    def on_get(self, req, resp):
        return

    def on_put(self, req, resp):
        try:
            username, mail, created, expires, profile = self.manager.consume(req.get_param("token", required=True))
        except RelationalMixin.DoesNotExist:
            raise falcon.HTTPForbidden("Forbidden", "No such token or token expired")
        body = req.stream.read(req.content_length)
        header, _, der_bytes = pem.unarmor(body)
        csr = CertificationRequest.load(der_bytes)
        common_name = csr["certification_request_info"]["subject"].native["common_name"]
        assert common_name == username or common_name.startswith(username + "@"), "Invalid common name %s" % common_name
        try:
            _, resp.body = self.authority._sign(csr, body, profile=config.PROFILES.get(profile),
                overwrite=config.TOKEN_OVERWRITE_PERMITTED)
            resp.set_header("Content-Type", "application/x-pem-file")
            logger.info("Autosigned %s as proven by token ownership", common_name)
        except FileExistsError:
            logger.info("Won't autosign duplicate %s", common_name)
            raise falcon.HTTPConflict(
                "Certificate with such common name (CN) already exists",
                "Will not overwrite existing certificate signing request, explicitly delete existing one and try again")


    @serialize
    @login_required
    @authorize_admin
    def on_post(self, req, resp):
        self.manager.issue(
            issuer = req.context.get("user"),
            subject = User.objects.get(req.get_param("username", required=True)),
            subject_mail = req.get_param("mail"))
