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

"""Project related views and functions.

This requires Django 0.97.pre.
"""


# Python imports
import os
import cgi
import random
import re
import logging
import binascii
import datetime
import urllib
import md5
from xml.etree import ElementTree
from cStringIO import StringIO

# AppEngine imports
from google.appengine.api import mail
from google.appengine.api import memcache
from google.appengine.api import users
from google.appengine.api import urlfetch
from google.appengine.ext import db
from google.appengine.ext.db import djangoforms

# Django imports
# TODO(guido): Don't import classes/functions directly.
from django import http
from django import forms
from django.http import HttpResponse, HttpResponseRedirect
from django.http import HttpResponseForbidden, HttpResponseNotFound
from django.shortcuts import render_to_response
from django.utils import simplejson
from django.forms import formsets

# Local imports
import models
import engine
import library
import patching
import fields
import views
from view_util import *

## Project CRUD ##

def _assert_project_and_owner(request, project):
  "If the current user is not an owner of this project or an admin, give a 404."
  if not project:
    raise http.Http404()
  if not request.user or not ((project.key() in [
          p.key() for p in request.projects_owned_by_user])
      or request.user_is_admin):
    raise http.Http404()

@project_owner_or_admin_required
def project_list(request):
  """/admin/projects - list of all projects"""
  if request.user_is_admin:
    projects = models.Project.get_all_projects()
  else:
    projects = models.Project.projects_owned_by_user(request.user)
    logging.info("project_list projects=" + str(projects))
    if not projects:
      raise http.Http404()
  return respond(request, 'admin_projects.html', {'projects': projects})

def _keys_for(values):
  return [x.key() for x in values]

def _users_to_accounts(users):
  return map(models.Account.get_account_for_user, users)

def _combine_users_and_groups(users, groupKeys):
  return models.AccountGroup.get(groupKeys) + _users_to_accounts(users)

def _field_to_approval_right(cleaned):
  result = models.ApprovalRight()
  result.files = cleaned["files"]
  (result.approvers_users,result.approvers_groups
      ) = fields.UserGroupField.get_user_and_group_keys(cleaned["approvers"])
  (result.verifiers_users,result.verifiers_groups
      ) = fields.UserGroupField.get_user_and_group_keys(cleaned["verifiers"])
  result.put()
  return result

def _approval_right_to_field(key):
  val = models.ApprovalRight.get(key)
  if not val:
    raise KeyError("no ApprovalRight for key: " + str(key))
  return {
      'files': val.files,
      'approvers': _combine_users_and_groups(val.approvers_users,
                      val.approvers_groups),
      'verifiers': _combine_users_and_groups(val.verifiers_users,
                      val.verifiers_groups),
    }

class AdminProjectForm(BaseForm):
  _template = 'admin_project.html'

  name = forms.CharField()
  comment = forms.CharField(required=False,
                            max_length=10000,
                            widget=forms.Textarea(attrs={'cols': 60}))
  owners = fields.UserGroupField()
  code_reviews = fields.ApproversField()

  @classmethod
  def _init(cls, project):
     owners = fields.UserGroupField.field_value_for_keys(
                project.owners_users,
                project.owners_groups),
     return {'initial': {'name': project.name,
             'comment': project.comment,
             'owners': owners,
             'code_reviews': map(_approval_right_to_field,
                                 project.code_reviews),
            }}

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

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

    if self.is_valid():
      project.name = new_name
      project.comment = cd['comment']
      project.owners_users, project.owners_groups = \
        fields.UserGroupField.get_user_and_group_keys(cd['owners'])
      project.set_code_reviews(_keys_for(map(_field_to_approval_right,
                                         cd['code_reviews'])))
      project.put()

def project_edit(request, name):
  """/admin/project/project - edit this project"""
  project = models.Project.get_project_for_name(name)
  _assert_project_and_owner(request, project)
  def done():
    return HttpResponseRedirect('/admin/projects')
  return process_form(request, AdminProjectForm, project, done,
                      {'project':project,
                       'del_url': '/admin/project_delete/%s' % project.name,
                      })

class AdminNewProjectForm(AdminProjectForm):
  @classmethod
  def _init(cls, state):
    return {'initial': {'name': '', 'comment': ''}}

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

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

    if self.is_valid():
      owners_users = fields.UserGroupField.get_users(cd['owners'])
      owners_groups = fields.UserGroupField.get_group_keys(cd['owners'])

      project = models.Project(name = name,
                               comment = cd['comment'],
                               owners_users = owners_users,
                               owners_groups = owners_groups)
      project.set_code_reviews(_keys_for(map(_field_to_approval_right,
                               cd['code_reviews'])))
      project.put()

@admin_required
def project_new(request):
  """/admin/project/GROUP - add a new project"""
  def done():
    return HttpResponseRedirect('/admin/projects')
  return process_form(request, AdminNewProjectForm, [], done)

@gae_admin_required
@xsrf_required
def project_delete(request, name):
  """/admin/project_delete/GROUP - add a new project"""
  project = models.Project.get_project_for_name(name)
  assert project
  project.remove()
  return HttpResponseRedirect('/admin/projects')


def _matches_file_pattern(pattern, files):
  """Returns whether the list of files matches the pattern"""
  for filename in files:
    if regex.match(filename):
      return True
  return False

def _is_leaf_pattern(pattern):
  """Returns whether the pattern ends with ..."""
  return not pattern.endswith("...")

def _split_rules_for_review(project):
  """Gets the approval file pattern rules for a project

  Returns:
    A tuple of:
      0 - A list of tuples of:
        0 - leaf pattern rules (rules of the form /.../xxx)
        1 - the ApprovalRight object
      1 - A list of tuples of:
        0 - directory pattern rules (rules of the form /xxx/...)
        1 - the ApprovalRight object
  """
  leaf_rules = []
  dir_rules = []

  for approval_right in project.get_code_reviews():
    for pattern in approval_right.files:
      if _is_leaf_pattern(pattern):
        leaf_rules.append((pattern, approval_right))
      else:
        dir_rules.append((pattern, approval_right))

  return (leaf_rules, dir_rules)

def _file_pattern_to_regex(pattern):
  if pattern.startswith('/'):
    pattern = pattern[1:]
  return re.compile('^%s$' % pattern.replace("...", ".*?"))

def _convert_pattern_to_regex(rules):
  return [(_file_pattern_to_regex(pattern),pattern,approval_right)
      for (pattern,approval_right) in rules]

def _flatten_rule_users(rules):
  flattened = {}
  def _flatten_approval_right(approval_right):
    if not flattened.has_key(approval_right):
      flattened[approval_right] = {
          'required': approval_right.required,
          'approvers': set([u.email() for u in approval_right.approvers()]),
          'verifiers': set([u.email() for u in approval_right.verifiers()]),
        }
    return flattened[approval_right]
  return [(regex,pattern,_flatten_approval_right(approval_right))
      for (regex,pattern,approval_right) in rules]

def _split_files_for_review(project, files):
  """Return a mapping of files to the set of users that can approve or verify
  that file.

  Returns:
    A tuple of booleans, corresponding to (can_approve, can_verify).
  """
  result = {}

  (leaf_rules, dir_rules) = _split_rules_for_review(project)

  leaf_rules = _convert_pattern_to_regex(leaf_rules)
  dir_rules = _convert_pattern_to_regex(dir_rules)

  leaf_rules = _flatten_rule_users(leaf_rules)
  dir_rules = _flatten_rule_users(dir_rules)

  for file in files:
    approvers = []
    verifiers = []
    # check leaf rules -- we want all of those that match
    for (regex,pattern,flat_approval_right) in leaf_rules:
      if _is_leaf_pattern(pattern):
        if regex.match(file):
          user_set = flat_approval_right['approvers']
          if not user_set in approvers:
            approvers.append(user_set)
          user_set = flat_approval_right['verifiers']
          if not user_set in verifiers:
            verifiers.append(user_set)
    # check dir rules -- we want all of those that match
    dir_rule_approvers = set()
    dir_rule_verifiers = set()
    for (regex,pattern,flat_approval_right) in reversed(dir_rules):
      if not _is_leaf_pattern(pattern):
        if regex.match(file):
          dir_rule_approvers |= flat_approval_right['approvers']
          dir_rule_verifiers |= flat_approval_right['verifiers']
          if flat_approval_right['required']:
            break
    if not dir_rule_approvers in approvers:
      approvers.append(dir_rule_approvers)
    if not dir_rule_verifiers in verifiers:
      verifiers.append(dir_rule_verifiers)
    # save the result
    result[file] = {
          'approvers': approvers,
          'verifiers': verifiers,
        }

  return result

def _check_users(possible, actual):
  """Return whether for each set in possible there is one entry from actual """
  for user_set in possible:
    inter = user_set.intersection(actual)
    if len(user_set.intersection(actual)) == 0:
      return False
  return True

def _match_users(possible, actual):
  """Return the users who have actually approved/verified a change"""
  matched = set()
  for user_set in possible:
    inter = user_set.intersection(actual)
    matched |= inter
  return matched

def ready_to_submit(branch, owner, reviewer_status, files):
  """Returns whether the supplied change is ready to submit.

  These are the rules for whether a change is considered ready to submit:

  1. If the project, repository or branch has code reviews turned off, then
     the change is ok.
  2. If all of the following are true, the change is ok:
    a. Either:
        i. Someone who is authorized to lgtm each file has done so.
        ii. For each file where the owner is the only approver in the list,
            there is at least one other person that has given a positive 
            score.
    b. No one who is authorized to say no has done so.

  If 'owner' can lgtm or verify a change, she is added to the respective list.

  Args:
    branch:           The branch that this change is in (a Branch object).
    owner:            The user that owns the change. (a User object).
    reviewer_status:  A map as returned by Change.get_reviewer_status()
    files:            A list of the files that are affected.

  Returns:
    A tuple containing:
      0 - whether the change is ready to submit over all,
      1 - whether it has been approved,
      2 - whether it has been denied
      3 - whether it has been verified.
      4 - A tuple of
            0 - whether the owner has lgtm rights
            1 - whether the owner has verification rights
  """

  if branch is None:
    return (False, False, False, False, (False, False))
  project = branch.project
  if not project.is_code_reviewed():
    return (True, True, False, True, (False, False))
  if not branch.is_code_reviewed():
    return (True, True, False, True, (False, False))

  approved_cnt = 0
  verified_cnt = 0
  denied_cnt = 0
  owner_auto_lgtm = False
  owner_auto_verify = False

  lgtm_emails = set([u.email() for u in reviewer_status['lgtm']])
  reject_emails = set([u.email() for u in reviewer_status['reject']])
  verified_by_emails = set([u.email() for u in reviewer_status['verified_by']])
  owner_email = owner.email()

  files_to_approve = _split_files_for_review(project, files)
  if files_to_approve:
    for (file,user_sets) in files_to_approve.iteritems():
      # check the real approvals - the owner is checked in this list
      if _check_users(user_sets['approvers'], lgtm_emails):
        approved_cnt += 1
      if _check_users(user_sets['approvers'], reject_emails):
        denied_cnt += 1
      if _check_users(user_sets['verifiers'], verified_by_emails):
        verified_cnt += 1
      # check the owner auto-approve
      if _check_users(user_sets['approvers'], [owner_email]):
        owner_auto_lgtm = True
      if _check_users(user_sets['verifiers'], [owner_email]):
        owner_auto_verify = True

    require_review = False
    approved = ((approved_cnt == len(files_to_approve))
                or (owner_auto_lgtm
                    and ((not require_review)
                          or (len(reviewer_status['yes']) > 0
                               or len(reviewer_status['lgtm']) > 0))))
    verified = verified_cnt == len(files_to_approve) or owner_auto_verify
    denied = denied_cnt > 0
  else:
    approved = False
    verified = False
    denied = False

  real_approvers = _match_users(user_sets['approvers'], lgtm_emails) 
  real_deniers = _match_users(user_sets['approvers'], reject_emails) 
  real_verifiers = _match_users(user_sets['verifiers'], verified_by_emails) 

  return {
      'can_submit': approved and verified and (not denied),
      'approved': approved,
      'denied': denied,
      'verified': verified,
      'owner_auto_lgtm': owner_auto_lgtm,
      'owner_auto_verify': owner_auto_verify,
      'real_approvers': real_approvers,
      'real_deniers': real_deniers,
      'real_verifiers': real_verifiers,
    }

def user_can_approve(user, change):
  """Returns whether the user can approve or verify this change.

  Args:
    user:   The user to test (a User object)
    branch: The branch that this change is in (a Branch object)
    files:  A list of files in question

  Returns:
    A map of 'approve' and 'verify' to booleans of whether the user
    can approve or verify at least one of these files.
  """
  # pick the files
  patchsets = list(change.patchset_set.order('id'))
  if not patchsets:
    return (False, False)
  files = patchsets[-1].filenames

  branch = change.dest_branch
  project = branch.project

  if not project.is_code_reviewed():
    return (True, True)
  files_to_approve = _split_files_for_review(project, files)
  if not files_to_approve:
    return (False, False)

  email = user.email()
  can_approve = False
  can_verify = False
  for (file,user_sets) in files_to_approve.iteritems(): 
    for user_set in user_sets["approvers"]:
      if email in user_set:
        can_approve = True
    for user_set in user_sets["verifiers"]:
      if email in user_set:
        can_verify = True
    if can_approve and can_verify:
      # short circuit
      return (True, True)

  return (can_approve, can_verify)
