# 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.

"""Custom fields and widgets for Gerrit.

This requires Django 0.97.pre.
"""


### Imports ###

import string
import logging

import django.forms.widgets
import django.forms.fields
from django import forms
from django.utils import encoding
from django.utils import safestring
from django.forms import util
from django.utils import html
from django.utils import simplejson
from google.appengine.ext import db

import models

def person_to_dict(v):
  entry = {}
  if isinstance(v, models.Account):
    entry["type"] = "user"
    entry["key"] = "user/" + v.email
    entry["email"] = v.email
    entry["real_name"] = v.real_name
    entry["sort_key"] = "2/" + unicode(v.user)
  elif isinstance(v, models.AccountGroup):
    entry["type"] = "group"
    entry["key"] = "group/" + str(v.key())
    entry["name"] = v.name
    entry["sort_key"] = "1/" + unicode(v.name)
  else:
    raise AssertionError("bad value: " + str(v))
  return entry

def people_to_dicts(value):
  data = []
  for v in value:
    if isinstance(v, list):
      data.extend(people_to_dicts(v))
    elif v:
      data.append(person_to_dict(v))
  data.sort(lambda a,b: cmp(a["sort_key"], b["sort_key"]))
  return data


### User/Group Field ###

class UserGroupWidget(django.forms.widgets.Widget):
  """The widget that is used with UserGroupField."""
  def __init__(self, allow_users=True, allow_groups=True, attrs=None):
    self.attrs = {'cols': '40', 'rows': '10'}
    self.allow_users = allow_users
    self.allow_groups = allow_groups
    if attrs:
      self.attrs.update(attrs)

  def render(self, name, value, attrs=None):
    if value is None:
      value = []
    return safestring.mark_safe(
        u"""
        <div id="%(name)s_mom"></div>
        <script>
          UserGroupField_insertField(document.getElementById('%(name)s_mom'),
              '%(name)s', %(allow_users)s, %(allow_groups)s, %(initial)s);
        </script>
        """ % { "name":name,
                "initial":self._render_initial_js(value),
                "allow_users": ("true" if self.allow_users else "false"),
                "allow_groups": ("true" if self.allow_groups else "false"),
              })

  def _render_initial_js(self, value):
    data = people_to_dicts(value)
    return "[%s]" % ','.join(map(simplejson.dumps, data))

  def value_from_datadict(self, data, files, name):
    return data.getlist(name + "_keys")


class UserGroupField(django.forms.fields.Field):
  """A Field that picks a list of users and groups."""

  def __init__(self, *args, **kwargs):
    self.allow_users = kwargs.pop("allow_users", True)
    self.allow_groups = kwargs.pop("allow_groups", True)
    self.widget = UserGroupWidget(self.allow_users, self.allow_groups)
    super(UserGroupField, self).__init__(*args, **kwargs)

  def clean(self, data, initial=None):
    def get_correct_model(key):
      (type,id) = key.split("/", 1)
      if id:
        try:
          if type == "user":
            return models.Account.get_account_for_email(id)
          elif type == "group":
            return models.AccountGroup.get(id)
        except db.BadKeyError, v:
          pass
      raise forms.ValidationError("invalid key")
    keys = data
    result = [get_correct_model(key) for key in keys]
    super(UserGroupField, self).clean(initial or result)
    return result

  @classmethod
  def get_users(cls, cleaned):
    """Returns the users, given the cleaned data from the form.

    e.g.
    model_obj.usrs = fields.UserGroupField.get_users(form.cleaned_data['field'])
    """
    return [x.user for x in cleaned if isinstance(x, models.Account)]

  @classmethod
  def get_groups(cls, cleaned):
    """Returns the groups, given the cleaned data from the form.

    e.g.
    groups = fields.UserGroupField.get_users(form.cleaned_data['field'])
    """
    return [x for x in cleaned if isinstance(x, models.AccountGroup)]

  @classmethod
  def get_group_keys(cls, cleaned):
    """Returns keys for the groups, given the cleaned data from the form.

    e.g.
    groups = fields.UserGroupField.get_users(form.cleaned_data['field'])
    """
    return [x.key() for x in cleaned if isinstance(x, models.AccountGroup)]

  @classmethod
  def get_user_and_group_keys(cls, cleaned):
    """Returns the users and the groups for the cleaned data from the form.

    e.g.
    (model_obj.users,model_obj.groups
        ) = fields.UserGroupField.get_user_and_group_keys(
        form.cleaned_data['field'])
    """
    return (UserGroupField.get_users(cleaned),
            UserGroupField.get_group_keys(cleaned))

  @classmethod
  def field_value_for_keys(cls, users=[], groups=[]):
    """Return the value suitable for this field from a list keys.

    e.g.
    form_initial_values['field'] = fields.UserGroupField.field_value_for_keys(
              users, group_keys)
    """
    return ([models.AccountGroup.get(k) for k in groups]
          + [models.Account.get_account_for_user(u) for u in users])
  

### Approvers Field ###

class ApproversWidget(django.forms.widgets.Widget):
  """The widget for ApproversField"""

  def __init__(self, allow_users=True, allow_groups=True, attrs=None,
        approvers=None, verifiers=None):
    self.attrs = {'cols': '40', 'rows': '10'}
    if attrs:
      self.attrs.update(attrs)
    self.approvers = approvers or UserGroupWidget();
    self.verifiers = verifiers or UserGroupWidget();

  def render(self, name, value, attrs=None):
    if value is None:
      value = []
    styles = self.attrs.get("styles", {})
    return safestring.mark_safe(
        u"""
        <div id="%(name)s_mom"></div>
        <script>
          ApproversField_insertField('%(name)s_mom', '%(name)s', %(initial)s,
              %(styles)s);
        </script>
        """ % {
          "name": name,
          "initial": self._render_initial_js(name, value),
          "styles": simplejson.dumps(styles),
        })


  def _render_initial_js(self, name, value):
    data = []
    index = 0
    for v in value:
      # BEGIN DEBUGGING
      key = "initial_%d" % index
      files = v["files"]
      bad_files = v.get("bad_files", [])
      approvers = v["approvers"]
      verifiers = v["verifiers"]
      # END DEBUGGING
      entry = {}
      entry["key"] = "initial_%d" % index
      entry["files"] = encoding.force_unicode("\n".join(files))
      entry["bad_files"] = map(encoding.force_unicode, bad_files)
      entry["approvers"] = people_to_dicts(approvers)
      entry["verifiers"] = people_to_dicts(verifiers)
      data.append(entry)
      index = index + 1
    rows = []
    for entry in data:
      rows.append(simplejson.dumps(entry))
    return "[%s]" % ','.join(rows)
    

  def value_from_datadict(self, data, files, name):
    result = []
    keys = data.getlist(name + "_keys")
    for key in keys:
      field_key = "%s_%s" % (name, key)
      files = filter(string.strip, data.get(field_key + "_files").splitlines())
      bad_files = []
      for f in files:
        if not models.ApprovalRight.validate_file(f):
          err = True
          bad_files.append(f)
      approvers = self.approvers.value_from_datadict(data, files,
          field_key + "_approvers")
      verifiers = self.verifiers.value_from_datadict(data, files,
          field_key + "_verifiers")
      result.append({
              "key": key,
              "files": files,
              "bad_files": bad_files,
              "approvers": approvers,
              "verifiers": verifiers,
          })
    return result


class ApproversField(django.forms.fields.Field):
  """A Field to pick which users/groups can edit which field"""
  approvers = UserGroupField();
  verifiers = UserGroupField();
  widget = ApproversWidget(approvers=approvers.widget,
      verifiers=verifiers.widget, attrs={"styles": {
        "approval": "approval"
      }})

  def __init__(self, *args, **kwargs):
    super(ApproversField, self).__init__(*args, **kwargs)

  def clean(self, data, initial=None):
    result = []
    err = False
    for d in data:
      files = d["files"]
      if len(d["bad_files"]) > 0:
        err = True
      approvers = self.approvers.clean(d["approvers"])
      verifiers = self.verifiers.clean(d["verifiers"])
      result.append({"files": files, "approvers": approvers,
          "verifiers": verifiers})
    if False:
      for r in result:
        logging.info("clean: files=" + str(r["files"]))
        logging.info("   approvers=" + str(r["approvers"]))
        logging.info("   verifiers=" + str(r["verifiers"]))
    super(ApproversField, self).clean(initial or result)
    if err:
        raise forms.ValidationError("invalid files")
    return result

### Project field ###

class ProjectSelectWidget(django.forms.widgets.Widget):
  """A widget that lets a user pick a set of projects."""
  def __init__(self, attrs=None):
    super(ProjectSelectWidget, self).__init__(attrs)
    if attrs:
      self.attrs.update(attrs)

  def render(self, name, value, attrs=None):
    if value is None:
      value = []
    project_list = [{'name': p.name, 'key': str(p.key())}
                    for p in models.Project.get_all_projects()]
    return safestring.mark_safe(
        u"""
        <div id="%(name)s_mom"></div>
        <script>
          ProjectField_insertField(document.getElementById('%(name)s_mom'),
              '%(name)s', %(project_list)s, %(initial)s);
        </script>
        """ % { "name": name,
                "project_list": self._render_js_list(project_list),
                "initial": self._render_js_list([str(v) for v in value]),
              })

  def _render_js_list(self, value):
    return "[%s]" % ','.join(map(simplejson.dumps, value))

  def value_from_datadict(self, data, files, name):
    return set([v.strip() for v in data.getlist(name) if len(v.strip()) > 0])

class ProjectSelectField(django.forms.fields.Field):
  """A Field that lets a user pick a set of projects."""

  def __init__(self, *args, **kwargs):
    self.widget = ProjectSelectWidget()
    super(ProjectSelectField, self).__init__(*args, **kwargs)

  def clean(self, data, initial=None):
    objects = models.Project.get(data)
    result = [o.key() for o in objects if o]
    super(ProjectSelectField, self).clean(initial or result)
    return result


