import flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_httpauth import HTTPBasicAuth
from markupsafe import escape, Markup
from flask_migrate import Migrate
from jinja2_fragments.flask import render_block
import config
import markdown


app = flask.Flask(__name__)
bcrypt = Bcrypt(app)


app.config["SQLALCHEMY_DATABASE_URI"] = config.DB_URI
app.config["SECRET_KEY"] = config.DB_PASSWORD


db = SQLAlchemy(app)
migrate = Migrate(app, db)


@app.template_filter("split")
def split(value, separator=None, maxsplit=-1):
    return value.split(separator, maxsplit)


with app.app_context():
    class User(db.Model):
        username = db.Column(db.String(32), unique=True, nullable=False, primary_key=True)
        password_hashed = db.Column(db.String(60), nullable=False)

        def __init__(self, username, real_name, password):
            self.username = username
            self.real_name = real_name
            self.password_hashed = bcrypt.generate_password_hash(password).decode("utf-8")


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


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


@app.route("/login", methods=["POST"])
def login():
    username = flask.request.form["username"]
    password = flask.request.form["password"]

    user = db.session.get(User, username)

    if user is None:
        flask.flash("This username is not registered.")
        return flask.redirect("/accounts")

    if not bcrypt.check_password_hash(user.password_hashed, password):
        flask.flash("Incorrect password.")
        return flask.redirect("/accounts")

    flask.flash("You have been logged in.")

    flask.session["username"] = username
    return flask.redirect("/")


@app.route("/logout")
def logout():
    flask.session.pop("username", None)
    flask.flash("You have been logged out.")
    return flask.redirect("/")


@app.route("/signup", methods=["POST"])
def signup():
    username = flask.request.form["username"]
    password = flask.request.form["password"]

    if db.session.get(User, username) is not None:
        flask.flash("This username is already taken.")
        return flask.redirect("/accounts")

    if set(username) > set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"):
        flask.flash("Usernames can only contain the Latin alphabet, digits, hyphens, and underscores.")
        return flask.redirect("/accounts")

    if len(username) < 3 or len(username) > 32:
        flask.flash("Usernames must be between 3 and 32 characters long.")
        return flask.redirect("/accounts")

    if len(password) < 6:
        flask.flash("Passwords must be at least 6 characters long.")
        return flask.redirect("/accounts")

    user = User(username, None, password)
    db.session.add(user)
    db.session.commit()

    flask.session["username"] = username

    flask.flash("You have been registered and logged in.")

    return flask.redirect("/")


@app.route("/profile", defaults={"username": None})
@app.route("/profile/<username>")
def profile(username):
    if username is None:
        if "username" in flask.session:
            return flask.redirect("/profile/" + flask.session["username"])
        else:
            flask.flash("Please log in to perform this action.")
            return flask.redirect("/accounts")

    user = db.session.get(User, username)
    if user is None:
        return flask.abort(404)

    return flask.render_template("profile.html", user=user)
