# Calendar.social
# Copyright (C) 2018 Gergely Polonkai
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see .
"""Main module for the Calendar.social app
"""
from flask import Blueprint, abort, current_app, redirect, render_template, url_for
from flask_security import current_user, login_required
from sqlalchemy.orm.exc import NoResultFound
from calsocial.utils import RoutedMixin
class AccountBlueprint(Blueprint, RoutedMixin):
    """Blueprint for account management
    """
    def __init__(self):
        Blueprint.__init__(self, 'account', __name__)
        self.app = None
        RoutedMixin.register_routes(self)
    def init_app(self, app, url_prefix=None):
        """Initialise the blueprint, registering it with ``app``.
        """
        self.app = app
        app.register_blueprint(self, url_prefix=url_prefix)
    @staticmethod
    @RoutedMixin.route('/register')
    def register_account():
        """View for user registration
        If the ``REGISTRATION_FAILED`` configuration value is set to ``True`` it displays the
        registration disabled template.  Otherwise, it performs user registration.
        """
        if not current_app.config['REGISTRATION_ENABLED']:
            return render_template('registration-disabled.html')
        from .forms import RegistrationForm
        from .models import db, User
        form = RegistrationForm()
        if form.validate_on_submit():
            # TODO: This might become False later, if we want registrations to be confirmed via
            #       e-mail
            user = User(active=True)
            form.populate_obj(user)
            db.session.add(user)
            db.session.commit()
            return redirect(url_for('hello'))
        return render_template('account/registration.html', form=form)
    @staticmethod
    @RoutedMixin.route('/settings', methods=['GET', 'POST'])
    @login_required
    def settings():
        """View for user settings
        """
        from .forms import SettingsForm
        from .models import db
        form = SettingsForm(current_user)
        if form.validate_on_submit():
            form.populate_obj(current_user)
            db.session.commit()
            return redirect(url_for('hello'))
        return render_template('account/user-settings.html', form=form)
    @staticmethod
    @RoutedMixin.route('/notifications')
    def notifications():
        """View to list the notifications for the current user
        """
        from .models import Notification
        if current_user.is_authenticated:
            notifs = Notification.query.filter(Notification.profile == current_user.profile)
        else:
            notifs = []
        return render_template('account/notifications.html', notifs=notifs)
    @staticmethod
    @RoutedMixin.route('/first-steps', methods=['GET', 'POST'])
    @login_required
    def first_steps():
        """View to set up a new registrant’s profile
        """
        from .forms import FirstStepsForm
        from .models import db, Profile
        if current_user.profile:
            return redirect(url_for('hello'))
        form = FirstStepsForm()
        if form.validate_on_submit():
            profile = Profile(user=current_user, display_name=form.display_name.data)
            db.session.add(profile)
            current_user.settings['timezone'] = str(form.time_zone.data)
            db.session.commit()
            return redirect(url_for('hello'))
        return render_template('account/first-steps.html', form=form)
    @staticmethod
    @RoutedMixin.route('/edit-profile', methods=['GET', 'POST'])
    @login_required
    def edit_profile():
        """View for editing one’s profile
        """
        from .forms import ProfileForm
        from .models import db
        form = ProfileForm(current_user.profile)
        if form.validate_on_submit():
            form.populate_obj(current_user.profile)
            db.session.add(current_user.profile)
            db.session.commit()
            return redirect(url_for('account.edit_profile'))
        return render_template('account/profile-edit.html', form=form)
    @staticmethod
    @RoutedMixin.route('/follow-requests')
    @login_required
    def follow_requests():
        """View for listing follow requests
        """
        from .models import UserFollow
        requests = UserFollow.query \
                             .filter(UserFollow.followed == current_user.profile) \
                             .filter(UserFollow.accepted_at.is_(None))
        return render_template('account/follow-requests.html', requests=requests)
    @staticmethod
    @RoutedMixin.route('/follow-request//accept')
    @login_required
    def accept_follow(follower_id):
        """View for accepting a follow request
        """
        from .models import db, UserFollow
        try:
            req = UserFollow.query \
                            .filter(UserFollow.followed == current_user.profile) \
                            .filter(UserFollow.follower_id == follower_id) \
                            .one()
        except NoResultFound:
            abort(404)
        if req.accepted_at is None:
            req.accept()
            db.session.add(req)
            db.session.commit()
        return redirect(url_for('account.follow_requests'))