# Copyright 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Info about the users

This requires Django 0.97.pre.
"""

import datetime
import logging

from django import forms
from django import http
from django.utils import simplejson

import models
import views
import fields
from view_util import *

def respond_json(obj):
  data = simplejson.dumps(obj)
  return http.HttpResponse(data,
      mimetype="text/javascript; charset=utf-8")

def get_user_info(request):
  """check if the requested user exists
  
  Parameters:
    id: the user's email address or the group name
    allow_users: whether users are allowed, true by default
    allow_groups: whether groups are allowed, true by default

  Result:
  If user/group not found:
    null
  If user found: map of
    type: "user"
    key: a unique key for this user
    email: their email address
    real_name: the user's real name
  If group found: map of
    type: "group"
    key: a unique key for this group
    name: the name of the group

  If users or groups are not allowed, then null will be returned
  even if there does happen to be a user or group with that name
  """
  id = request.REQUEST.get("id", None)
  if not id:
    return http.HttpResponseServerError("id not provided")
  allow_users = request.REQUEST.get("allow_users", "true")
  allow_groups = request.REQUEST.get("allow_groups", "true")
  if allow_users != "false":
    account = models.Account.get_account_for_email(id)
    if account:
      return respond_json({
          'allow_users': allow_users,
          'allow_groups': allow_groups,
          'type': 'user',
          'key': "user/" + account.email,
          'email': account.email,
          'real_name': account.real_name,
          })
  if allow_groups != "false":
    group = models.AccountGroup.get_group_for_name(id)
    if group:
      return respond_json({
          'allow_users': allow_users,
          'allow_groups': allow_groups,
          'type': 'group',
          'key': "group/" + str(group.key()),
          'name': group.name,
          })
  return respond_json(None)

@admin_required
def admin_people_info(request):
  """/admin/people_info"""
  op = request.REQUEST.get("op", None)
  if op == "get_user_info":
    return get_user_info(request);
  return http.HttpResponseServerError("op=" + str(op))

@admin_required
def admin_users(request):
  """/admin/users - list of all users"""
  accounts = models.Account.get_all_accounts()
  return respond(request, 'admin_users.html', {'users': accounts})

@admin_required
def admin_users_verify_cla(request):
  """/admin/users - list of all users"""
  accounts = models.Account.gql('WHERE welcomed=True '
                              + 'AND individual_cla_version != 0'
                              + 'AND cla_verified=False').fetch(1000)
  return respond(request, 'admin_users.html', {'users': accounts})


def _get_groups_for_account(account):
  return models.gql(models.AccountGroup,
                    'WHERE members = :1',
                    account.user).fetch(models.FETCH_MAX)

def _set_groups_for_account(account, groups):
  u = account.user
  existing = _get_groups_for_account(account)
  # remove from the ones that don't have it any more
  group_keys = [g.key() for g in groups]
  for g in existing:
    if g.key() not in group_keys:
      g.members.remove(u)
      g.put()
  # add to the ones that didn't have it before
  existing_keys = [g.key() for g in existing]
  for g in groups:
    if g.key() not in existing_keys:
      g.members.append(u)
      g.put()
  
class AdminUserForm(BaseForm):
  _template = 'admin_user.html'

  dest = forms.fields.CharField(widget=forms.widgets.HiddenInput)

  # user info
  real_name = forms.CharField(max_length=60)
  preferred_email = forms.EmailField(required=False)
  mailing_address = forms.CharField(required=False,
                          max_length=150,
                          widget=forms.Textarea(attrs={'rows': 4, 'cols': 60}))
  mailing_address_country = forms.CharField(max_length=30, required=False)
  phone_number = forms.CharField(max_length=30, required=False)
  fax_number = forms.CharField(max_length=30, required=False)

  # groups
  groups = fields.UserGroupField(allow_users=False, allow_groups=True)

  # cla
  cla_verified = forms.fields.BooleanField(required=False)
  cla_comments = forms.CharField(required=False,
                          max_length=300,
                          widget=forms.Textarea(attrs={'rows': 6, 'cols': 60}))

  @classmethod
  def _init(cls, state):
    account = state['account']
    dest = state['dest']
    return {
        'initial': {
            'dest': dest,
            'real_name': account.real_name,
            'preferred_email': account.preferred_email,
            'mailing_address': account.mailing_address,
            'mailing_address_country': account.mailing_address_country,
            'phone_number': account.phone_number,
            'fax_number': account.fax_number,
            'groups': _get_groups_for_account(account),
            'cla_verified': account.cla_verified,
            'cla_verified_by': account.cla_verified_by,
            'cla_verified_timestamp': account.cla_verified_timestamp,
            'individual_cla_version': account.individual_cla_version,
            'individual_cla_timestamp': account.individual_cla_timestamp,
            'cla_comments': account.cla_comments,
          },
        }

  def _save(self, cd, state):
    account = state['account']
    account.real_name = cd['real_name'].strip()
    if cd['preferred_email']:
      account.preferred_email = cd['preferred_email']
    account.mailing_address = cd['mailing_address']
    account.mailing_address_country = cd['mailing_address_country']
    account.phone_number = cd['phone_number']
    account.fax_number = cd['fax_number']
    if account.cla_verified != cd['cla_verified']:
      account.cla_verified = cd['cla_verified']
      account.cla_verified_by = models.Account.current_user_account.user
    if cd['cla_verified'] and account.cla_verified_timestamp is None:
      account.cla_verified_timestamp = datetime.datetime.utcnow()
    account.cla_comments = cd['cla_comments']
    account.put()
    _set_groups_for_account(account, 
                            fields.UserGroupField.get_groups(cd['groups']))
    if self.is_valid():
      return HttpResponseRedirect(cd['dest'])


@admin_required
def admin_user(request, email):
  """/admin/user/email@address.com - edit this user"""
  account = models.Account.get_account_for_email(email)
  referrer = request.META.get('HTTP_REFERER', '/admin/users')
  state = {
      'account': account,
      'dest': referrer,
    }
  return process_form(request, AdminUserForm, state, None, {'email':email})
  
@admin_required
def admin_groups(request):
  """/admin/groups - list of all groups"""
  models.AccountGroup.create_groups()
  groups = models.AccountGroup.get_all_groups()
  return respond(request, 'admin_groups.html', {'groups': groups})

class AdminGroupForm(BaseForm):
  _template = 'admin_group.html'

  name = forms.CharField(max_length=30)
  comment = forms.CharField(required=False,
                            max_length=10000,
                            widget=forms.Textarea(attrs={'cols': 60}))
  members = fields.UserGroupField(allow_users=True, allow_groups=False)

  @classmethod
  def _init(cls, group):
     who = group.members
     who = fields.UserGroupField.field_value_for_keys(users = who)
     return {'initial': {'name': group.name,
             'comment': group.comment,
             'members': who
            }}

  def _save(self, cd, group):
    new_name = cd['name'].strip()
    if group.is_auto_group and group.name != new_name:
      self.errors['name'] = ['Name can not be changed']

    # TODO(joeo): Big race condition here.
    #
    in_use = models.AccountGroup.get_group_for_name(new_name)
    if in_use and group.key() != in_use.key():
      self.errors['name'] = ['Name is already in use']

    if self.is_valid():
      group.name = new_name
      group.comment = cd['comment']
      group.members = fields.UserGroupField.get_users(cd['members'])
      group.put()

@admin_required
def admin_group(request, name):
  """/admin/group/group - edit this group"""
  group = models.AccountGroup.get_group_for_name(name)
  def done():
    return HttpResponseRedirect('/admin/groups')
  return process_form(request, AdminGroupForm, group, done,
                      {'group': group,
                       'del_url': '/admin/group_delete/%s' % group.name,
                      })
  
class AdminNewGroupForm(AdminGroupForm):
  @classmethod
  def _init(cls, group):
     return {'initial': {'name': '', 'comment': ''}}

  def _save(self, cd, group):
    new_name = cd['name'].strip()

    # TODO(joeo): Big race condition here.
    #
    if models.AccountGroup.get_group_for_name(new_name):
      self.errors['name'] = ['Name is already in use']

    if self.is_valid():
      who = fields.UserGroupField.get_users(cd['members'])
      group = models.AccountGroup(name = new_name,
                                  comment = cd['comment'],
                                  members = who)
      group.put()

@admin_required
def admin_group_new(request):
  """/admin/group/GROUP - add a new group"""
  def done():
    return HttpResponseRedirect('/admin/groups')
  return process_form(request, AdminNewGroupForm, [], done)

@gae_admin_required
@xsrf_required
def admin_group_delete(request, name):
  """/admin/group_delete/GROUP - add a new group"""
  group = models.AccountGroup.get_group_for_name(name)
  assert group
  group.remove()
  return HttpResponseRedirect('/admin/groups')


