# coding=utf-8
from os.path import join, dirname

from flask import (render_template, redirect, flash, url_for, request,
                   g, make_response, jsonify, current_app)
from flask_babel import gettext as _
from werkzeug.exceptions import NotFound, InternalServerError
from sqlalchemy import func
from abilian.core.models.subjects import User, Group
from abilian.core.extensions import db
from abilian.web import csrf
from abilian.web.views import default_view
from abilian.services.image import resize, CROP
from abilian.services.security import security

from ..forms import GroupForm
from .social import social
from .util import Env


DEFAULT_GROUP_MUGSHOT = open(join(dirname(__file__),
                                 "../../../static/images/frog.jpg")).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(lambda x, y: cmp(x.name, y.name))
  return render_template("social/groups.html", **e)


def is_admin(group):
  is_admin = g.user in group.admins
  if not is_admin and 'security' in current_app.extensions:
    is_admin = current_app.services['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", u'').lower()
  if q:
    members = filter(
      lambda u: any([term.startswith(q)
                    for name in (u.first_name.lower(), u.last_name.lower())
                    for term in name.split()]),
      members)

  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', u'').strip()
    try:
      user_id = int(user_id)
    except:
      flash(_(u'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)


# TODO: duplicated code (with user_mugshot). Extract common method.
@social.route("/groups/<int:group_id>/mugshot")
def group_mugshot(group_id):
  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)
