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

from datetime import timedelta
from uuid import uuid4
import os

from flask import Flask
from flask import jsonify
from flask import render_template, send_from_directory 
from flask import request
from flask import session
from flask import url_for
from flask_compress import Compress
from flask_session import Session
from werkzeug import redirect
import pyotp

from functions import pbkdf2
import config

################################################################################

app = Flask( __name__ )
app.config.from_pyfile( 'config.py' )

Compress( app )
Session( app )

debug = os.environ.get( "DEBUG", False )
baseurl = os.environ.get( "BASEURL", "" )

################################################################################
#    Generic routing

@app.route( baseurl + '/ping' )
def ping():
    return "pong"

################################################################################
#    App serving

@app.route( baseurl + '/app/<path>' )
def send_app_files( path ):
    return send_from_directory( 'app', path )

################################################################################
#    Sessions

@app.before_request
def renew_session():
    session.permanent = True
    app.permanent_session_lifetime = timedelta( seconds = config.session_timeout )

@app.route( baseurl + '/logout' )
def logout():
    session.clear()
    return redirect( url_for( 'home' ) )

@app.route( baseurl + '/login' )
def login():
    session.clear()
    session[ 'stage' ] = 'password'
    
    return render_template( 
        "login.html",
        baseurl = baseurl,
        js = config.cdnjs,
        css = config.cdncss
    )

@app.route( baseurl + '/do_login', methods = [ 'POST' ] )
def do_login():
    if session[ 'stage' ] == 'password' or not 'stage' in session:
        q = config.db.query( 'SELECT * FROM users WHERE username = %s', ( request.form.get( "username" ), ) )
        user = q.fetchone()
        
        if user == None:
            return jsonify( {
                'error': False,
                'logged': False
            } )
        
        form_password = request.form.get( "password", None )
        
        if form_password == None or not pbkdf2( form_password, user[ 'password' ] ):
            return jsonify( {
                'error': False,
                'logged': False,
            } )
        
        elif not user[ 'active' ]:
            return jsonify( {
                'error': False,
                'logged': False,
                'message': 'Your account is not activated. Please contact an administrator.'
            } )
        
        else:
            session[ 'session_id' ] = str( uuid4() )
            session[ 'username' ] = user[ 'username' ]
            session[ 'password_check' ] = 'ok'
        
        if user[ 'must_use_totp' ]:
            session[ 'stage' ] = 'totp'
            
            return jsonify( {
                'error': False,
                'must_use_totp': True
            } )
        else:
            session[ 'logged' ] = True
    
    elif session[ 'stage' ] == 'totp':
        q = config.db.query( 'SELECT username, totp FROM users WHERE username = %s', ( session[ 'username' ], ) )
        user = q.fetchone()
        
        if not pyotp.TOTP( user[ 'totp' ] ).verify( request.form[ "totp" ], valid_window = 1 ):
            return jsonify( {
                'error': False,
                'logged': False,
                'message': 'Wrong TOTP'
            } )
        
        else:
            session[ 'logged' ] = True
    
    ############################################################################
    
    if session.get( 'logged', False ) and session.get( 'username', False ):
        return jsonify( {
            'error': False,
            'logged': True,
        } )
    
    else:
        session.clear()
        return jsonify( {
            'error': False,
            'logged': False,
        } )

################################################################################
#    Home page

@app.route( baseurl + '/' )
def home():
    if not session.get( "logged", False ):
        return redirect( url_for( 'login' ) )
    
    else:
        return render_template( 
            "index.html",
            baseurl = baseurl,
            js = config.cdnjs,
            css = config.cdncss,
            session_timeout = config.session_timeout
        )

################################################################################
#    Main startup

if __name__ == '__main__':
    app.run( debug = debug, host = "0.0.0.0", threaded = True )