# -*- coding: utf-8 -*-
"""
"""
import os
import markdown2
from flask import (Blueprint,
                   request,
                   render_template,
                   flash, g,
                   session,
                   redirect,
                   url_for,
                   abort,
                   Markup)
from werkzeug import check_password_hash, generate_password_hash
from logzero import logger
from base import db, app
from base import search as search_module  # don't override function name
from base.users.forms import RegisterForm, LoginForm
from base.users.models import User
from base.threads.models import Thread, Publication
from base.subreddits.models import Subreddit
from base.users.decorators import requires_login
from base.utils.user_utils import get_school
from base.subreddits.forms import subreddit_subs, sub_form
from base.utils.email import send_email
from base.utils.misc import random_string, validate_sort_type

mod = Blueprint('frontends', __name__, url_prefix='')


@mod.before_request
def before_request():
    g.user = None
    if session.get('user_id'):
        g.user = User.query.get(session['user_id'])


def home_subreddit():
    logger.info(g.user)
    if g.get('user'):
        subreddit_subs = g.user.subreddit_subs.get('subs')
        subs = Thread.query.order_by(db.desc(Thread.hotness), db.desc(Thread.hotness)) \
                           .filter(Subreddit.name.in_(subreddit_subs))
    else:
        subs = Thread.query.order_by(db.desc(Thread.hotness), db.desc(Thread.hotness))
    return subs


def get_subreddits():
    """
    Fetch user subreddits otherwise fetch a list of defaults
    """
    if g.get('user'):
        subreddit_subs = g.user.subreddit_subs.get('subs')
        subreddits = Subreddit.query.filter(Subreddit.name.in_(subreddit_subs))
    else:
        # Default set of subreddits
        subreddits = Subreddit.query.all()
    return subreddits


def process_thread_paginator(trending=False, rs=None, subreddit=None, sort_type='hot'):
    """
    abstracted because many sources pull from a thread listing
    source (subreddit permalink, homepage, etc)
    """
    threads_per_page = 15
    cur_page = request.args.get('page') or 1
    cur_page = int(cur_page)
    thread_paginator = None

    # if we are passing in a resultset, that means we are just looking to
    # quickly paginate some arbitrary data, no sorting
    if rs:
        thread_paginator = rs.paginate(cur_page,
                                       per_page=threads_per_page,
                                       error_out=True)
        return thread_paginator

    # sexy line of code :)
    base_query = subreddit.threads if subreddit else Thread.query

    # Filter by user subs
    logger.info(g.user)
    if g.user:
        subreddit_subs = g.user.subreddit_subs.get('subs')
        base_query = base_query.join(Subreddit).filter(Subreddit.name.in_(subreddit_subs))

    # Sorting
    if sort_type == 'hot':
        base_query = base_query.order_by(db.desc(Thread.hotness))
    elif sort_type == 'top':
        base_query = base_query.order_by(db.desc(Thread.votes))
    elif sort_type == 'comments':
        base_query = base_query.order_by(db.desc(Thread.n_comments))
    elif sort_type == 'new':
        base_query = base_query.order_by(db.desc(Thread.created_on))
    elif sort_type == 'publication_date':
        base_query = base_query.join(Publication).order_by(db.desc(Publication.pub_date))

    thread_paginator = base_query.paginate(cur_page, per_page=threads_per_page, error_out=True)

    return thread_paginator


@mod.route('/')
def home(sort_type='hot'):
    """
    If not trending we order by creation date
    """
    atom_url = url_for('subreddits.atom_feed', subreddit_name='frontpage', _external=True)
    trending = True if request.path.endswith('trending') else False
    page_title = "Trending" if trending else "Frontpage"
    thread_paginator = process_thread_paginator(trending=trending)

    return render_template('home.html',
                           atom_url=atom_url,
                           page_title=page_title,
                           cur_subreddit=home_subreddit(),
                           thread_paginator=thread_paginator)


@mod.route('/.atom')
@mod.route('/.xml')
@mod.route('/.rss')
def atom_redirect():
    return redirect(url_for("subreddits.atom_feed", subreddit_name="frontpage"))


@mod.route('/h/<string:page>')
def render_markdown(page):
    page_md = f"base/markdown/{page}.md"
    if not os.path.exists(page_md):
        abort(404)
    with open(page_md, 'r') as f:
        content = f.read()
        md = markdown2.markdown(content,
                                extras = ['fenced-code-blocks',
                                          'nofollow',
                                          'target-blank-links',
                                          'toc',
                                          'tables',
                                          'footnotes',
                                          'metadata',
                                          'markdown-in-html'])
    return render_template('markdown.html',
                           page=md,
                           **md.metadata)


@mod.route('/search/', methods=['GET'])
def search():
    """
    Allows users to search threads and comments
    """
    query = request.args.get('query')
    page_title=f"Search results for '{query}'"
    rs = search_module.search(query, orderby='creation', search_title=True,
            search_text=True)

    thread_paginator = process_thread_paginator(rs=rs)
    #rs = rs.all()
    num_searches = rs.count()
    subreddits = get_subreddits()

    return render_template('home.html',
                            page_title=page_title,
                            cur_subreddit=home_subreddit(),
                            thread_paginator=thread_paginator,
                            num_searches=num_searches)


@mod.route('/login/', methods=['GET', 'POST'])
def login():
    """
    We had to do some extra work to route the user back to
    his or her original place before logging in
    """
    if g.user:
        return redirect(url_for('frontends.home'))

    next = ''
    if request.method == 'GET':
        if 'next' in request.args:
            next = request.args['next']

    form = LoginForm(request.form)
    # make sure data is valid, but doesn't validate password is right
    if form.validate_on_submit():
        # continue where we left off if so
        user = User.query.filter_by(email=form.email.data).first()
        # we use werzeug to validate user's password
        if user and check_password_hash(user.password, form.password.data):
            # the session can't be modified as it's signed,
            # it's a safe place to store the user id
            session['user_id'] = user.id

            if 'next' in request.form and request.form['next']:
                return redirect(request.form['next'])
            return redirect(url_for('frontends.home'))

        flash('Wrong email or password', 'danger')
    return render_template("login.html", form=form, next=next)


@mod.route('/logout/', methods=['GET', 'POST'])
@requires_login
def logout():
    session.pop('user_id', None)
    return redirect(url_for('frontends.home'))


@mod.route('/confirm-email/<string:token>')
def confirm_email(token):
    """
        Confirm user email
    """
    user = User.query.filter_by(email_token=token).first()
    if user.email_token == token:
        user.email_verified = True
    db.session.commit()
    flash("Thank you for confirming your email! You can now submit and comment.", 'success')
    return redirect(url_for('frontends.home'))


@mod.route('/register/', methods=['GET', 'POST'])
def register():
    """
        Registration page
    """
    if g.user:
        # If the user is logged in send them home
        return redirect(url_for('frontends.home'))

    next = ''
    if request.method == 'GET':
        if 'next' in request.args:
            next = request.args['next']

    form = RegisterForm(request.form)
    if form.validate_on_submit():
        # create an user instance not yet stored in the database
        user = User(username=form.username.data,
                    email=form.email.data, \
                    password=generate_password_hash(form.password.data),
                    university=get_school(form.email.data),
                    email_token=random_string())
        # Insert the record in our database and commit it
        db.session.add(user)
        email_confirm_link = url_for('frontends.confirm_email', token = user.email_token)
        email_response = send_email("Confirm upvote.pub email",
                                    """Please visit the link below to confirm your email:\n\n{}{}""".format(request.url_root.strip("/"), email_confirm_link),
                                    user.email)
        # Log the user in, as he now has an id
        db.session.commit()
        session['user_id'] = user.id
        flash('Thanks for signing up! Please confirm your email by following the link sent in the confirmation email.', 'success')
        if 'next' in request.form and request.form['next']:
            return redirect(request.form['next'])
        return redirect(url_for('frontends.home'))

    return render_template("register.html", form=form, next=next)


@mod.route('/subs/', methods=['GET', 'POST'])
def view_all():
    """
    """
    subreddit_list = Subreddit.query.all()
    form = None
    if g.user:
        if request.form:
            form = subreddit_subs(request.form)
            if form.validate_on_submit():
                form_subs = form.data.get('subs')
                form_subs = list(set([x['sub_name'] for x in form_subs if x['value']]))
                g.user.subreddit_subs = {'subs': form_subs}
                flash("Updated Subs", 'success')
                db.session.commit()
        else:
            form = subreddit_subs()
            for subreddit in subreddit_list:
                sform = sub_form()
                sform.sub_name = subreddit.name
                sform.sub_group = subreddit.group
                if g.user:
                    sform.value=subreddit.name in g.user.subreddit_subs['subs']
                form.subs.append_entry(sform)


    return render_template('subreddits/subs.html',
                           cur_subreddit=None,
                           page_title='subs',
                           form=form,
                           subreddit_list=subreddit_list)

[(29, 'flask.Blueprint', 'Blueprint', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (35, 'flask.session.get', 'session.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (40, 'logzero.logger.info', 'logger.info', False, 'from logzero import logger\n'), (41, 'flask.g.get', 'g.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (54, 'flask.g.get', 'g.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (85, 'logzero.logger.info', 'logger.info', False, 'from logzero import logger\n'), (112, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (147, 'flask.render_template', 'render_template', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (157, 'flask.request.args.get', 'request.args.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (159, 'base.search.search', 'search_module.search', True, 'from base import search as search_module\n'), (188, 'base.users.forms.LoginForm', 'LoginForm', False, 'from base.users.forms import RegisterForm, LoginForm\n'), (204, 'flask.render_template', 'render_template', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (210, 'flask.session.pop', 'session.pop', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (222, 'base.db.session.commit', 'db.session.commit', False, 'from base import db, app\n'), (223, 'flask.flash', 'flash', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (241, 'base.users.forms.RegisterForm', 'RegisterForm', False, 'from base.users.forms import RegisterForm, LoginForm\n'), (263, 'flask.render_template', 'render_template', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (270, 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', False, 'from base.subreddits.models import Subreddit\n'), (292, 'flask.render_template', 'render_template', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (36, 'base.users.models.User.query.get', 'User.query.get', False, 'from base.users.models import User\n'), (42, 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (55, 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (59, 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', False, 'from base.subreddits.models import Subreddit\n'), (69, 'flask.request.args.get', 'request.args.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (87, 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (113, 'flask.request.path.endswith', 'request.path.endswith', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (128, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (134, 'os.path.exists', 'os.path.exists', False, 'import os\n'), (135, 'flask.abort', 'abort', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (138, 'markdown2.markdown', 'markdown2.markdown', False, 'import markdown2\n'), (203, 'flask.flash', 'flash', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (211, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (224, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (250, 'base.db.session.add', 'db.session.add', False, 'from base import db, app\n'), (251, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (256, 'base.db.session.commit', 'db.session.commit', False, 'from base import db, app\n'), (258, 'flask.flash', 'flash', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (44, 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', False, 'from base.subreddits.models import Subreddit\n'), (46, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (46, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (56, 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', False, 'from base.subreddits.models import Subreddit\n'), (88, 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', False, 'from base.subreddits.models import Subreddit\n'), (92, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (181, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (194, 'werkzeug.check_password_hash', 'check_password_hash', False, 'from werkzeug import check_password_hash, generate_password_hash\n'), (219, 'base.users.models.User.query.filter_by', 'User.query.filter_by', False, 'from base.users.models import User\n'), (234, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (260, 'flask.redirect', 'redirect', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (261, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (94, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (192, 'base.users.models.User.query.filter_by', 'User.query.filter_by', False, 'from base.users.models import User\n'), (200, 'flask.redirect', 'redirect', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (201, 'flask.url_for', 'url_for', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (246, 'werkzeug.generate_password_hash', 'generate_password_hash', False, 'from werkzeug import check_password_hash, generate_password_hash\n'), (247, 'base.utils.user_utils.get_school', 'get_school', False, 'from base.utils.user_utils import get_school\n'), (248, 'base.utils.misc.random_string', 'random_string', False, 'from base.utils.misc import random_string, validate_sort_type\n'), (253, 'flask.request.url_root.strip', 'request.url_root.strip', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (279, 'flask.flash', 'flash', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), (280, 'base.db.session.commit', 'db.session.commit', False, 'from base import db, app\n'), (284, 'base.subreddits.forms.sub_form', 'sub_form', False, 'from base.subreddits.forms import subreddit_subs, sub_form\n'), (43, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (43, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (96, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (98, 'base.db.desc', 'db.desc', False, 'from base import db, app\n'), (100, 'base.db.desc', 'db.desc', False, 'from base import db, app\n')]