# coding=utf-8
from __future__ import absolute_import, print_function, unicode_literals

from os.path import dirname, join

from flask import current_app, flash, g, jsonify, make_response, redirect, \
    render_template, request, url_for
from flask_babel import gettext as _
from sqlalchemy import func
from werkzeug.exceptions import InternalServerError, NotFound

from abilian.core.extensions import db
from abilian.core.models.subjects import Group, User
from abilian.services import get_service
from abilian.services.image import CROP, resize
from abilian.services.security import security
from abilian.web import csrf
from abilian.web.views import default_view

from .social import social
from .util import Env

DEFAULT_GROUP_MUGSHOT = open(
    join(dirname(__file__), "../../../static/images/frog.jpg"), 'rb').read()


@social.route("/groups/")
def groups():
    tab = request.args.get("tab", "all_groups")
    e = Env()
    if tab == 'all_groups':
        e.groups = Group.query.order_by(Group.name).all()
        if not security.has_role(g.user, "admin"):
            e.groups = [
                group for group in e.groups
                if group.public or g.user in group.members
            ]
    else:
        e.groups = g.user.groups
        e.groups.sort(key=lambda x: x.name)
    return render_template("social/groups.html", **e)


def is_admin(group):
    security = get_service('security')
    is_admin = g.user in group.admins
    if not is_admin and 'security' in current_app.extensions:
        is_admin = security.has_role(g.user, 'admin')

    return is_admin


@social.route("/groups/<int:group_id>")
@default_view(social, Group, 'group_id')
def group_home(group_id):
    e = Env(csrf_token=csrf.field())
    e.group = Group.query.get(group_id)
    e.is_admin = is_admin(e.group)
    return render_template("social/group.html", **e)


@social.route("/groups/<int:group_id>/json")
def group_json(group_id):
    members = Group.query.get(group_id).members
    q = request.args.get("q", '').lower()
    if q:
        members = [
            u for u in members
            if any(
                term.startswith(q) for name in (u.first_name.lower(
                ), u.last_name.lower()) for term in name.split())
        ]

    result = {'results': [{'id': obj.id, 'text': obj.name} for obj in members]}
    return jsonify(result)


@social.route("/groups/<int:group_id>", methods=['POST'])
@csrf.protect
def group_post(group_id):
    group = Group.query.get(group_id)
    action = request.form.get('action')
    return_url = request.form.get('return_url')

    membership_actions = frozenset((
        'add',
        'remove',
        'add-admin',
        'remove-admin',
    ))

    if action not in ('join', 'leave'):
        assert is_admin(group)

    if action == 'join':
        g.user.join(group)
    elif action == 'leave':
        g.user.leave(group)
    elif action in membership_actions:
        user_id = request.form.get('user', '').strip()
        try:
            user_id = int(user_id)
        except:
            flash(_('Error: No user selected'), 'error')
            return redirect(url_for(".group_home", group_id=group_id))

        user = User.query.get(user_id)

        if action == 'add':
            user.join(group)
        elif action == 'remove':
            user.leave(group)
        elif action == 'add-admin':
            if user not in group.admins:
                group.admins.append(user)
        elif action == 'remove-admin':
            if user in group.admins:
                group.admins.remove(user)
    else:
        raise Exception("Should not happen")
    db.session.commit()

    if return_url:
        # TODO: security check
        return redirect(return_url)
    else:
        return redirect(url_for(".group_home", group_id=group_id))


@social.route("/groups/new")
def groups_new():
    # TODO later
    return

    # e = Env()
    # e.form = GroupForm()
    # return render_template("social/groups-new.html", **e)


@social.route("/groups/new", methods=['POST'])
def groups_new_post():
    # TODO later
    return

    # form = GroupForm()
    #
    # if form.validate():
    #     group = Group()
    #     form.populate_obj(group)
    #     db.session.add(group)
    #     db.session.commit()
    #     flash(_(u"Your new group has been created"), category='info')
    #     return redirect(url_for('.group_home', group_id=group.id))
    #
    # else:
    #     e = Env()
    #     e.form = form
    #     return render_template("social/groups-new.html", **e)


@social.route("/groups/<int:group_id>/mugshot")
def group_mugshot(group_id):
    # TODO: duplicated code (with user_mugshot). Extract common method.
    size = int(request.args.get('s', 55))
    if size > 500:
        raise ValueError("Error, size = %d" % size)
    group = Group.query.get(group_id)

    if not group:
        raise NotFound()

    if group.photo:
        data = group.photo
    else:
        data = DEFAULT_GROUP_MUGSHOT

    if size:
        data = resize(data, size, size, mode=CROP)

    response = make_response(data)
    response.headers['content-type'] = 'image/jpeg'
    response.headers.add('Cache-Control', 'public, max-age=600')
    return response


#
# Ad-hoc JSON endpoints, used by select boxes
#
@social.route("/groups/json")
def groups_json():
    q = request.args.get("q").replace("%", " ").lower()

    if not q or len(q) < 2:
        raise InternalServerError()

    query = Group.query
    # query = query.filter(func.lower(Group.name).like(q + "%"))
    query = query.order_by(func.lower(Group.name))
    all = query.all()

    result = {'results': [{'id': obj.id, 'text': obj.name} for obj in all]}
    return jsonify(result)
