# -*- 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, 6, 29, 53), 'flask.Blueprint', 'Blueprint', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((35, 7, 35, 29), 'flask.session.get', 'session.get', ({(35, 19, 35, 28): '"""user_id"""'}, {}), "('user_id')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((40, 4, 40, 23), 'logzero.logger.info', 'logger.info', ({(40, 16, 40, 22): 'g.user'}, {}), '(g.user)', False, 'from logzero import logger\n'), ((41, 7, 41, 20), 'flask.g.get', 'g.get', ({(41, 13, 41, 19): '"""user"""'}, {}), "('user')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((54, 7, 54, 20), 'flask.g.get', 'g.get', ({(54, 13, 54, 19): '"""user"""'}, {}), "('user')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((85, 4, 85, 23), 'logzero.logger.info', 'logger.info', ({(85, 16, 85, 22): 'g.user'}, {}), '(g.user)', False, 'from logzero import logger\n'), ((112, 15, 112, 90), 'flask.url_for', 'url_for', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((147, 11, 149, 41), 'flask.render_template', 'render_template', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((157, 12, 157, 37), 'flask.request.args.get', 'request.args.get', ({(157, 29, 157, 36): '"""query"""'}, {}), "('query')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((159, 9, 160, 29), 'base.search.search', 'search_module.search', (), '', True, 'from base import search as search_module\n'), ((188, 11, 188, 34), 'base.users.forms.LoginForm', 'LoginForm', ({(188, 21, 188, 33): 'request.form'}, {}), '(request.form)', False, 'from base.users.forms import RegisterForm, LoginForm\n'), ((204, 11, 204, 62), 'flask.render_template', 'render_template', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((210, 4, 210, 32), 'flask.session.pop', 'session.pop', ({(210, 16, 210, 25): '"""user_id"""', (210, 27, 210, 31): 'None'}, {}), "('user_id', None)", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((222, 4, 222, 23), 'base.db.session.commit', 'db.session.commit', ({}, {}), '()', False, 'from base import db, app\n'), ((223, 4, 223, 92), 'flask.flash', 'flash', ({(223, 10, 223, 80): '"""Thank you for confirming your email! You can now submit and comment."""', (223, 82, 223, 91): '"""success"""'}, {}), "('Thank you for confirming your email! You can now submit and comment.',\n    'success')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((241, 11, 241, 37), 'base.users.forms.RegisterForm', 'RegisterForm', ({(241, 24, 241, 36): 'request.form'}, {}), '(request.form)', False, 'from base.users.forms import RegisterForm, LoginForm\n'), ((263, 11, 263, 65), 'flask.render_template', 'render_template', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((270, 21, 270, 42), 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', ({}, {}), '()', False, 'from base.subreddits.models import Subreddit\n'), ((292, 11, 296, 57), 'flask.render_template', 'render_template', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((36, 17, 36, 51), 'base.users.models.User.query.get', 'User.query.get', ({(36, 32, 36, 50): "session['user_id']"}, {}), "(session['user_id'])", False, 'from base.users.models import User\n'), ((42, 25, 42, 58), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', ({(42, 51, 42, 57): '"""subs"""'}, {}), "('subs')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((55, 25, 55, 58), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', ({(55, 51, 55, 57): '"""subs"""'}, {}), "('subs')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((59, 21, 59, 42), 'base.subreddits.models.Subreddit.query.all', 'Subreddit.query.all', ({}, {}), '()', False, 'from base.subreddits.models import Subreddit\n'), ((69, 15, 69, 39), 'flask.request.args.get', 'request.args.get', ({(69, 32, 69, 38): '"""page"""'}, {}), "('page')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((87, 25, 87, 58), 'flask.g.user.subreddit_subs.get', 'g.user.subreddit_subs.get', ({(87, 51, 87, 57): '"""subs"""'}, {}), "('subs')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((113, 23, 113, 56), 'flask.request.path.endswith', 'request.path.endswith', ({(113, 45, 113, 55): '"""trending"""'}, {}), "('trending')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((128, 20, 128, 79), 'flask.url_for', 'url_for', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((134, 11, 134, 34), 'os.path.exists', 'os.path.exists', ({(134, 26, 134, 33): 'page_md'}, {}), '(page_md)', False, 'import os\n'), ((135, 8, 135, 18), 'flask.abort', 'abort', ({(135, 14, 135, 17): '(404)'}, {}), '(404)', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((138, 13, 146, 62), 'markdown2.markdown', 'markdown2.markdown', (), '', False, 'import markdown2\n'), ((203, 8, 203, 50), 'flask.flash', 'flash', ({(203, 14, 203, 39): '"""Wrong email or password"""', (203, 41, 203, 49): '"""danger"""'}, {}), "('Wrong email or password', 'danger')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((211, 20, 211, 45), 'flask.url_for', 'url_for', ({(211, 28, 211, 44): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((224, 20, 224, 45), 'flask.url_for', 'url_for', ({(224, 28, 224, 44): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((250, 8, 250, 28), 'base.db.session.add', 'db.session.add', ({(250, 23, 250, 27): 'user'}, {}), '(user)', False, 'from base import db, app\n'), ((251, 29, 251, 89), 'flask.url_for', 'url_for', (), '', False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((256, 8, 256, 27), 'base.db.session.commit', 'db.session.commit', ({}, {}), '()', False, 'from base import db, app\n'), ((258, 8, 258, 130), 'flask.flash', 'flash', ({(258, 14, 258, 118): '"""Thanks for signing up! Please confirm your email by following the link sent in the confirmation email."""', (258, 120, 258, 129): '"""success"""'}, {}), "(\n    'Thanks for signing up! Please confirm your email by following the link sent in the confirmation email.'\n    , 'success')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((44, 35, 44, 69), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', ({(44, 54, 44, 68): 'subreddit_subs'}, {}), '(subreddit_subs)', False, 'from base.subreddits.models import Subreddit\n'), ((46, 37, 46, 60), 'base.db.desc', 'db.desc', ({(46, 45, 46, 59): 'Thread.hotness'}, {}), '(Thread.hotness)', False, 'from base import db, app\n'), ((46, 62, 46, 85), 'base.db.desc', 'db.desc', ({(46, 70, 46, 84): 'Thread.hotness'}, {}), '(Thread.hotness)', False, 'from base import db, app\n'), ((56, 44, 56, 78), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', ({(56, 63, 56, 77): 'subreddit_subs'}, {}), '(subreddit_subs)', False, 'from base.subreddits.models import Subreddit\n'), ((88, 55, 88, 89), 'base.subreddits.models.Subreddit.name.in_', 'Subreddit.name.in_', ({(88, 74, 88, 88): 'subreddit_subs'}, {}), '(subreddit_subs)', False, 'from base.subreddits.models import Subreddit\n'), ((92, 41, 92, 64), 'base.db.desc', 'db.desc', ({(92, 49, 92, 63): 'Thread.hotness'}, {}), '(Thread.hotness)', False, 'from base import db, app\n'), ((181, 24, 181, 49), 'flask.url_for', 'url_for', ({(181, 32, 181, 48): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((194, 20, 194, 74), 'werkzeug.check_password_hash', 'check_password_hash', ({(194, 40, 194, 53): 'user.password', (194, 55, 194, 73): 'form.password.data'}, {}), '(user.password, form.password.data)', False, 'from werkzeug import check_password_hash, generate_password_hash\n'), ((219, 11, 219, 50), 'base.users.models.User.query.filter_by', 'User.query.filter_by', (), '', False, 'from base.users.models import User\n'), ((234, 24, 234, 49), 'flask.url_for', 'url_for', ({(234, 32, 234, 48): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((260, 19, 260, 49), 'flask.redirect', 'redirect', ({(260, 28, 260, 48): "request.form['next']"}, {}), "(request.form['next'])", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((261, 24, 261, 49), 'flask.url_for', 'url_for', ({(261, 32, 261, 48): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((94, 41, 94, 62), 'base.db.desc', 'db.desc', ({(94, 49, 94, 61): 'Thread.votes'}, {}), '(Thread.votes)', False, 'from base import db, app\n'), ((192, 15, 192, 58), 'base.users.models.User.query.filter_by', 'User.query.filter_by', (), '', False, 'from base.users.models import User\n'), ((200, 23, 200, 53), 'flask.redirect', 'redirect', ({(200, 32, 200, 52): "request.form['next']"}, {}), "(request.form['next'])", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((201, 28, 201, 53), 'flask.url_for', 'url_for', ({(201, 36, 201, 52): '"""frontends.home"""'}, {}), "('frontends.home')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((246, 29, 246, 71), 'werkzeug.generate_password_hash', 'generate_password_hash', ({(246, 52, 246, 70): 'form.password.data'}, {}), '(form.password.data)', False, 'from werkzeug import check_password_hash, generate_password_hash\n'), ((247, 31, 247, 58), 'base.utils.user_utils.get_school', 'get_school', ({(247, 42, 247, 57): 'form.email.data'}, {}), '(form.email.data)', False, 'from base.utils.user_utils import get_school\n'), ((248, 32, 248, 47), 'base.utils.misc.random_string', 'random_string', ({}, {}), '()', False, 'from base.utils.misc import random_string, validate_sort_type\n'), ((253, 108, 253, 135), 'flask.request.url_root.strip', 'request.url_root.strip', ({(253, 131, 253, 134): '"""/"""'}, {}), "('/')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((279, 16, 279, 48), 'flask.flash', 'flash', ({(279, 22, 279, 36): '"""Updated Subs"""', (279, 38, 279, 47): '"""success"""'}, {}), "('Updated Subs', 'success')", False, 'from flask import Blueprint, request, render_template, flash, g, session, redirect, url_for, abort, Markup\n'), ((280, 16, 280, 35), 'base.db.session.commit', 'db.session.commit', ({}, {}), '()', False, 'from base import db, app\n'), ((284, 24, 284, 34), 'base.subreddits.forms.sub_form', 'sub_form', ({}, {}), '()', False, 'from base.subreddits.forms import subreddit_subs, sub_form\n'), ((43, 37, 43, 60), 'base.db.desc', 'db.desc', ({(43, 45, 43, 59): 'Thread.hotness'}, {}), '(Thread.hotness)', False, 'from base import db, app\n'), ((43, 62, 43, 85), 'base.db.desc', 'db.desc', ({(43, 70, 43, 84): 'Thread.hotness'}, {}), '(Thread.hotness)', False, 'from base import db, app\n'), ((96, 41, 96, 67), 'base.db.desc', 'db.desc', ({(96, 49, 96, 66): 'Thread.n_comments'}, {}), '(Thread.n_comments)', False, 'from base import db, app\n'), ((98, 41, 98, 67), 'base.db.desc', 'db.desc', ({(98, 49, 98, 66): 'Thread.created_on'}, {}), '(Thread.created_on)', False, 'from base import db, app\n'), ((100, 59, 100, 88), 'base.db.desc', 'db.desc', ({(100, 67, 100, 87): 'Publication.pub_date'}, {}), '(Publication.pub_date)', False, 'from base import db, app\n')]