#!/usr/bin/python
# -*- coding: UTF-8 -*-

from flask import Blueprint
from flask import current_app
from flask import request, session, jsonify

import json

import config

from functions import dek_generate, do_encrypt_dek, do_decrypt_dek, dek_check

import utils
from utils.decorator import login_required
from utils.template import my_render_template

donor_view = Blueprint( "donor", __name__, template_folder = "templates" )

@donor_view.route( "/dek/reconstruct", methods = [ "POST" ] )
@login_required
def dek_regenerate():
    current_app.logger.info( "DEK reconstruction" )
    try:
        email_hash = request.form.get( "email_hash" )
        username = session.get( "username" )
        
        current_app.logger.debug( "User: {}".format( username ) )
        
        sql = "SELECT * FROM donor_dek WHERE donor_name = %s"
        user = config.db.query_fetchone( sql, ( username, ) )
        
        if user[ "salt" ] == None:
            current_app.logger.error( "No DEK salt for user '{}'".format( session[ "username" ] ) )
            raise
        
        _, dek, _ = dek_generate( username = username, email_hash = email_hash, salt = user[ "salt" ] )
        
        current_app.logger.debug( "DEK reconstructed: {}...".format( dek[ 0:10 ] ) )
        
        check = utils.aes.do_decrypt( user[ "dek_check" ], dek )
        check = json.loads( check )
        
        if check[ "value" ] != "ok":
            current_app.logger.error( "DEK check error for user '{}'".format( session[ "username" ] ) )
            raise
        
        current_app.logger.debug( "DEK check OK" )
        
        sql = "UPDATE donor_dek SET dek = %s WHERE id = %s AND donor_name = %s"
        config.db.query( sql, ( dek, user[ "id" ], username, ) )
        config.db.commit()
        
        current_app.logger.info( "Reconstructed DEK saved to the database" )
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@donor_view.route( "/dek/delete" )
@login_required
def dek_delete():
    try:
        username = session.get( "username" )
        
        current_app.logger.info( "Delete DEK for user {}".format( username ) )
        
        sql = "UPDATE donor_dek SET dek = NULL WHERE donor_name = %s"
        config.db.query( sql, ( username, ) )
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@donor_view.route( "/dek/fulldelete" )
@login_required
def dek_delete_fully():
    try:
        username = session.get( "username" )
        
        current_app.logger.info( "Fully delete the DEK of user {}".format( username ) )
        
        sql = "UPDATE donor_dek SET dek = NULL WHERE donor_name = %s"
        config.db.query( sql, ( username, ) )
        sql = "UPDATE donor_dek SET salt = NULL WHERE donor_name = %s"
        config.db.query( sql, ( username, ) )
        sql = "UPDATE donor_dek SET dek_check = NULL WHERE donor_name = %s"
        config.db.query( sql, ( username, ) )
        
        config.db.commit()
        
        return jsonify( {
            "error": False
        } )
    
    except:
        return jsonify( {
            "error": True
        } )

@donor_view.route( "/user/myprofile/dek" )
@login_required
def user_myprofile_dek():
    """
        Serve the page to manadge the Data Encryption Key of a donor.
    """
    current_app.logger.info( "Serve the donor DEK page" )
    
    sql = """
        SELECT dek, salt
        FROM donor_dek
        WHERE donor_name = %s
    """
    data = config.db.query_fetchone( sql, ( session[ "username" ], ) )
    
    has_dek = data[ "dek" ] != None
    has_salt = data[ "salt" ] != None
    
    current_app.logger.debug( "username: {}".format( session[ "username" ] ) )
    current_app.logger.debug( "has_dek:  {}".format( has_dek ) )
    current_app.logger.debug( "has_salt: {}".format( has_salt ) )
    
    return my_render_template( 
        "dek.html",
        has_dek = has_dek,
        has_salt = has_salt
    )

@donor_view.route( "/user/myprofile/tenprint" )
@login_required
def user_myprofile_tenprint():
    """
        Serve the page to see all the information related to the current user.

        This page is the summary of all informations related to the current logged user,
        i.e. the tenprint cards and mark images. The consent form, beeing mendatory to
        upload the tenprint and mark images, and beeing encrypted in the database, is
        not accessible by the user via this interface. The consent form has been sent the 
        the donor by email anyways before uploading any of the images.
    """
    current_app.logger.info( "Serve the page with all tenprint to the donor" )
    
    sql = """
        SELECT files.id, files.uuid
        FROM users
        LEFT JOIN submissions ON users.email = submissions.email_hash
        LEFT JOIN files ON files.folder = submissions.id
        WHERE users.id = %s AND ( files.type = 1 OR files.type = 2 OR files.type = 5 )
    """
    tenprint_cards = config.db.query_fetchall( sql, ( session[ "user_id" ], ) )
    
    current_app.logger.debug( "{} tenprint(s) stored in database".format( len( tenprint_cards ) ) )
    
    return my_render_template( 
        "tenprint.html",
        tenprint_cards = tenprint_cards
    )

@donor_view.route( "/user/myprofile/marks" )
@login_required
def user_myprofile_marks():
    current_app.logger.info( "Serve the page with all marks to the donor" )
    
    sql = """
        SELECT files.id, files.uuid
        FROM users
        LEFT JOIN submissions ON users.email = submissions.email_hash
        LEFT JOIN files ON files.folder = submissions.id
        WHERE users.id = %s AND ( files.type = 3 OR files.type = 4 )
    """
    marks = config.db.query_fetchall( sql, ( session[ "user_id" ], ) )
    nb_marks = len( marks )
    
    current_app.logger.debug( "{} mark(s) stored in database".format( len( marks ) ) )
    
    return my_render_template(
        "marks.html",
        marks = marks,
        nb_marks = nb_marks
    )

