import os
from whitenoise import WhiteNoise
from flask import (Flask, render_template, redirect, request, abort, url_for,
                   make_response)
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_wtf.csrf import CSRFProtect, generate_csrf

app = Flask(__name__)
app.wsgi_app = WhiteNoise(app.wsgi_app, root="static/")

CSRFProtect().init_app(app)

# Configurations
# Using environmental variables for secret key and database url
# Secret key is used to sign cookies, so it's secure to keep it hidden
app.config.update(
    SECRET_KEY=os.environ["SECRET_KEY"],
    SQLALCHEMY_DATABASE_URI=os.environ["DATABASE_URL"],
    SQLALCHEMY_TRACK_MODIFICATIONS=False,
)

db = SQLAlchemy(app)
bcrypt = Bcrypt(app)

# Must import after db is defined, not pretty
from models import User

@app.after_request
def add_csrf_to_cookie(response):
    return_response = make_response(response)
    if request.cookies.get("csrf_token") is not None:
        return_response.set_cookie("csrf_token", generate_csrf())
    return return_response

@app.route('/')
def index():
    return render_template("index.html")

# For testing purposes
@app.route('/users')
def users():
    return "<br>".join(map(lambda x: str(x), User.query.all()))

@app.route('/register')
def register():
    errormessage = request.args.get("errormessage", default="")
    return render_template("register.html", errormessage=errormessage)

@app.route('/register/submit', methods=["POST"])
def submit():
    username = request.form.get("username")
    name = request.form.get("name", default="")
    email = request.form.get("email")
    password = request.form.get("password")
    
    # Quick way to check if any of these is empty
    # Should implement javascript password checker to prevent this
    if "" in [username, email, password]:
        errormessage = "Username, email, and password are required."
        return redirect(url_for("register", errormessage=errormessage))
    
    new_user = User(username, email, name, password)
    db.session.add(new_user)
    db.session.commit()
    
    response = make_response(redirect(url_for("user")))
    response.set_cookie("username", username)
    
    return response

@app.route('/user')
def user():
    username = request.cookies.get("username")
    return render_template("user.html", username=username)

@app.route('/login')
def login():
    return render_template("login.html")

@app.route('/login/validate', methods=["POST"])
def validate():
    username = request.form.get("username")
    password = request.form.get("password")
    
    if "" in [username, password]:
        return redirect(url_for("login"))
    
    if validate_password(username, password):
        response = make_response(redirect(url_for("user")))
        response.set_cookie("username", username)
        return response
    else:
        return redirect(url_for("login"))
    
def validate_password(username, password):
    user = User.query.filter_by(username=username)[0]
    return user.check_password(password)

@@ -2096,38 +2096,24 @@
  response = 
-make_response(
 redirect(url
@@ -2129,80 +2129,65 @@
 r%22))
-)
+%0A    
 %0A    re
-sponse.set_cookie(%22username%22, username)%0A    %0A    return response
+turn add_logged_in_cookie(response, username)
 %0A%0A@a
@@ -2703,30 +2703,16 @@
 ponse = 
-make_response(
 redirect
@@ -2728,17 +2728,16 @@
 %22user%22))
-)
 %0A       
@@ -2743,71 +2743,53 @@
   re
-sponse.set_cookie(%22username%22, username)%0A        return response
+turn add_logged_in_cookie(response, username)
 %0A   
@@ -2972,16 +2972,299 @@
 sword(password)%0A
+%0Adef add_logged_in_cookie(response, username):%0A    return_response = make_response(response)%0A    expiry_date = datetime.datetime.now()%0A    expiry_date += datetime.timedelta(days=30)%0A    return_response.set_cookie(%22username%22, username, expires=expiry_date)%0A    return return_response%0A

Add expiry date to user logged in cookies